Projects >> CloudStack-archive >>848ce6009772023cc9394abd631de266d2085d63

Chunk
Conflicting content
        List securityGroups = listBy(sc);
        return ((securityGroups != null) && !securityGroups.isEmpty());
    }
<<<<<<< HEAD
=======

    @Override
    public List listAvailableGroups(Long accountId, Long domainId) {
        List availableGroups = new ArrayList();
        if ((accountId != null) || (domainId != null)) {
            if (accountId != null) {
                SearchCriteria sc = createSearchCriteria();
                sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
                List accountGroups = listBy(sc);
                availableGroups.addAll(accountGroups);
            } else if (domainId != null) {
                while (domainId != null) {
                    SearchCriteria sc = createSearchCriteria();
                    sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
                    if (accountId != null) {
                        sc.addAnd("accountId", SearchCriteria.Op.NEQ, accountId); // we added the account specific ones above
                    }
                    List domainGroups = listBy(sc);
                    availableGroups.addAll(domainGroups);

                    // get the parent domain, repeat the loop
                    DomainVO domain = _domainDao.findById(domainId);
                    domainId = domain.getParent();
                }
            }
        }
        return availableGroups;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
        List securityGroups = listBy(sc);
        return ((securityGroups != null) && !securityGroups.isEmpty());
    }
}
File
SecurityGroupDaoImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
        List securityGroups = listBy(sc);
        return ((securityGroups != null) && !securityGroups.isEmpty());
<<<<<<< HEAD
=======
    }

    @Override
    public List listAvailableGroups(Long accountId, Long domainId) {
        List availableGroups = new ArrayList();
        if ((accountId != null) || (domainId != null)) {
            if (accountId != null) {
                SearchCriteria sc = createSearchCriteria();
                sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
                List accountGroups = listBy(sc);
                availableGroups.addAll(accountGroups);
            } else if (domainId != null) {
                while (domainId != null) {
                    SearchCriteria sc = createSearchCriteria();
                    sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
                    if (accountId != null) {
                        sc.addAnd("accountId", SearchCriteria.Op.NEQ, accountId); // we added the account specific ones above
                    }
                    List domainGroups = listBy(sc);
                    availableGroups.addAll(domainGroups);

                    // get the parent domain, repeat the loop
                    DomainVO domain = _domainDao.findById(domainId);
                    domainId = domain.getParent();
                }
            }
        }
        return availableGroups;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }

	@Override
Solution content
        List securityGroups = listBy(sc);
        return ((securityGroups != null) && !securityGroups.isEmpty());
    }

	@Override
File
NetworkGroupDaoImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
If statement
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content

        return listBy(sc, searchFilter);
    }
<<<<<<< HEAD
=======

    @Override
    public List listNetworkGroupRulesByDomain(long domainId, boolean recursive) {

        if (_domainDao == null) {
            ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
            _domainDao = locator.getDao(DomainDao.class);
            DomainSearch = createSearchBuilder();
            DomainSearch.and("domainId", DomainSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            DomainSearch.join("domainSearch", domainSearch, DomainSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
            DomainSearch.done();
        }

        Filter searchFilter = new Filter(NetworkGroupRulesVO.class, "id", true, null, null);
        SearchCriteria sc = DomainSearch.create();

        if (!recursive) {
            sc.setParameters("domainId", domainId);
        }

        DomainVO domain = _domainDao.findById(domainId);
        if (domain != null) {
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return listBy(sc, searchFilter);
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
        return listBy(sc, searchFilter);
    }
}
File
NetworkGroupRulesDaoImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
        sc.setParameters("hostAddress", host);
        sc.setParameters("path", path);
        
<<<<<<< HEAD
        return listActiveBy(sc);
=======
        return listIncludingRemovedBy(sc);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	}
	
	public StoragePoolVO listById(Integer id)
Solution content
        sc.setParameters("hostAddress", host);
        sc.setParameters("path", path);
        
        return listIncludingRemovedBy(sc);
	}
	
	public StoragePoolVO listById(Integer id)
File
StoragePoolDaoImpl.java
Developer's decision
Version 2
Kind of conflict
Method invocation
Return statement
Chunk
Conflicting content
        DestroySearch.and("updateTime", DestroySearch.entity().getUpdateTime(), SearchCriteria.Op.LT);
        DestroySearch.done();

<<<<<<< HEAD
        ZoneAccountGuestIpSearch = createSearchBuilder();
        ZoneAccountGuestIpSearch.and("dataCenterId", ZoneAccountGuestIpSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        ZoneAccountGuestIpSearch.and("accountId", ZoneAccountGuestIpSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        ZoneAccountGuestIpSearch.and("guestIpAddress", ZoneAccountGuestIpSearch.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        ZoneAccountGuestIpSearch.done();

=======
        
        
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        _updateTimeAttr = _allAttributes.get("updateTime");
        assert _updateTimeAttr != null : "Couldn't get this updateTime attribute";
    }
Solution content
        DestroySearch.and("updateTime", DestroySearch.entity().getUpdateTime(), SearchCriteria.Op.LT);
        DestroySearch.done();

        ZoneAccountGuestIpSearch = createSearchBuilder();
        ZoneAccountGuestIpSearch.and("dataCenterId", ZoneAccountGuestIpSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        ZoneAccountGuestIpSearch.and("accountId", ZoneAccountGuestIpSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        ZoneAccountGuestIpSearch.and("guestIpAddress", ZoneAccountGuestIpSearch.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        ZoneAccountGuestIpSearch.done();

        _updateTimeAttr = _allAttributes.get("updateTime");
        assert _updateTimeAttr != null : "Couldn't get this updateTime attribute";
    }
File
UserVmDaoImpl.java
Developer's decision
Version 1
Kind of conflict
Attribute
Method invocation
Chunk
Conflicting content
    public boolean reconnect(final long hostId) throws AgentUnavailableException;
    public HostVO reconnectHost(ReconnectHostCmd cmd) throws AgentUnavailableException;
    
<<<<<<< HEAD:server/src/com/cloud/agent/manager/AgentManager.java
    public List discoverHosts(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password) throws DiscoveryException, InvalidParameterValueException;
    public List discoverHosts(AddHostCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
    public List discoverHosts(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
=======
    public List discoverHosts(long dcId, Long podId, Long clusterId, URI url, String username, String password) throws DiscoveryException;

	Answer easySend(Long hostId, Command cmd, int timeout);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590:core/src/com/cloud/agent/AgentManager.java
}
Solution content
    public boolean reconnect(final long hostId) throws AgentUnavailableException;
    public HostVO reconnectHost(ReconnectHostCmd cmd) throws AgentUnavailableException;
    
    public List discoverHosts(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password) throws DiscoveryException, InvalidParameterValueException;
    public List discoverHosts(AddHostCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
    public List discoverHosts(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;

	Answer easySend(Long hostId, Command cmd, int timeout);
}
File
AgentManager.java
Developer's decision
Combination
Kind of conflict
Method interface
Chunk
Conflicting content
import com.cloud.resource.ServerResource;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.GuestOSCategoryVO;
<<<<<<< HEAD
import com.cloud.storage.StorageManager;
=======
import com.cloud.storage.Storage;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateVO;
Solution content
import com.cloud.resource.ServerResource;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateVO;
File
AgentManagerImpl.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
            try {
        Enumeration en = _discoverers.enumeration();
        while (en.hasMoreElements()) {
            Discoverer discoverer = en.nextElement();
<<<<<<< HEAD
            Map> resources = discoverer.find(dcId, podId, clusterId, uri, username, password);
=======
            Map> resources = null;
            
            	resources = discoverer.find(dcId, podId, clusterId, url, username, password);
            } catch(Exception e) {
            	s_logger.info("Exception in host discovery process with discoverer: " + discoverer.getName() + ", skip to another discoverer if there is any");
            }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            if (resources != null) {
                for (Map.Entry> entry : resources.entrySet()) {
                    ServerResource resource = entry.getKey();
Solution content
        Enumeration en = _discoverers.enumeration();
        while (en.hasMoreElements()) {
            Discoverer discoverer = en.nextElement();
            Map> resources = null;
            
            try {
            	resources = discoverer.find(dcId, podId, clusterId, uri, username, password);
            } catch(Exception e) {
            	s_logger.info("Exception in host discovery process with discoverer: " + discoverer.getName() + ", skip to another discoverer if there is any");
            }
            if (resources != null) {
                for (Map.Entry> entry : resources.entrySet()) {
                    ServerResource resource = entry.getKey();
File
AgentManagerImpl.java
Developer's decision
Manual
Kind of conflict
Method invocation
Try statement
Variable
Chunk
Conflicting content
        }
    }
    
<<<<<<< HEAD
    public HostVO updateHost(UpdateHostCmd cmd) throws InvalidParameterValueException{
    	Long hostId = cmd.getId();
    	Long guestOSCategoryId = cmd.getOsCategoryId();
=======
    @Override
    public void updateHost(long hostId, long guestOSCategoryId) {
    	GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId);
    	Map hostDetails = _hostDetailsDao.findDetails(hostId);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	
    	if (guestOSCategoryId != null) {
Solution content
        }
    }

    @Override
    public HostVO updateHost(UpdateHostCmd cmd) throws InvalidParameterValueException{
    	Long hostId = cmd.getId();
    	Long guestOSCategoryId = cmd.getOsCategoryId();
    	
    	if (guestOSCategoryId != null) {
File
AgentManagerImpl.java
Developer's decision
Combination
Kind of conflict
Annotation
Method invocation
Method signature
Variable
Chunk
Conflicting content
                    }
    }

    private boolean dataCenterAndPodHasEnoughCapacity(long dataCenterId, long podId, long capacityNeeded, short capacityType, long[] hostCandidate) {
<<<<<<< HEAD
        if (m_capacityCheckLock.lock(120)) { // 2 minutes
            try {
                SearchCriteria sc = _capacityDao.createSearchCriteria();
                sc.addAnd("capacityType", SearchCriteria.Op.EQ, capacityType);
                sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId);
                sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
                List capacities = _capacityDao.search(sc, null);
                boolean enoughCapacity = false;
                if (capacities != null) {
                    for (CapacityVO capacity : capacities) {
                    	if(capacityType == CapacityVO.CAPACITY_TYPE_CPU || capacityType == CapacityVO.CAPACITY_TYPE_MEMORY) {
                    		//
                    		// for CPU/Memory, we now switch to static allocation
                    		//
	                        if ((capacity.getTotalCapacity() -
	                        	calcHostAllocatedCpuMemoryCapacity(capacity.getHostOrPoolId(), capacityType)) >= capacityNeeded) {

	                            hostCandidate[0] = capacity.getHostOrPoolId();
	                            enoughCapacity = true;
	                            break;
	                        }
                    	} else {
	                        if ((capacity.getTotalCapacity() - capacity.getUsedCapacity()) >= capacityNeeded) {
	                            hostCandidate[0] = capacity.getHostOrPoolId();
	                            enoughCapacity = true;
	                            break;
	                        }
                    	}
=======
        List capacities = null;
        
        SearchCriteria sc = _capacityDao.createSearchCriteria();
        sc.addAnd("capacityType", SearchCriteria.Op.EQ, capacityType);
        sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId);
        sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        s_logger.trace("Executing search");
        capacities = _capacityDao.search(sc, null);
        s_logger.trace("Done with a search");

        boolean enoughCapacity = false;
        if (capacities != null) {
            for (CapacityVO capacity : capacities) {
                if(capacityType == CapacityVO.CAPACITY_TYPE_CPU || capacityType == CapacityVO.CAPACITY_TYPE_MEMORY) {
                    //
                    // for CPU/Memory, we now switch to static allocation
                    //
                    if ((capacity.getTotalCapacity() -
                            calcHostAllocatedCpuMemoryCapacity(capacity.getHostOrPoolId(), capacityType)) >= capacityNeeded) {

                        hostCandidate[0] = capacity.getHostOrPoolId();
                        enoughCapacity = true;
                        break;
                    }
                } else {
                    if ((capacity.getTotalCapacity() - capacity.getUsedCapacity()) >= capacityNeeded) {
                        hostCandidate[0] = capacity.getHostOrPoolId();
                        enoughCapacity = true;
                        break;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
                }
            }
Solution content
    }

    private boolean dataCenterAndPodHasEnoughCapacity(long dataCenterId, long podId, long capacityNeeded, short capacityType, long[] hostCandidate) {
        List capacities = null;
        
        SearchCriteria sc = _capacityDao.createSearchCriteria();
        sc.addAnd("capacityType", SearchCriteria.Op.EQ, capacityType);
        sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId);
        sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        s_logger.trace("Executing search");
        capacities = _capacityDao.search(sc, null);
        s_logger.trace("Done with a search");

        boolean enoughCapacity = false;
        if (capacities != null) {
            for (CapacityVO capacity : capacities) {
                if(capacityType == CapacityVO.CAPACITY_TYPE_CPU || capacityType == CapacityVO.CAPACITY_TYPE_MEMORY) {
                    //
                    // for CPU/Memory, we now switch to static allocation
                    //
                    if ((capacity.getTotalCapacity() -
                            calcHostAllocatedCpuMemoryCapacity(capacity.getHostOrPoolId(), capacityType)) >= capacityNeeded) {

                        hostCandidate[0] = capacity.getHostOrPoolId();
                        enoughCapacity = true;
                        break;
                    }
                } else {
                    if ((capacity.getTotalCapacity() - capacity.getUsedCapacity()) >= capacityNeeded) {
                        hostCandidate[0] = capacity.getHostOrPoolId();
                        enoughCapacity = true;
                        break;
                    }
                }
            }
File
UserConcentratedAllocator.java
Developer's decision
Version 2
Kind of conflict
Array access
Break statement
Comment
For statement
If statement
Method invocation
Try statement
Variable
Chunk
Conflicting content
            	systemVmUseLocalStorage = "false";            

            // set the userId and account object for everyone
<<<<<<< HEAD
            session.setAttribute("userid", userAcct.getId().toString());
            session.setAttribute("username", userAcct.getUsername());
            session.setAttribute("firstname", userAcct.getFirstname());
            session.setAttribute("lastname", userAcct.getLastname());
            session.setAttribute("accountobj", account);
            session.setAttribute("account", account.getAccountName());
            session.setAttribute("domainid", account.getDomainId().toString());
            session.setAttribute("type", Short.valueOf(account.getType()).toString());
            session.setAttribute("networktype", networkType);
            session.setAttribute("hypervisortype", hypervisorType);
            session.setAttribute("directattachnetworkgroupsenabled", directAttachNetworkGroupsEnabled);
            session.setAttribute("directattacheduntaggedenabled", directAttachedUntaggedEnabled);
            session.setAttribute("systemvmuselocalstorage", systemVmUseLocalStorage);
=======
            loginParams.add(new Pair(BaseCmd.Properties.USER_ID.getName(), userAcct.getId().toString()));
            loginParams.add(new Pair(BaseCmd.Properties.USERNAME.getName(), userAcct.getUsername()));
            loginParams.add(new Pair(BaseCmd.Properties.FIRSTNAME.getName(), userAcct.getFirstname()));
            loginParams.add(new Pair(BaseCmd.Properties.LASTNAME.getName(), userAcct.getLastname()));
            loginParams.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ.getName(), account));
            loginParams.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), account.getAccountName()));
            loginParams.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), Long.toString(account.getDomainId())));           
            loginParams.add(new Pair(BaseCmd.Properties.TYPE.getName(), Short.valueOf(account.getType()).toString()));
            loginParams.add(new Pair(BaseCmd.Properties.NETWORK_TYPE.getName(), networkType));
            loginParams.add(new Pair(BaseCmd.Properties.HYPERVISOR_TYPE.getName(), hypervisorType));
            loginParams.add(new Pair(BaseCmd.Properties.DIRECT_ATTACH_NETWORK_GROUPS_ENABLED.getName(), directAttachNetworkGroupsEnabled));
            loginParams.add(new Pair(BaseCmd.Properties.DIRECT_ATTACHED_UNTAGGED_ENABLED.getName(), directAttachedUntaggedEnabled));
            loginParams.add(new Pair(BaseCmd.Properties.SYSTEM_VM_USE_LOCAL_STORAGE.getName(), systemVmUseLocalStorage));
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            if (timezone != null) {
                session.setAttribute("timezone", timezone);
                session.setAttribute("timezoneoffset", Float.valueOf(offsetInHrs).toString());
Solution content
            	systemVmUseLocalStorage = "false";            

            // set the userId and account object for everyone
            session.setAttribute("userid", userAcct.getId().toString());
            session.setAttribute("username", userAcct.getUsername());
            session.setAttribute("firstname", userAcct.getFirstname());
            session.setAttribute("lastname", userAcct.getLastname());
            session.setAttribute("accountobj", account);
            session.setAttribute("account", account.getAccountName());
            session.setAttribute("domainid", account.getDomainId());
            session.setAttribute("type", Short.valueOf(account.getType()).toString());
            session.setAttribute("networktype", networkType);
            session.setAttribute("hypervisortype", hypervisorType);
            session.setAttribute("directattachnetworkgroupsenabled", directAttachNetworkGroupsEnabled);
            session.setAttribute("directattacheduntaggedenabled", directAttachedUntaggedEnabled);
            session.setAttribute("systemvmuselocalstorage", systemVmUseLocalStorage);

            if (timezone != null) {
                session.setAttribute("timezone", timezone);
                session.setAttribute("timezoneoffset", Float.valueOf(offsetInHrs).toString());
File
ApiServer.java
Developer's decision
Manual
Kind of conflict
Method invocation
Chunk
Conflicting content
    public static final DateFormat INPUT_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    private static final DateFormat _outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

<<<<<<< HEAD
    private Object _responseObject = null;
=======
    public enum Properties {
        ACCOUNT("account", BaseCmd.TYPE_STRING, "account"),
        ACCOUNT_ID("accountid", BaseCmd.TYPE_LONG, "accountId"),
        ACCOUNT_NAMES("accounts", BaseCmd.TYPE_STRING, "accounts"),
        ACCOUNT_TYPE("accounttype", BaseCmd.TYPE_LONG, "accounttype"),
        ACCOUNT_OBJ("accountobj", BaseCmd.TYPE_OBJECT, "accountobj"),
        ACTIVE_VIEWER_SESSIONS("activeviewersessions", BaseCmd.TYPE_INT, "activeviewersessions"),
        ADD("add", BaseCmd.TYPE_BOOLEAN, "add"),
        ALGORITHM("algorithm", BaseCmd.TYPE_STRING, "algorithm"),
        ALLOCATED("allocated", BaseCmd.TYPE_DATE, "allocated"),
        ALLOCATED_ONLY("allocatedonly", BaseCmd.TYPE_BOOLEAN, "allocatedOnly"),
        API_KEY("apikey", BaseCmd.TYPE_STRING, "apiKey"),
        APPLIED("applied", BaseCmd.TYPE_BOOLEAN, "applied"),
        AVAILABLE("available", BaseCmd.TYPE_BOOLEAN, "available"),
        AVERAGE_LOAD("averageload",BaseCmd.TYPE_LONG,"averageLoad"),
        ASSIGN_DATE("assigneddate", BaseCmd.TYPE_DATE, "assigneddate"),
        BITS("bits", BaseCmd.TYPE_INT, "bits"),
        BOOTABLE("bootable", BaseCmd.TYPE_BOOLEAN, "bootable"),
        BYTES_RECEIVED("receivedbytes", BaseCmd.TYPE_LONG, "receivedbytes"),
        BYTES_SENT("sentbytes", BaseCmd.TYPE_LONG, "sentbytes"),
        CAPABILITIES("capabilities", BaseCmd.TYPE_STRING, "capabilities"),
        CAPACITY_TOTAL("capacitytotal", BaseCmd.TYPE_LONG, "capacitytotal"),
        CAPACITY_USED("capacityused", BaseCmd.TYPE_LONG, "capacityused"),
        CATEGORY("category", BaseCmd.TYPE_STRING, "category"),
        CLEANUP("cleanup", BaseCmd.TYPE_BOOLEAN, "cleanup"),
        CLOUD_IDENTIFIER("cloudidentifier", BaseCmd.TYPE_STRING, "cloudIdentifier"),
        CLUSTER_ID("clusterid", BaseCmd.TYPE_LONG, "clusterid"),
        CLUSTER_NAME("clustername", BaseCmd.TYPE_STRING, "clustername"),
        CMD("cmd", BaseCmd.TYPE_STRING, "cmd"),
        COMPONENT("component", BaseCmd.TYPE_STRING, "component"),
        CONSOLE_HOST("consolehost", BaseCmd.TYPE_STRING, "consoleHost"),
        CONSOLE_IMAGE_URL("consoleimageurl", BaseCmd.TYPE_STRING, "consoleImageUrl"),
        CONSOLE_PASSWORD("consolepassword", BaseCmd.TYPE_STRING, "consolePassword"),
        CONSOLE_PORT("consoleport", BaseCmd.TYPE_STRING, "consolePort"),
        CONSOLE_PROXY_HOST("consoleproxyhost", BaseCmd.TYPE_STRING, "consoleProxyHost"),
        CONSOLE_PROXY_PORT("consoleproxyport", BaseCmd.TYPE_STRING, "consoleProxyPort"),
        CONSOLE_PROXY_SSLENABLED("consoleproxysslenabled", BaseCmd.TYPE_BOOLEAN, "consoleProxySslEnabled"),
        CIDR("cidr", BaseCmd.TYPE_STRING, "cidr"),
        CIDR_ADDRESS("cidraddress", BaseCmd.TYPE_STRING, "CidrAddress"),
        CIDR_LIST("cidrlist", BaseCmd.TYPE_STRING, "cidrList"),
        GUEST_IP_ADDRESS("guestipaddress", BaseCmd.TYPE_STRING, "guestIpAddress"),
        GUEST_MAC_ADDRESS("guestmacaddress", BaseCmd.TYPE_STRING, "guestMacAddress"),
        GUEST_NETMASK("guestnetmask", BaseCmd.TYPE_STRING, "guestNetmask"),
        GUEST_CIDR_ADDRESS("guestcidraddress", BaseCmd.TYPE_STRING, "GuestCidrAddress"),
        CIDR_SIZE("cidrsize", BaseCmd.TYPE_LONG, "CidrSize"),
        CPU_NUMBER("cpunumber", BaseCmd.TYPE_LONG, "CpuNumber"),
        CPU_SPEED("cpuspeed", BaseCmd.TYPE_LONG, "CpuSpeed"),
        CPU_ALLOCATED("cpuallocated", BaseCmd.TYPE_LONG, "cpuallocated"),
        CPU_USED("cpuused", BaseCmd.TYPE_LONG, "cpuused"),
        CREATED("created", BaseCmd.TYPE_DATE, "created"),
        ATTACHED("attached", BaseCmd.TYPE_DATE, "attached"),
        CROSS_ZONES("crossZones", BaseCmd.TYPE_BOOLEAN, "crosszones"),
        DAILY_MAX("dailymax", BaseCmd.TYPE_INT, "dailyMax"),
        DATA_DISK_OFFERING_ID("datadiskofferingid", BaseCmd.TYPE_LONG, "dataDiskOfferingId"),
        DATA_DISK_OFFERING_NAME("datadiskofferingname", BaseCmd.TYPE_LONG, "dataDiskOfferingName"),
        DESCRIPTION("description", BaseCmd.TYPE_STRING, "description"),
        DETAILS("details", BaseCmd.TYPE_OBJECT_MAP, "details"),
        DEVICE_NAME("devicename", BaseCmd.TYPE_STRING, "deviceName"),
        DIRECT_ATTACH_NETWORK_GROUPS_ENABLED("directattachnetworkgroupsenabled", BaseCmd.TYPE_BOOLEAN, "directAttachNetworkGroupsEnabled"),
        DIRECT_ATTACHED_UNTAGGED_ENABLED("directattacheduntaggedenabled", BaseCmd.TYPE_BOOLEAN, "directAttachedUntaggedEnabled"),
        SYSTEM_VM_USE_LOCAL_STORAGE("systemvmuselocalstorage", BaseCmd.TYPE_BOOLEAN, "systemVmUseLocalStorage"),
        DISCONNECTED("disconnected", BaseCmd.TYPE_DATE, "disconnected"),
        DISPLAY_TEXT("displaytext", BaseCmd.TYPE_STRING, "displayText"),
        DISK_OFFERING_DISPLAY_TEXT("diskofferingdisplaytext", BaseCmd.TYPE_LONG, "diskOfferingDisplayText"),
        DISK_OFFERING_ID("diskofferingid", BaseCmd.TYPE_LONG, "diskOfferingId"),
        DISK_OFFERING_NAME("diskofferingname", BaseCmd.TYPE_LONG, "diskOfferingName"),
        DISK_SIZE("disksize", BaseCmd.TYPE_LONG, "diskSize"),
        DISK_SIZE_ALLOCATED("disksizeallocated", BaseCmd.TYPE_LONG, "disksizeallocated"),
        DISK_SIZE_TOTAL("disksizetotal", BaseCmd.TYPE_LONG, "disksizetotal"),
        DISPLAY_NAME("displayname", BaseCmd.TYPE_STRING, "displayname"),
        DNS1("dns1", BaseCmd.TYPE_STRING, "dns1"),
        DNS2("dns2", BaseCmd.TYPE_STRING, "dns2"),
        DOMAIN("domain", BaseCmd.TYPE_STRING, "domain"),
        DOMAIN_ID("domainid", BaseCmd.TYPE_LONG, "domainId"),
        DOMAIN_LEVEL("level", BaseCmd.TYPE_INT, "level"),
        DEST_ZONE_ID("destzoneid", BaseCmd.TYPE_LONG, "destZoneId"),
        DURATION("duration", BaseCmd.TYPE_INT, "duration"),
        EMAIL("email", BaseCmd.TYPE_STRING, "email"),
        END_DATE("enddate", BaseCmd.TYPE_DATE, "endDate"),
        END_IP("endip", BaseCmd.TYPE_STRING, "endIp"),
        END_PORT("endport", BaseCmd.TYPE_INT, "endPort"),
        END_VLAN("endvlan", BaseCmd.TYPE_LONG, "endvlan"),
        ENTRY_TIME("entrytime", BaseCmd.TYPE_INT, "entryTime"),
        EVENTS("events",BaseCmd.TYPE_STRING,"events"),
        FIREWALL_ENABLE_PASSWORD("firewallenablepassword", BaseCmd.TYPE_STRING, "firewallEnablePassword"),
        FIREWALL_IP("firewallip", BaseCmd.TYPE_STRING, "firewallIp"),
        FIREWALL_PASSWORD("firewallpassword", BaseCmd.TYPE_STRING, "firewallPassword"),
        FIREWALL_RULE_ID("firewallruleid", BaseCmd.TYPE_LONG, "firewallRuleId"),
        FIREWALL_USER("firewalluser", BaseCmd.TYPE_STRING, "firewallUser"),
        FIRSTNAME("firstname", BaseCmd.TYPE_STRING, "firstname"),
        FOR_VIRTUAL_NETWORK("forvirtualnetwork", BaseCmd.TYPE_BOOLEAN, "forVirtualNetwork"),
        FORMAT("format", BaseCmd.TYPE_STRING, "format"),
        GATEWAY("gateway", BaseCmd.TYPE_STRING, "gateway"),
        GROUP("group", BaseCmd.TYPE_STRING, "group"),
        GROUP_ID("groupid", BaseCmd.TYPE_LONG, "groupId"),
        GROUP_IDS("groupids", BaseCmd.TYPE_STRING, "groupIds"),
        GUEST_OS_ID("guestosid", BaseCmd.TYPE_LONG, "guestOsId"),
        HA_ENABLE("haenable", BaseCmd.TYPE_BOOLEAN, "haEnable"),
        HAS_CHILD("haschild", BaseCmd.TYPE_BOOLEAN, "haschild"),
        HOST_ID("hostid", BaseCmd.TYPE_LONG, "hostId"),
        HOST_IDS("hostids", BaseCmd.TYPE_STRING, "hostIds"),
        HOST_NAME("hostname", BaseCmd.TYPE_STRING, "hostname"),
        HOURLY_MAX("hourlymax", BaseCmd.TYPE_INT, "hourlyMax"),
        HYPERVISOR("hypervisor", BaseCmd.TYPE_STRING, "hypervisor"),
        HYPERVISOR_TYPE("hypervisortype", BaseCmd.TYPE_STRING, "hypervisorType"),
        ICMP_TYPE("icmptype", BaseCmd.TYPE_INT, "icmpType"),
        ICMP_CODE("icmpcode", BaseCmd.TYPE_INT, "icmpCode"),
        ID("id", BaseCmd.TYPE_LONG, "id"),
        DEVICE_ID("deviceid", BaseCmd.TYPE_LONG, "deviceid"),
        IDS("ids", BaseCmd.TYPE_STRING, "Ids"),
        INTERNAL_DNS1("internaldns1", BaseCmd.TYPE_STRING, "internaldns1"),
        INTERNAL_DNS2("internaldns2", BaseCmd.TYPE_STRING, "internaldns2"),
        INTERVAL("interval", BaseCmd.TYPE_INT, "interval"),
        INTERVAL_TYPE("intervaltype", BaseCmd.TYPE_STRING, "intervalType"),
        INSTANCE("instance", BaseCmd.TYPE_STRING, "instance"),
        IP_ADDRESS("ipaddress", BaseCmd.TYPE_STRING, "ipAddress"),
        IP_AVAIL("ipavailable", BaseCmd.TYPE_INT, "ipavailable"),
        IP_LIMIT("iplimit", BaseCmd.TYPE_INT, "iplimit"),
        IP_TOTAL("iptotal", BaseCmd.TYPE_INT, "iptotal"),
        IS_RECURSIVE("isrecursive", BaseCmd.TYPE_BOOLEAN, "isrecursive"),
        IS_FEATURED("isfeatured", BaseCmd.TYPE_BOOLEAN, "isfeatured"),
        IS_MINE("ismine", BaseCmd.TYPE_BOOLEAN, "isMine"),
        IS_PUBLIC("ispublic", BaseCmd.TYPE_BOOLEAN, "isPublic"),
        IS_CLEANUP_REQUIRED("iscleanuprequired", BaseCmd.TYPE_BOOLEAN, "iscleanuprequired"),
        IS_ENABLED("isenabled", BaseCmd.TYPE_BOOLEAN, "isEnabled"),
        IS_MIRRORED("ismirrored", BaseCmd.TYPE_BOOLEAN, "isMirrored"),
        IS_LOCAL_STORAGE_ACTIVE("islocalstorageactive", BaseCmd.TYPE_BOOLEAN, "isLocalStorageActive"),
        ISO_FILTER("isofilter", BaseCmd.TYPE_STRING, "isoFilter"),
        ISO_ID("isoid", BaseCmd.TYPE_LONG, "isoId"),
        ISO_NAME("isoname", BaseCmd.TYPE_STRING, "isoName"),
        ISO_PATH("isopath", BaseCmd.TYPE_STRING, "isoPath"),
        ISO_STATUS("isostatus", BaseCmd.TYPE_STRING, "isoStatus"),
        IS_READY("isready", BaseCmd.TYPE_BOOLEAN, "isReady"),
        IS_SOURCE_NAT("issourcenat", BaseCmd.TYPE_BOOLEAN, "isSourceNat"),
        JOB_CMD("jobcmd", BaseCmd.TYPE_LONG, "jobcmd"),
        JOB_ID("jobid", BaseCmd.TYPE_LONG, "jobid"),
        JOB_INSTANCE_ID("jobinstanceid", BaseCmd.TYPE_LONG, "jobinstanceid"),
        JOB_INSTANCE_TYPE("jobinstancetype", BaseCmd.TYPE_STRING, "jobinstancetype"),
        JOB_PROCESS_STATUS("jobprocstatus", BaseCmd.TYPE_INT, "jobprocstatus"),
        JOB_RESULT("jobresult", BaseCmd.TYPE_STRING, "jobresult"),
        JOB_RESULT_CODE("jobresultcode", BaseCmd.TYPE_INT, "jobresultcode"),
        JOB_RESULT_TYPE("jobresulttype", BaseCmd.TYPE_STRING, "jobresulttype"),
        JOB_STATUS("jobstatus", BaseCmd.TYPE_INT, "jobstatus"),
        KEYWORD("keyword", BaseCmd.TYPE_STRING, "keyword"),
        LASTNAME("lastname", BaseCmd.TYPE_STRING, "lastname"),
        LASTPINGED("lastpinged", BaseCmd.TYPE_DATE, "lastpinged"),
        LEVEL("level", BaseCmd.TYPE_STRING, "level"),
        LUN("lun", BaseCmd.TYPE_INT, "lun"),
        MAC_ADDRESS("macaddress", BaseCmd.TYPE_STRING, "macaddress"),
        MAX("max", BaseCmd.TYPE_LONG, "max"),
        MAX_SNAPS("maxsnaps", BaseCmd.TYPE_INT, "maxSnaps"),
        M_SERVER_ID("managementserverid", BaseCmd.TYPE_LONG, "managementserverid"),
        MEMORY("memory", BaseCmd.TYPE_LONG, "memory"),
        MEMORY_TOTAL("memorytotal", BaseCmd.TYPE_LONG, "memorytotal"),
        MEMORY_USED("memoryused", BaseCmd.TYPE_LONG, "memoryused"),
        MEMORY_ALLOCATED("memoryallocated", BaseCmd.TYPE_LONG, "memoryallocated"),
        MONTHLY_MAX("monthlymax", BaseCmd.TYPE_INT, "monthlyMax"),
        MULTICAST_RATE("multicastrate", BaseCmd.TYPE_INT, "multicastrate"),
        NAME("name", BaseCmd.TYPE_STRING, "name"),
        NEW_NAME("newname", BaseCmd.TYPE_STRING, "newname"),
        NETMASK("netmask", BaseCmd.TYPE_STRING, "netmask"),
        NETWORK_DOMAIN("networkdomain", BaseCmd.TYPE_STRING, "networkdomain"),
        NETWORK_GROUP_LIST("networkgrouplist", BaseCmd.TYPE_STRING, "networkGroupList"),
        NETWORK_GROUP_NAME("networkgroupname", BaseCmd.TYPE_STRING, "networkGroupName"),
        NETWORK_KB_READ("networkkbsread", BaseCmd.TYPE_LONG, "networkkbsread"),
        NETWORK_KB_WRITE("networkkbswrite", BaseCmd.TYPE_LONG, "networkkbswrite"),
        NETWORK_RATE("networkrate", BaseCmd.TYPE_INT, "networkrate"),
        NETWORK_TYPE("networktype", BaseCmd.TYPE_STRING, "networkType"),
        OFFERING_ID("offeringid", BaseCmd.TYPE_LONG, "offeringId"),
        OFFER_HA("offerha", BaseCmd.TYPE_BOOLEAN, "offerHa"),
        OLD_POD_NAME("oldpodname", BaseCmd.TYPE_STRING, "oldPodName"),
        OLD_ZONE_NAME("oldzonename", BaseCmd.TYPE_STRING, "oldZoneName"),
        OS_ARCHITECTURE("osarchitecture", BaseCmd.TYPE_INT, "osArchitecture"),
        OS_CATEGORY_ID("oscategoryid", BaseCmd.TYPE_LONG, "osCategoryId"),
        OS_CATEGORY_NAME("oscategoryname", BaseCmd.TYPE_STRING, "osCategoryName"),
        OS_TYPE_ID("ostypeid", BaseCmd.TYPE_LONG, "osTypeId"),
        OS_TYPE_NAME("ostypename", BaseCmd.TYPE_STRING, "osTypeName"),
        OP("op", BaseCmd.TYPE_STRING, "op"),
        PAGE("page", BaseCmd.TYPE_INT, "page"),
        PAGESIZE("pagesize", BaseCmd.TYPE_INT, "pagesize"),
        PARENT_ID("parentid", BaseCmd.TYPE_LONG, "parentId"),
        PARENT_DOMAIN_ID("parentdomainid", BaseCmd.TYPE_LONG, "parentDomainId"),
        PARENT_DOMAIN_NAME("parentdomainname", BaseCmd.TYPE_STRING, "parentDomainName"),
        PASSWORD("password", BaseCmd.TYPE_STRING, "password"),
        PASSWORD_ENABLED("passwordenabled", BaseCmd.TYPE_BOOLEAN, "passwordenabled"),
        PATH("path", BaseCmd.TYPE_STRING, "path"),
        PERCENT_USED("percentused", BaseCmd.TYPE_STRING, "percentused"),
        POD_ID("podid", BaseCmd.TYPE_LONG, "podId"),
        POD_NAME("podname", BaseCmd.TYPE_STRING, "podName"),
        PORT_FORWARDING_SERVICE_ID("portforwardingserviceid", BaseCmd.TYPE_LONG, "portForwardingServiceId"),
        PORTAL("portal", BaseCmd.TYPE_STRING, "portal"),
        PRIVATE_IP("privateip", BaseCmd.TYPE_STRING, "privateIp"),
        PRIVATE_MAC_ADDRESS("privatemacaddress", BaseCmd.TYPE_STRING, "privatemacaddress"),
        PRIVATE_NETMASK("privatenetmask", BaseCmd.TYPE_STRING, "privatenetmask"),
        PRIVATE_PORT("privateport", BaseCmd.TYPE_STRING, "privatePort"),
        PROTOCOL("protocol", BaseCmd.TYPE_STRING, "protocol"),
        PUBLIC_IP("publicip", BaseCmd.TYPE_STRING, "publicIp"),
        PUBLIC_MAC_ADDRESS("publicmacaddress", BaseCmd.TYPE_STRING, "publicMacAddress"),
        PUBLIC_NETMASK("publicnetmask", BaseCmd.TYPE_STRING, "publicNetmask"),
        PUBLIC_PORT("publicport", BaseCmd.TYPE_STRING, "publicPort"),
        RAW_USAGE("rawusage", BaseCmd.TYPE_FLOAT, "rawUsage"),
        RELEASE_DATE("releaseddate", BaseCmd.TYPE_DATE, "releaseddate"),
        REMOVED("removed", BaseCmd.TYPE_DATE, "removed"),
        REQUIRES_HVM("requireshvm", BaseCmd.TYPE_BOOLEAN, "requireshvm"),
        RESOURCE_TYPE("resourcetype", BaseCmd.TYPE_INT, "resourcetype"),
        RESPONSE_TYPE("response",BaseCmd.TYPE_STRING,"response"),
        ROOT_DISK_OFFERING_ID("rootdiskofferingid", BaseCmd.TYPE_LONG, "rootDiskOfferingId"),
        ROOT_DEVICE_ID("rootdeviceid", BaseCmd.TYPE_LONG, "rootDeviceId"),
        ROOT_DEVICE_TYPE("rootdevicetype", BaseCmd.TYPE_STRING, "rootDeviceType"),
        RULE_ID("ruleid", BaseCmd.TYPE_LONG, "ruleId"),
        RUNNING_VMS("runningvms", BaseCmd.TYPE_LONG, "runningvms"),
        SCHEDULE("schedule", BaseCmd.TYPE_STRING, "schedule"),
        SCHEDULED("scheduled", BaseCmd.TYPE_DATE, "scheduled"),
        SCOPE("scope", BaseCmd.TYPE_STRING, "scope"),
        SECRET_KEY("secretkey", BaseCmd.TYPE_STRING, "secretKey"),
        SENT("sent", BaseCmd.TYPE_DATE, "sent"),
        SERVICE_OFFERING_ID("serviceofferingid", BaseCmd.TYPE_LONG, "serviceOfferingId"),
        SERVICE_OFFERING_NAME("serviceofferingname", BaseCmd.TYPE_STRING, "serviceOfferingName"),
        SESSION_KEY("sessionkey", BaseCmd.TYPE_STRING, "sessionKey"),
        SHOW_ALL("showall", BaseCmd.TYPE_BOOLEAN, "showall"),
        SIGNATURE("signature",BaseCmd.TYPE_STRING,"signature"),
        SIZE("size", BaseCmd.TYPE_LONG, "size"),
        SNAPSHOT_AVAIL("snapshotavailable", BaseCmd.TYPE_INT, "snapshotavailable"),
        SNAPSHOT_ID("snapshotid", BaseCmd.TYPE_LONG, "snapshotid"),
        SNAPSHOT_LIMIT("snapshotlimit", BaseCmd.TYPE_INT, "snapshotlimit"),
        SNAPSHOT_POLICY_ID("snapshotpolicyid", BaseCmd.TYPE_LONG, "snapshotPolicyId"),
        SNAPSHOT_TOTAL("snapshottotal", BaseCmd.TYPE_INT, "snapshottotal"),
        SNAPSHOT_TYPE("snapshottype", BaseCmd.TYPE_STRING, "snapshotType"),
        SOURCE_ZONE_ID("sourcezoneid", BaseCmd.TYPE_LONG, "sourceZoneId"),
        SSO_KEY("ssokey", BaseCmd.TYPE_STRING, "ssoKey"),
        START_DATE("startdate", BaseCmd.TYPE_DATE, "startDate"),
        START_IP("startip", BaseCmd.TYPE_STRING, "startIp"),
        START_PORT("startport", BaseCmd.TYPE_INT, "startPort"),
        START_TZDATE("startdate", BaseCmd.TYPE_TZDATE, "startDate"),
        START_VLAN("startvlan", BaseCmd.TYPE_LONG, "startvlan"),
        STATE("state", BaseCmd.TYPE_STRING, "state"),
        STOPPED_VMS("stoppedvms", BaseCmd.TYPE_LONG, "stoppedvms"),
        STORAGE("storage", BaseCmd.TYPE_LONG, "storage"),
        SOURCE_ID("sourceid", BaseCmd.TYPE_LONG, "sourceid"),
        SOURCE_TYPE("sourcetype",BaseCmd.TYPE_STRING,"sourcetype"),
        STORAGE_TYPE("storagetype", BaseCmd.TYPE_STRING, "storageType"),
        STATUS("status", BaseCmd.TYPE_STRING, "status"),
        SUCCESS("success", BaseCmd.TYPE_BOOLEAN, "success"),
        SUM_ACROSS_ZONE("sumacrosszone", BaseCmd.TYPE_BOOLEAN, "sumAcrossZone"),
        SYSTEM_VM_TYPE("systemvmtype", BaseCmd.TYPE_STRING, "systemvmtype"),
        TAGS("tags", BaseCmd.TYPE_STRING, "tags"),
        TAKEN("taken", BaseCmd.TYPE_DATE, "taken"),
        TARGET_IQN("targetiqn", BaseCmd.TYPE_STRING, "targetiqn"),
        TEMPLATE_AVAIL("templateavailable", BaseCmd.TYPE_INT, "templateavailable"),
        TEMPLATE_FILTER("templatefilter", BaseCmd.TYPE_STRING, "templateFilter"),
        TEMPLATE_ID("templateid", BaseCmd.TYPE_LONG, "templateId"),
        TEMPLATE_LIMIT("templatelimit", BaseCmd.TYPE_INT, "templatelimit"),
        TEMPLATE_NAME("templatename", BaseCmd.TYPE_STRING, "templateName"),
        TEMPLATE_DISPLAY_TEXT("templatedisplaytext", BaseCmd.TYPE_STRING, "templateDisplayText"),
        TEMPLATE_STATUS("templatestatus", BaseCmd.TYPE_STRING, "templateStatus"),
        TEMPLATE_TOTAL("templatetotal", BaseCmd.TYPE_INT, "templatetotal"),
        TIMEZONE("timezone", BaseCmd.TYPE_STRING, "timezone"),
        TIMEZONE_OFFSET("timezoneoffset", BaseCmd.TYPE_FLOAT, "timezoneOffset"),
        TOTAL_MEMORY("totalmemory", BaseCmd.TYPE_LONG, "totalmemory"),
        TOTAL_VMS("totalvms", BaseCmd.TYPE_LONG, "totalvms"),
        TYPE("type", BaseCmd.TYPE_STRING, "type"),
        URL("url", BaseCmd.TYPE_STRING, "url"),
        USAGE("usage", BaseCmd.TYPE_STRING, "usage"),
        USAGE_ID("usageid", BaseCmd.TYPE_LONG, "usageId"),
        USER_ID("userid", BaseCmd.TYPE_LONG, "userId"),
        USERNAME("username", BaseCmd.TYPE_STRING, "username"),
        USER_DATA("userdata", BaseCmd.TYPE_STRING, "userData"),
        USER_NETWORK_GROUP_LIST("usernetworkgrouplist", BaseCmd.TYPE_OBJECT_MAP, "userNetworkGroupList"),
        USE_VIRTUAL_NETWORK("usevirtualnetwork", BaseCmd.TYPE_BOOLEAN, "useVirtualNetwork"),
        VALUE("value", BaseCmd.TYPE_STRING, "value"),
        VERSION("version", BaseCmd.TYPE_STRING, "version"),
        VIRTUAL_MACHINE_DISPLAYNAME("vmdisplayname", BaseCmd.TYPE_STRING, "vmdisplayname"),
        VIRTUAL_MACHINE_ID("virtualmachineid", BaseCmd.TYPE_LONG, "virtualMachineId"),
        VIRTUAL_MACHINE_IDS("virtualmachineids", BaseCmd.TYPE_STRING, "virtualMachineIds"),
        VIRTUAL_MACHINE_NAME("vmname", BaseCmd.TYPE_STRING, "vmname"),
        //VIRTUAL_MACHINE_PASSWORD("virtualmachinepassword", BaseCmd.TYPE_STRING, "virtualMachinePassword"),
        VIRTUAL_MACHINE_STATE("vmstate", BaseCmd.TYPE_STRING, "vmState"),
        VLAN_ID("vlanname", BaseCmd.TYPE_STRING, "vlanName"),
        VLAN_DB_ID("vlanid", BaseCmd.TYPE_LONG, "vlanId"),
        VLAN("vlan", BaseCmd.TYPE_STRING, "vlan"),
        VM_AVAIL("vmavailable", BaseCmd.TYPE_LONG, "vmavailable"),
        VM_LIMIT("vmlimit", BaseCmd.TYPE_LONG, "vmlimit"),
        VM_RUNNING("vmrunning", BaseCmd.TYPE_LONG, "vmrunning"),
        VM_STOPPED("vmstopped", BaseCmd.TYPE_LONG, "vmstopped"),
        VM_TOTAL("vmtotal", BaseCmd.TYPE_LONG, "vmtotal"),
        VNET("vlan", BaseCmd.TYPE_STRING, "vlan"),
        VOLUME_AVAIL("volumeavailable", BaseCmd.TYPE_INT, "volumeavailable"),
        VOLUME_ID("volumeid", BaseCmd.TYPE_LONG, "volumeId"), // FIXME: this is an array of longs
        VOLUME_LIMIT("volumelimit", BaseCmd.TYPE_INT, "volumelimit"),
        VOLUME_NAME("volumename", BaseCmd.TYPE_STRING, "volumeName"),
        VOLUME_TOTAL("volumetotal", BaseCmd.TYPE_INT, "volumetotal"),
        VOLUME_TYPE("volumetype", BaseCmd.TYPE_STRING, "volumeType"),
        WEEKLY_MAX("weeklymax", BaseCmd.TYPE_INT, "weeklyMax"),
        ZONE_ID("zoneid", BaseCmd.TYPE_LONG, "zoneId"),
        ZONE_NAME("zonename", BaseCmd.TYPE_STRING, "zoneName");

        private final String _name;
        private final short _dataType;
        private final String _tagName;

        Properties(String name, short dataType, String tagName) {
            _name = name;
            _dataType = dataType;
            _tagName = tagName;
        }

        public short getDataType() { return _dataType; }
        public String getName() { return _name; }
        public String getTagName() { return _tagName; }
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    public abstract String getName();
    public abstract ResponseObject getResponse();
Solution content
    public static final DateFormat INPUT_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    private static final DateFormat _outputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

    private Object _responseObject = null;

    public abstract String getName();
    public abstract ResponseObject getResponse();
File
BaseCmd.java
Developer's decision
Version 1
Kind of conflict
Attribute
Enum declaration
Chunk
Conflicting content
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}
<<<<<<< HEAD
=======
	
	protected Account getAccount(Map params) throws ServerApiException {
	    Long domainId      = (Long)   params.get(Properties.DOMAIN_ID.getName());
        Account account    = (Account)params.get(Properties.ACCOUNT_OBJ.getName());
        String accountName = (String) params.get(Properties.ACCOUNT.getName());
        
        Long accountId = null;
        Account finalAccount = null;
	    ManagementServer managementServer = getManagementServer();
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !managementServer.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(PARAM_ERROR, "Invalid domain id (" + domainId + ") ");
                }
                if (accountName != null) {
                    Account userAccount = managementServer.findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new ServerApiException(PARAM_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((account != null) ? account.getId() : null);
            }
        } else {
            accountId = account.getId();
        }

        if (accountId != null) {
            finalAccount = managementServer.findAccountById(accountId);
        }
        return finalAccount;
	}
	
    protected Long checkAccountPermissions(Map params,
                                           long targetAccountId,
                                           long targetDomainId,
                                           String targetDesc,
                                           long targetId)
    throws ServerApiException
    {
	    Long accountId = null;
	    
        Account account = getAccount(params);
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
        
        return accountId;
	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}
}
File
BaseCmd.java
Developer's decision
Version 1
Kind of conflict
Method declaration
Chunk
Conflicting content
import java.util.Map;
import java.util.List;
 * 
 */

<<<<<<< HEAD

package com.cloud.api.commands;
=======
package com.cloud.api.commands;
import java.util.ArrayList;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

import org.apache.log4j.Logger;
Solution content
 * 
 */
package com.cloud.api.commands;

import org.apache.log4j.Logger;
File
AddConfigCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Package declaration
Chunk
Conflicting content
@Implementation(method="discoverHosts", manager=Manager.AgentManager)
public class AddHostCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(AddHostCmd.class.getName());
<<<<<<< HEAD
    private static final String s_name = "addhostresponse";
    
    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="clusterid", type=CommandType.LONG)
    private Long clusterId;

    @Parameter(name="clustername", type=CommandType.STRING)
    private String clusterName;

    @Parameter(name="password", type=CommandType.STRING, required=true)
    private String password;

    @Parameter(name="podid", type=CommandType.LONG)
    private Long podId;

    @Parameter(name="url", type=CommandType.STRING, required=true)
    private String url;

    @Parameter(name="username", type=CommandType.STRING, required=true)
    private String username;

    @Parameter(name="zoneid", type=CommandType.LONG, required=true)
    private Long zoneId;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public Long getClusterId() {
        return clusterId;
    }

    public String getClusterName() {
        return clusterName;
    }

    public String getPassword() {
        return password;
    }

    public Long getPodId() {
        return podId;
    }

    public String getUrl() {
        return url;
    }

    public String getUsername() {
        return username;
    }

    public Long getZoneId() {
        return zoneId;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
    	return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
    	List hosts = (List)getResponseObject();

    	ListResponse response = new ListResponse();
        List hostResponses = new ArrayList();
        if (hosts != null) {
            for (HostVO host : hosts) {
	        	HostResponse hostResponse = new HostResponse();
	        	hostResponse.setId(host.getId());
	            hostResponse.setCapabilities(host.getCapabilities());
	            hostResponse.setClusterId(host.getClusterId());
	            hostResponse.setCpuNumber(host.getCpus());
	            hostResponse.setZoneId(host.getDataCenterId());
	            hostResponse.setDisconnectedOn(host.getDisconnectedOn());
	            hostResponse.setHypervisor(host.getHypervisorType());
	            hostResponse.setHostType(host.getType());
	            hostResponse.setLastPinged(new Date(host.getLastPinged()));
	            hostResponse.setManagementServerId(host.getManagementServerId());
	            hostResponse.setName(host.getName());
	            hostResponse.setPodId(host.getPodId());
	            hostResponse.setCreated(host.getCreated());
	            hostResponse.setRemoved(host.getRemoved());
	            hostResponse.setCpuSpeed(host.getSpeed());
        	{
	            hostResponse.setState(host.getStatus());
	            hostResponse.setIpAddress(host.getPrivateIpAddress());
	            hostResponse.setVersion(host.getVersion());
=======
                Object[] sTag = new Object[h.size()];
    private static final String s_name = "addhostresponse";
    private static final List> s_properties = new ArrayList>();

    static {
        s_properties.add(new Pair(BaseCmd.Properties.ZONE_ID, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.POD_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.CLUSTER_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.CLUSTER_NAME, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.URL, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.USERNAME, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.PASSWORD, Boolean.TRUE));
    }

    @Override
    public String getName() {
        return s_name;
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params)
    {
        Long zoneId = (Long)params.get(BaseCmd.Properties.ZONE_ID.getName());
        Long podId = (Long)params.get(BaseCmd.Properties.POD_ID.getName());
        String url = (String)params.get(BaseCmd.Properties.URL.getName());
        String username = (String)params.get(BaseCmd.Properties.USERNAME.getName());
        String password = (String)params.get(BaseCmd.Properties.PASSWORD.getName());
        Long clusterId = (Long)params.get(BaseCmd.Properties.CLUSTER_ID.getName());
        String clusterName = (String)params.get(BaseCmd.Properties.CLUSTER_NAME.getName());
        
        if (clusterName != null && clusterId != null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't specify cluster by both id and name");
        }
        
        if (clusterName == null && clusterId == null) {  
               // Stand alone, assign a name to it
               String[] stringarray = url.split("//");
               String address = stringarray[stringarray.length - 1];
               clusterName = "Standalone-" + address; 
        }
        
        if ((clusterName != null || clusterId != null) && podId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't specify cluster without specifying the pod");
        }
        
        //Check if the zone exists in the system
        if (getManagementServer().findDataCenterById(zoneId) == null ){
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't find zone by id " + zoneId);
        }

        //Check if the pod exists in the system
        if (podId != null) {
            if (getManagementServer().findHostPodById(podId) == null ){
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't find pod by id " + podId);
            }
            //check if pod belongs to the zone
            HostPodVO pod = getManagementServer().findHostPodById(podId);
            if (!Long.valueOf(pod.getDataCenterId()).equals(zoneId)) {
            	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Pod " + podId + " doesn't belong to the zone " + zoneId);
            }
        }

        if (clusterId != null) {
            if (getManagementServer().findClusterById(clusterId) == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't find cluster by id " + clusterId);
            }
        }
        
        
        boolean success = false;
        List> serverTags = new ArrayList>();

        try
        {
            if (clusterName != null) {
                ClusterVO cluster = getManagementServer().createCluster(zoneId, podId, clusterName);
                clusterId = cluster.getId();
            }
            
        	List h = getManagementServer().discoverHosts(zoneId, podId, clusterId, url, username, password);
        	success = !h.isEmpty();

        	if(success)
                int i=0;
	        	for(Host host:h)
	        	{
	                List> serverData = new ArrayList>();
	                serverData.add(new Pair(BaseCmd.Properties.ID.getName(), host.getId().toString()));
	                serverData.add(new Pair(BaseCmd.Properties.NAME.getName(), host.getName()));
	                if (host.getStatus() != null) {
	                    serverData.add(new Pair(BaseCmd.Properties.STATE.getName(), host.getStatus().toString()));
	                }
	                if (host.getDisconnectedOn() != null) {
	                    serverData.add(new Pair(BaseCmd.Properties.DISCONNECTED.getName(), getDateString(host.getDisconnectedOn())));
	                }
	                if (host.getType() != null) {
	                    serverData.add(new Pair(BaseCmd.Properties.TYPE.getName(), host.getType().toString()));
	                }
	                
	                GuestOSCategoryVO guestOSCategory = getManagementServer().getHostGuestOSCategory(host.getId());
	                if (guestOSCategory != null) {
	                	serverData.add(new Pair(BaseCmd.Properties.OS_CATEGORY_ID.getName(), guestOSCategory.getId()));
	                	serverData.add(new Pair(BaseCmd.Properties.OS_CATEGORY_NAME.getName(), guestOSCategory.getName()));
	                }
	                
	                serverData.add(new Pair(BaseCmd.Properties.IP_ADDRESS.getName(), host.getPrivateIpAddress()));
	                serverData.add(new Pair(BaseCmd.Properties.ZONE_ID.getName(), Long.valueOf(host.getDataCenterId()).toString()));
	                serverData.add(new Pair(BaseCmd.Properties.ZONE_NAME.getName(), getManagementServer().getDataCenterBy(host.getDataCenterId()).getName()));
	                if (host.getPodId() != null && getManagementServer().findHostPodById(host.getPodId()) != null) {
	                    serverData.add(new Pair(BaseCmd.Properties.POD_ID.getName(), host.getPodId().toString()));
	                    serverData.add(new Pair(BaseCmd.Properties.POD_NAME.getName(), getManagementServer().findHostPodById(host.getPodId()).getName()));
	                }
	                serverData.add(new Pair(BaseCmd.Properties.VERSION.getName(), host.getVersion().toString()));
	                if (host.getHypervisorType() != null) {
	                    serverData.add(new Pair(BaseCmd.Properties.HYPERVISOR.getName(), host.getHypervisorType().toString()));
	                }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	
	            GuestOSCategoryVO guestOSCategory = ApiDBUtils.getHostGuestOSCategory(host.getId());
	            if (guestOSCategory != null) {
Solution content
@Implementation(method="discoverHosts", manager=Manager.AgentManager)
public class AddHostCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(AddHostCmd.class.getName());

    private static final String s_name = "addhostresponse";
    
    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="clusterid", type=CommandType.LONG)
    private Long clusterId;
    @Parameter(name="clustername", type=CommandType.STRING)
    private String clusterName;

    @Parameter(name="password", type=CommandType.STRING, required=true)
    private String password;

    @Parameter(name="podid", type=CommandType.LONG)
    private Long podId;

    @Parameter(name="url", type=CommandType.STRING, required=true)
    private String url;

    @Parameter(name="username", type=CommandType.STRING, required=true)
    private String username;

    @Parameter(name="zoneid", type=CommandType.LONG, required=true)
    private Long zoneId;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public Long getClusterId() {
        return clusterId;
    }

    public String getClusterName() {
        return clusterName;
    }

    public String getPassword() {
        return password;
    }

    public Long getPodId() {
        return podId;
    }

    public String getUrl() {
        return url;
    }

    public String getUsername() {
        return username;
    }

    public Long getZoneId() {
        return zoneId;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    }
    public String getName() {
    	return s_name;

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
    	List hosts = (List)getResponseObject();

    	ListResponse response = new ListResponse();
        List hostResponses = new ArrayList();
        if (hosts != null) {
            for (HostVO host : hosts) {
	        	HostResponse hostResponse = new HostResponse();
	        	hostResponse.setId(host.getId());
	            hostResponse.setCapabilities(host.getCapabilities());
	            hostResponse.setClusterId(host.getClusterId());
	            hostResponse.setCpuNumber(host.getCpus());
	            hostResponse.setZoneId(host.getDataCenterId());
	            hostResponse.setDisconnectedOn(host.getDisconnectedOn());
	            hostResponse.setHypervisor(host.getHypervisorType());
	            hostResponse.setHostType(host.getType());
	            hostResponse.setLastPinged(new Date(host.getLastPinged()));
	            hostResponse.setManagementServerId(host.getManagementServerId());
	            hostResponse.setName(host.getName());
	            hostResponse.setPodId(host.getPodId());
	            hostResponse.setCreated(host.getCreated());
	            hostResponse.setRemoved(host.getRemoved());
	            hostResponse.setCpuSpeed(host.getSpeed());
	            hostResponse.setState(host.getStatus());
	            hostResponse.setIpAddress(host.getPrivateIpAddress());
	            hostResponse.setVersion(host.getVersion());
	
	            GuestOSCategoryVO guestOSCategory = ApiDBUtils.getHostGuestOSCategory(host.getId());
	            if (guestOSCategory != null) {
File
AddHostCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Attribute
Cast expression
Comment
For statement
If statement
Method declaration
Method invocation
Method signature
Static initializer
Try statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.response.SuccessResponse;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

@Implementation(method="assignSecurityGroup", manager=Manager.ManagementServer)
public class AssignPortForwardingServiceCmd extends BaseAsyncCmd {
Solution content
package com.cloud.api.commands;

import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="assignSecurityGroup", manager=Manager.ManagementServer)
public class AssignPortForwardingServiceCmd extends BaseAsyncCmd {
File
AssignPortForwardingServiceCmd.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
    public String getName() {
        return s_name;
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
		Boolean success = (Boolean)getResponseObject();
		SuccessResponse response = new SuccessResponse();
		response.setSuccess(success);
		response.setResponseName(getName());
		return response;
	}
=======
    
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Long securityGroupId = (Long)params.get(BaseCmd.Properties.ID.getName());
        String securityGroupIds = (String)params.get(BaseCmd.Properties.IDS.getName());
        String publicIp = (String)params.get(BaseCmd.Properties.PUBLIC_IP.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());

        if ((securityGroupId == null) && (securityGroupIds == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }

        List sgIdList = null;
        if (securityGroupIds != null) {
            sgIdList = new ArrayList();
            StringTokenizer st = new StringTokenizer(securityGroupIds, ",");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                try {
                    Long nextSGId = Long.parseLong(token);
                    sgIdList.add(nextSGId);
                } catch (NumberFormatException nfe) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "The service id " + token + " is not a valid parameter.");
                }
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        List validateSGList = null;
        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = getManagementServer().validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = getManagementServer().findAccountById(validatedAccountId);
                if (!getManagementServer().isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }

        long jobId = getManagementServer().assignSecurityGroupAsync(userId, securityGroupId, sgIdList, publicIp, vmId);
        
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for AssignPortForwardingServiceCmd comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("AssignPortForwardingServiceCmd command has been accepted, job id: " + jobId);
        }
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
		Boolean success = (Boolean)getResponseObject();
		SuccessResponse response = new SuccessResponse();
		response.setSuccess(success);
		response.setResponseName(getName());
		return response;
	}
}
File
AssignPortForwardingServiceCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
 */
package com.cloud.api.commands;

<<<<<<< HEAD
import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="assignToLoadBalancer", manager=Manager.NetworkManager)
public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(AssignToLoadBalancerRuleCmd.class.getName());

    private static final String s_name = "assigntoloadbalancerruleresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="id", type=CommandType.LONG, required=true)
    private Long id;

    @Parameter(name="virtualmachineid", type=CommandType.LONG, required=false)
    private Long virtualMachineId;
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.network.LoadBalancerVO;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public class AssignToLoadBalancerRuleCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(AssignToLoadBalancerRuleCmd.class.getName());

    private static final String s_name = "assigntoloadbalancerruleresponse";
    private static final List> s_properties = new ArrayList>();

    static {
        s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.DOMAIN_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ID, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_IDS, Boolean.FALSE));
    }

    public String getName() {
        return s_name;
    }
    
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        Long loadBalancerId = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long instanceId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
        String instanceIds = (String)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_IDS.getName());

        if ((instanceId == null) && (instanceIds == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No virtual machine id (or list if ids) specified.");
        }

        List instanceIdList = new ArrayList();
        if (instanceIds != null) {
            StringTokenizer st = new StringTokenizer(instanceIds, ",");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                try {
                    Long nextInstanceId = Long.parseLong(token);
                    instanceIdList.add(nextInstanceId);
                } catch (NumberFormatException nfe) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "The virtual machine id " + token + " is not a valid parameter.");
                }
            }
        } else {
            instanceIdList.add(instanceId);
        }

        if (account == null) {
            account = getManagementServer().findActiveAccount(accountName, domainId);
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        LoadBalancerVO loadBalancer = getManagementServer().findLoadBalancerById(loadBalancerId.longValue());
        if (loadBalancer == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find load balancer rule, with id " + loadBalancerId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (loadBalancer.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName() +
                        " (id:" + loadBalancer.getId() + ")");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), loadBalancer.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid load balancer rule id (" + loadBalancer.getId() + ") given, unable to assign instances to load balancer rule.");
            }
        }

        long jobId = getManagementServer().assignToLoadBalancerAsync(userId.longValue(), loadBalancerId.longValue(), instanceIdList);

        if (jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for AssignToLoadBalancerRule comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("AssignToLoadBalancerRule command has been accepted, job id: " + jobId);
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    @Parameter(name="virtualmachineids", type=CommandType.LIST, collectionType=CommandType.LONG, required=false)
    private List virtualMachineIds;
Solution content
 */
package com.cloud.api.commands;

import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="assignToLoadBalancer", manager=Manager.NetworkManager)
public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(AssignToLoadBalancerRuleCmd.class.getName());

    private static final String s_name = "assigntoloadbalancerruleresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="id", type=CommandType.LONG, required=true)
    private Long id;

    @Parameter(name="virtualmachineid", type=CommandType.LONG, required=false)
    private Long virtualMachineId;

    @Parameter(name="virtualmachineids", type=CommandType.LIST, collectionType=CommandType.LONG, required=false)
    private List virtualMachineIds;
File
AssignToLoadBalancerRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Attribute
Cast expression
Class signature
Comment
If statement
Import
Method declaration
Method invocation
Method signature
Static initializer
Variable
Chunk
Conflicting content
public class AssociateIPAddrCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmd.class.getName());
    private static final String s_name = "associateipaddressresponse";
<<<<<<< HEAD

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="account", type=CommandType.STRING)
    private String accountName;

    @Parameter(name="domainid", type=CommandType.LONG)
    private Long domainId;

    @Parameter(name="zoneid", type=CommandType.LONG, required=true)
    private Long zoneId;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public String getAccountName() {
        return accountName;
    }

    public Long getDomainId() {
        return domainId;
    }

    public Long getZoneId() {
        return zoneId;
    }


    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

=======
    private static final List> s_properties = new ArrayList>();

    static {
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.DOMAIN_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ZONE_ID, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_ID, Boolean.FALSE));
    }

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public String getName() {
        return s_name;
    }
Solution content
public class AssociateIPAddrCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmd.class.getName());
    private static final String s_name = "associateipaddressresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="account", type=CommandType.STRING)
    private String accountName;

    @Parameter(name="domainid", type=CommandType.LONG)
    private Long domainId;

    @Parameter(name="zoneid", type=CommandType.LONG, required=true)
    private Long zoneId;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public String getAccountName() {
        return accountName;
    }

    public Long getDomainId() {
        return domainId;
    }

    public Long getZoneId() {
        return zoneId;
    }


    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    public String getName() {
        return s_name;
    }
File
AssociateIPAddrCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Attribute
Comment
Method declaration
Method invocation
Static initializer
Chunk
Conflicting content
    public static String getResultObjectName() {
    	return "addressinfo";
<<<<<<< HEAD
    }
    
    public ResponseObject getResponse() {
    	IPAddressVO ipAddress = (IPAddressVO)getResponseObject();

        VlanVO vlan  = ApiDBUtils.findVlanById(ipAddress.getVlanDbId());
        boolean forVirtualNetworks = vlan.getVlanType().equals(VlanType.VirtualNetwork);

        IPAddressResponse ipResponse = new IPAddressResponse();
        ipResponse.setIpAddress(ipAddress.getAddress());
        if (ipAddress.getAllocated() != null) {
            ipResponse.setAllocated(ipAddress.getAllocated());
        }
        ipResponse.setZoneId(ipAddress.getDataCenterId());
        ipResponse.setZoneName(ApiDBUtils.findZoneById(ipAddress.getDataCenterId()).getName());
        ipResponse.setSourceNat(ipAddress.isSourceNat());

        //get account information
        Account accountTemp = ApiDBUtils.findAccountById(ipAddress.getAccountId());
        if (accountTemp !=null){
            ipResponse.setAccountName(accountTemp.getAccountName());
            ipResponse.setDomainId(accountTemp.getDomainId());
            ipResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
        } 
        
        ipResponse.setForVirtualNetwork(forVirtualNetworks);

        //show this info to admin only
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null)  || isAdmin(account.getType())) {
            ipResponse.setVlanId(ipAddress.getVlanDbId());
            ipResponse.setVlanName(ApiDBUtils.findVlanById(ipAddress.getVlanDbId()).getVlanId());
        }

        ipResponse.setResponseName(getName());
        return ipResponse;
=======
    }

    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
    	Long zoneId = (Long)params.get(BaseCmd.Properties.ZONE_ID.getName());
    	Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
 
        String newIpAddr = null;
        String errorDesc = null;
        Long accountId = null;
        boolean isAdmin = false;

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to associate IP address.");
                }
                if (accountName != null) {
                    Account userAccount = getManagementServer().findAccountByName(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (account != null) {
                // the admin is acquiring an IP address
                accountId = account.getId();
                domainId = account.getDomainId();
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Account information is not specified.");
            }
        } else {
            accountId = account.getId();
}
            domainId = account.getDomainId();
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        //vmId == 0 => general flow
        //vmId != 0 => 1:1 NAT
        if(vmId == null){
        	vmId = Long.valueOf(0);
        }
        
        try {
            newIpAddr = getManagementServer().associateIpAddress(userId.longValue(), accountId.longValue(), domainId.longValue(), zoneId.longValue(), vmId.longValue());
        } catch (ResourceAllocationException rae) {
        	if (rae.getResourceType().equals("vm")) throw new ServerApiException (BaseCmd.VM_ALLOCATION_ERROR, rae.getMessage());
        	else if (rae.getResourceType().equals("ip")) throw new ServerApiException (BaseCmd.IP_ALLOCATION_ERROR, rae.getMessage());
        } catch (InvalidParameterValueException ex1) {
            s_logger.error("error associated IP Address with userId: " + userId, ex1);
            throw new ServerApiException (BaseCmd.NET_INVALID_PARAM_ERROR, ex1.getMessage());
        } catch (InsufficientAddressCapacityException ex2) {
        	throw new ServerApiException (BaseCmd.NET_IP_ASSOC_ERROR, ex2.getMessage());
        } catch (InternalErrorException ex3){
        	throw new ServerApiException (BaseCmd.NET_IP_ASSOC_ERROR, ex3.getMessage());
        } catch (Exception ex4) {
        	throw new ServerApiException (BaseCmd.NET_IP_ASSOC_ERROR, "Unable to associate IP address");
        }

        if (newIpAddr == null) {
            s_logger.warn("unable to associate IP address for user " + ((errorDesc != null) ? (", reason: " + errorDesc) : null));
            throw new ServerApiException(BaseCmd.NET_IP_ASSOC_ERROR, "unable to associate IP address for user " + ((errorDesc != null) ? (", reason: " + errorDesc) : null));
        }
        List> embeddedObject = new ArrayList>();
        List> returnValues = new ArrayList>();

        try {
        	returnValues.add(new Pair(BaseCmd.Properties.IP_ADDRESS.getName(), newIpAddr));
        	List ipAddresses = getManagementServer().listPublicIpAddressesBy(accountId.longValue(), true, null, null);
        	IPAddressVO ipAddress = null;
        	for (Iterator iter = ipAddresses.iterator(); iter.hasNext();) {
        		IPAddressVO current = iter.next();
        		if (current.getAddress().equals(newIpAddr)) {
        			ipAddress = current;
        			break;
        		}
        	}
        	if (ipAddress == null) {
        		return returnValues;
        	}
            if (ipAddress.getAllocated() != null) {
            	returnValues.add(new Pair(BaseCmd.Properties.ALLOCATED.getName(), getDateString(ipAddress.getAllocated())));
            }
            returnValues.add(new Pair(BaseCmd.Properties.ZONE_ID.getName(), Long.valueOf(ipAddress.getDataCenterId()).toString()));
            returnValues.add(new Pair(BaseCmd.Properties.ZONE_NAME.getName(), getManagementServer().findDataCenterById(ipAddress.getDataCenterId()).getName()));
            returnValues.add(new Pair(BaseCmd.Properties.IS_SOURCE_NAT.getName(), Boolean.valueOf(ipAddress.isSourceNat()).toString()));
            //get account information
            Account accountTemp = getManagementServer().findAccountById(ipAddress.getAccountId());
            returnValues.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountTemp.getAccountName()));
            returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), accountTemp.getDomainId()));
            returnValues.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(accountTemp.getDomainId()).getName()));
        	VlanVO vlan  = getManagementServer().findVlanById(ipAddress.getVlanDbId());
        	boolean forVirtualNetworks = vlan.getVlanType().equals(VlanType.VirtualNetwork);
            returnValues.add(new Pair(BaseCmd.Properties.FOR_VIRTUAL_NETWORK.getName(), forVirtualNetworks));
            //show this info to admin only
            if (isAdmin == true) {
            	returnValues.add(new Pair(BaseCmd.Properties.VLAN_DB_ID.getName(), Long.valueOf(ipAddress.getVlanDbId()).toString()));
                returnValues.add(new Pair(BaseCmd.Properties.VLAN_ID.getName(), vlan.getVlanId()));
            }
            embeddedObject.add(new Pair("publicipaddress", new Object[] { returnValues } ));
        } catch (Exception ex) {
            s_logger.error("error!", ex);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal Error encountered while assigning IP address " + newIpAddr + " to account " + accountId);
        }
        return embeddedObject;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
Solution content
    public static String getResultObjectName() {
    	return "addressinfo";
    }
    
    public ResponseObject getResponse() {
    	IPAddressVO ipAddress = (IPAddressVO)getResponseObject();

        VlanVO vlan  = ApiDBUtils.findVlanById(ipAddress.getVlanDbId());
        boolean forVirtualNetworks = vlan.getVlanType().equals(VlanType.VirtualNetwork);

        IPAddressResponse ipResponse = new IPAddressResponse();
        ipResponse.setIpAddress(ipAddress.getAddress());
        if (ipAddress.getAllocated() != null) {
            ipResponse.setAllocated(ipAddress.getAllocated());
        }
        ipResponse.setZoneId(ipAddress.getDataCenterId());
        ipResponse.setZoneName(ApiDBUtils.findZoneById(ipAddress.getDataCenterId()).getName());
        ipResponse.setSourceNat(ipAddress.isSourceNat());

        //get account information
        Account accountTemp = ApiDBUtils.findAccountById(ipAddress.getAccountId());
        if (accountTemp !=null){
            ipResponse.setAccountName(accountTemp.getAccountName());
            ipResponse.setDomainId(accountTemp.getDomainId());
            ipResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
        } 
        
        ipResponse.setForVirtualNetwork(forVirtualNetworks);

        //show this info to admin only
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null)  || isAdmin(account.getType())) {
            ipResponse.setVlanId(ipAddress.getVlanDbId());
            ipResponse.setVlanName(ApiDBUtils.findVlanById(ipAddress.getVlanDbId()).getVlanId());
        }

        ipResponse.setResponseName(getName());
        return ipResponse;
    }
}
File
AssociateIPAddrCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Return statement
Try statement
Variable
Chunk
Conflicting content
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach iso");
        }
<<<<<<< HEAD
=======
    	VMTemplateVO iso = getManagementServer().findTemplateById(isoId);
    	if (iso == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find an ISO with id " + isoId);
    	}

    	if (account != null) {
    	    if (!isAdmin(account.getType())) {
                if (account.getId() != vmInstanceCheck.getAccountId()) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to attach ISO " + iso.getName() + " to virtual machine " + vmInstanceCheck.getName() + " for this account");
                }
                if (!iso.isPublicTemplate() && (account.getId() != iso.getAccountId()) && (!iso.getName().startsWith("xs-tools"))) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to attach ISO " + iso.getName() + " to virtual machine " + vmInstanceCheck.getName() + " for this account");
                }
    	    } else {
    	        if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstanceCheck.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to attach ISO " + iso.getName() + " to virtual machine " + vmInstanceCheck.getName());
    	        }
    	        // FIXME:  if ISO owner is null we probably need to throw some kind of exception
    	        Account isoOwner = getManagementServer().findAccountById(iso.getAccountId());
    	        if ((isoOwner != null) && !getManagementServer().isChildDomain(account.getDomainId(), isoOwner.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to attach ISO " + iso.getName() + " to virtual machine " + vmInstanceCheck.getName());
    	        }
    	    }
    	}

    	// If command is executed via 8096 port, set userId to the id of System account (1)
    	if (userId == null)
    		userId = new Long(1);
    	
		try {
			long jobId = getManagementServer().attachISOToVMAsync(vmId.longValue(), userId, isoId.longValue());
			
            if (jobId == 0) {
            	s_logger.warn("Unable to schedule async-job for AttachIsoCmd");
            } else {
    	        if (s_logger.isDebugEnabled())
    	        	s_logger.debug("AttachIsoCmd has been accepted, job id: " + jobId);
            }
			
            List> returnValues = new ArrayList>();
            returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId)));
            
            return returnValues;
		} catch (ServerApiException apiEx) {
			s_logger.error("Exception attaching ISO", apiEx);
			throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach ISO: " + apiEx.getDescription());
		} catch (Exception ex) {
			s_logger.error("Exception attaching ISO", ex);
			throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach ISO: " + ex.getMessage());
		}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        response.setResponseName(getName());
        return response;
Solution content
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach iso");
        }

        response.setResponseName(getName());
        return response;
File
AttachIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Try statement
Variable
Chunk
Conflicting content
    /////////////////////////////////////////////////////

    @Override
<<<<<<< HEAD
    public String getName() {
        return s_name;
=======
    public List> execute(Map params) {
    	Account account = (Account) params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        //Long userId = (Long) params.get(BaseCmd.Properties.USER_ID.getName());
    	Long volumeId = (Long) params.get(BaseCmd.Properties.ID.getName());
    	Long vmId = (Long) params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
        Long deviceId = (Long) params.get(BaseCmd.Properties.DEVICE_ID.getName());

    	// Check that the volume ID is valid
    	VolumeVO volume = getManagementServer().findVolumeById(volumeId);
    	if (volume == null)
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId);

    	// Check that the virtual machine ID is valid
    	UserVmVO vm = getManagementServer().findUserVMInstanceById(vmId.longValue());
        if (vm == null) {
        	throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        // Check that the device ID is valid
        if( deviceId != null ) {
            if(deviceId.longValue() == 0) {
                throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, "deviceId can't be 0, which is used by Root device");
            }
        }
        
        if (volume.getAccountId() != vm.getAccountId()) {
        	throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, "virtual machine and volume belong to different accounts, can not attach");
        }

    	// If the account is not an admin, check that the volume and the virtual machine are owned by the account that was passed in
    	if (account != null) {
    	    if (!isAdmin(account.getType())) {
                if (account.getId() != volume.getAccountId())
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId + " for account: " + account.getAccountName());

                if (account.getId() != vm.getAccountId())
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find VM with ID: " + vmId + " for account: " + account.getAccountName());
    	    } else {
    	        if (!getManagementServer().isChildDomain(account.getDomainId(), volume.getDomainId()) ||
    	            !getManagementServer().isChildDomain(account.getDomainId(), vm.getDomainId())) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to attach volume " + volumeId + " to virtual machine instance " + vmId + ", permission denied.");
    	        }
    	    }
    	}

    	try {
    		long jobId = getManagementServer().attachVolumeToVMAsync(vmId, volumeId, deviceId);

    		if (jobId == 0) {
            	s_logger.warn("Unable to schedule async-job for AttachVolume comamnd");
            } else {
    	        if(s_logger.isDebugEnabled())
    	        	s_logger.debug("AttachVolume command has been accepted, job id: " + jobId);
            }

    		List> returnValues = new ArrayList>();
            returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 

            return returnValues;
    	} catch (Exception ex) {
    		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach volume: " + ex.getMessage());
    	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }

	@Override
Solution content
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

	@Override
File
AttachVolumeCmd.java
Developer's decision
Version 1
Kind of conflict
Attribute
Cast expression
Comment
If statement
Method invocation
Method signature
Return statement
Try statement
Variable
Chunk
Conflicting content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
<<<<<<< HEAD
import com.cloud.api.response.DiskOfferingResponse;
import com.cloud.storage.DiskOfferingVO;

@Implementation(method="createDiskOffering", manager=Manager.ConfigManager)
=======
import com.cloud.domain.DomainVO;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.user.User;
import com.cloud.utils.Pair;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
public class CreateDiskOfferingCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(CreateDiskOfferingCmd.class.getName());
Solution content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.DiskOfferingResponse;
import com.cloud.storage.DiskOfferingVO;

@Implementation(method="createDiskOffering", manager=Manager.ConfigManager)
public class CreateDiskOfferingCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(CreateDiskOfferingCmd.class.getName());
File
CreateDiskOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Import
Chunk
Conflicting content
    public static final Logger s_logger = Logger.getLogger(CreateDiskOfferingCmd.class.getName());

    private static final String s_name = "creatediskofferingresponse";
<<<<<<< HEAD
=======
    private static final List> s_properties = new ArrayList>();

    static {
    	s_properties.add(new Pair(BaseCmd.Properties.NAME, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.DISK_SIZE, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.DOMAIN_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.TAGS, Boolean.FALSE));
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
Solution content
    public static final Logger s_logger = Logger.getLogger(CreateDiskOfferingCmd.class.getName());

    private static final String s_name = "creatediskofferingresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
File
CreateDiskOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Attribute
Method invocation
Static initializer
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public ResponseObject getResponse() {
        DiskOfferingResponse response = new DiskOfferingResponse();
        DiskOfferingVO responseObject = (DiskOfferingVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setCreated(responseObject.getCreated());
            response.setDiskSize(responseObject.getDiskSize());
            response.setDisplayText(responseObject.getDisplayText());
            response.setDomainId(responseObject.getDomainId());
            response.setDomain(ApiDBUtils.findDomainById(responseObject.getDomainId()).getName());
            response.setName(responseObject.getName());
            response.setTags(responseObject.getTags());
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create disk offering");
        }

        response.setResponseName(getName());
        return response;
    }
=======
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        // FIXME: add domain-private disk offerings

        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        String displayText = (String)params.get(BaseCmd.Properties.DISPLAY_TEXT.getName());
        Long numGB = (Long) params.get(BaseCmd.Properties.DISK_SIZE.getName());
        String tags = (String)params.get(BaseCmd.Properties.TAGS.getName());
       
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        DiskOfferingVO diskOffering = null;
        try {
        	diskOffering = getManagementServer().createDiskOffering(userId, DomainVO.ROOT_DOMAIN, name, displayText, numGB.intValue(),tags);
        } catch (InvalidParameterValueException ex) {
        	throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, ex.getMessage());
        } catch (InternalErrorException ex) {
            throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, ex.getMessage());            
        }
        
        if (diskOffering == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create disk offering");
        }

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), Long.toString(diskOffering.getId())));
        returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), diskOffering.getDomainId()));
        returnValues.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(diskOffering.getDomainId()).getName()));
        returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), diskOffering.getName()));
        returnValues.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), diskOffering.getDisplayText()));
        returnValues.add(new Pair(BaseCmd.Properties.DISK_SIZE.getName(), diskOffering.getDiskSizeInBytes()));
        returnValues.add(new Pair(BaseCmd.Properties.CREATED.getName(), diskOffering.getCreated()));
        returnValues.add(new Pair(BaseCmd.Properties.TAGS.getName(), diskOffering.getTags()));
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    }

    @Override
    public ResponseObject getResponse() {
        DiskOfferingResponse response = new DiskOfferingResponse();
        DiskOfferingVO responseObject = (DiskOfferingVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setCreated(responseObject.getCreated());
            response.setDiskSize(responseObject.getDiskSize());
            response.setDisplayText(responseObject.getDisplayText());
            response.setDomainId(responseObject.getDomainId());
            response.setDomain(ApiDBUtils.findDomainById(responseObject.getDomainId()).getName());
            response.setName(responseObject.getName());
            response.setTags(responseObject.getTags());
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create disk offering");
        }

        response.setResponseName(getName());
        return response;
    }
}
File
CreateDiskOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
<<<<<<< HEAD
import com.cloud.api.response.DomainResponse;
import com.cloud.domain.DomainVO;
=======
import com.cloud.domain.Domain;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

@Implementation(method="createDomain")
public class CreateDomainCmd extends BaseCmd {
Solution content
import com.cloud.api.ResponseObject;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.DomainResponse;
import com.cloud.domain.DomainVO;

@Implementation(method="createDomain")
public class CreateDomainCmd extends BaseCmd {
File
CreateDomainCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
File
CreateDomainCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
        return s_name;
    }

<<<<<<< HEAD
    @Override
    public ResponseObject getResponse() {
        DomainResponse response = new DomainResponse();
        DomainVO responseObject = (DomainVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setDomainName(responseObject.getName());
            response.setLevel(responseObject.getLevel());
            response.setParentDomainId(responseObject.getParent());
            response.setParentDomainName(ApiDBUtils.findDomainById(responseObject.getParent()).getName());
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create domain");
        }

        response.setResponseName(getName());
        return response;
    }
=======
    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        Long parentDomainId = (Long)params.get(BaseCmd.Properties.PARENT_DOMAIN_ID.getName());

        // If account is null, consider System as an owner for this action
        if (account == null) {
            account = getManagementServer().findAccountById(Long.valueOf(1L));
        }

        if (parentDomainId == null){
        	parentDomainId = Domain.ROOT_DOMAIN;
        } else {
        	Domain parentDomain = null;
            parentDomain = getManagementServer().findDomainIdById(parentDomainId);
        	if (parentDomain == null) {
        		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find parent domain " + parentDomainId);
        	}
        }

        if (!getManagementServer().isChildDomain(account.getDomainId(), parentDomainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid parent domain " + parentDomainId + ", unable to create domain " + name);
        }

        Domain domain = null;
        try {
            domain = getManagementServer().createDomain(name, account.getId(), parentDomainId);
        } catch (IllegalArgumentException illArgEx) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Failed to create domain " + name + " due to invalid name given.");
            }
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create domain " + name + ", invalid name given.  The character '/' is not valid for domain names.");
        } catch (Exception ex) {
            s_logger.error("Exception creating domain", ex);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create domain " + name + ":  internal error.");
        }

        List> embeddedObject = new ArrayList>();
        List> returnValues = new ArrayList>();
        if (domain == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create domain " + name + ":  a domain with that name already exists.");
        } else {
            returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), domain.getId()));
            returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), domain.getName()));
            returnValues.add(new Pair(BaseCmd.Properties.LEVEL.getName(), Integer.toString(domain.getLevel())));
            returnValues.add(new Pair(BaseCmd.Properties.PARENT_DOMAIN_ID.getName(), domain.getParent().toString()));
            returnValues.add(new Pair(BaseCmd.Properties.PARENT_DOMAIN_NAME.getName(), 
        			getManagementServer().findDomainIdById(domain.getParent()).getName()));
            embeddedObject.add(new Pair("domain", new Object[] { returnValues } ));
        }
        return embeddedObject;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
        return s_name;
    }

    @Override
    public ResponseObject getResponse() {
        DomainResponse response = new DomainResponse();
        DomainVO responseObject = (DomainVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setDomainName(responseObject.getName());
            response.setLevel(responseObject.getLevel());
            response.setParentDomainId(responseObject.getParent());
            response.setParentDomainName(ApiDBUtils.findDomainById(responseObject.getParent()).getName());
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create domain");
        }

        response.setResponseName(getName());
        return response;
    }
}
File
CreateDomainCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public ResponseObject getResponse() {
        FirewallRuleVO fwRule = (FirewallRuleVO)getResponseObject();

        FirewallRuleResponse fwResponse = new FirewallRuleResponse();
        fwResponse.setId(fwRule.getId());
        fwResponse.setPrivatePort(fwRule.getPrivatePort());
        fwResponse.setProtocol(fwRule.getProtocol());
        fwResponse.setPublicPort(fwRule.getPublicPort());

        UserVm vm = ApiDBUtils.findUserVmById(virtualMachineId);
        fwResponse.setVirtualMachineId(vm.getId());
        fwResponse.setVirtualMachineName(vm.getName());

        fwResponse.setResponseName(getName());
        return fwResponse;
    }
=======
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String ipAddress = (String)params.get(BaseCmd.Properties.IP_ADDRESS.getName());
        String publicPort = (String)params.get(BaseCmd.Properties.PUBLIC_PORT.getName());
        String privatePort = (String)params.get(BaseCmd.Properties.PRIVATE_PORT.getName());
        String protocol = (String)params.get(BaseCmd.Properties.PROTOCOL.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());

        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = getManagementServer().findIPAddressById(ipAddress);
        if (ipAddressVO == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find IP address " + ipAddress);
        }

        UserVmVO userVM = getManagementServer().findUserVMInstanceById(vmId);
        if (userVM == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find virtual machine with id " + vmId);
        }

        if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding rule, IP address " + ipAddress + " owner is not the same as owner of virtual machine " + userVM.toString()); 
        }

        if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding rule, IP address " + ipAddress + " owner is not in the same availability zone as virtual machine " + userVM.toString());
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                Account vmOwner = getManagementServer().findAccountById(userVM.getAccountId());
                if (!getManagementServer().isChildDomain(account.getDomainId(), vmOwner.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding rule, IP address " + ipAddress + " to virtual machine " + vmId + ", permission denied.");
                }
            } else if (account.getId() != userVM.getAccountId()) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding rule, IP address " + ipAddress + " to virtual machine " + vmId + ", permission denied.");
            }
        }

        FirewallRuleVO firewallRule = null;
        
        try {
            firewallRule = getManagementServer().createPortForwardingRule(userId.longValue(), ipAddressVO, userVM, publicPort, privatePort, protocol);
        } catch (NetworkRuleConflictException ex) {
            throw new ServerApiException(BaseCmd.NET_CONFLICT_IPFW_RULE_ERROR, "Network rule conflict creating a forwarding rule on address:port " + ipAddress + ":" + publicPort + " to virtual machine " + userVM.toString());
        } catch (IllegalArgumentException argEx) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, argEx.getMessage());
        }

        if (firewallRule == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "The port forwarding rule from public port " + publicPort + " to private port " + privatePort + " for address " + ipAddress + " and virtual machine " + userVM.toString() + " already exists.");
        }

        List> groupsTags = new ArrayList>();
        Object[] forwardingTag = new Object[1];

        List> ruleData = new ArrayList>();

        ruleData.add(new Pair(BaseCmd.Properties.ID.getName(), firewallRule.getId().toString()));
        ruleData.add(new Pair(BaseCmd.Properties.PUBLIC_PORT.getName(), firewallRule.getPublicPort()));
        ruleData.add(new Pair(BaseCmd.Properties.PRIVATE_PORT.getName(), firewallRule.getPrivatePort()));
        ruleData.add(new Pair(BaseCmd.Properties.PROTOCOL.getName(), firewallRule.getProtocol()));
        ruleData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_NAME.getName(), userVM.getName()));
        ruleData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_DISPLAYNAME.getName(), userVM.getDisplayName()));
        ruleData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName(), Long.toString(userVM.getId())));

        forwardingTag[0] = ruleData;

        Pair eventTag = new Pair("portforwardingrule", forwardingTag);
        groupsTags.add(eventTag);
        return groupsTags;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    }

    @Override
    public ResponseObject getResponse() {
        FirewallRuleVO fwRule = (FirewallRuleVO)getResponseObject();

        FirewallRuleResponse fwResponse = new FirewallRuleResponse();
        fwResponse.setId(fwRule.getId());
        fwResponse.setPrivatePort(fwRule.getPrivatePort());
        fwResponse.setProtocol(fwRule.getProtocol());
        fwResponse.setPublicPort(fwRule.getPublicPort());

        UserVm vm = ApiDBUtils.findUserVmById(virtualMachineId);
        fwResponse.setVirtualMachineId(vm.getId());
        fwResponse.setVirtualMachineName(vm.getName());

        fwResponse.setResponseName(getName());
        return fwResponse;
    }
}
File
CreateIPForwardingRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseCmd;
<<<<<<< HEAD
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.LoadBalancerResponse;
=======
import com.cloud.api.ServerApiException;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.network.IPAddressVO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.network.LoadBalancerVO;

@Implementation(method="createLoadBalancerRule", manager=Manager.NetworkManager)
Solution content
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.LoadBalancerResponse;
import com.cloud.network.LoadBalancerVO;

@Implementation(method="createLoadBalancerRule", manager=Manager.NetworkManager)
File
CreateLoadBalancerRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public ResponseObject getResponse() {
        LoadBalancerVO responseObj = (LoadBalancerVO)getResponseObject();

        LoadBalancerResponse response = new LoadBalancerResponse();
        response.setAlgorithm(responseObj.getAlgorithm());
        response.setDescription(responseObj.getDescription());
        response.setId(responseObj.getId());
        response.setName(responseObj.getName());
        response.setPrivatePort(responseObj.getPrivatePort());
        response.setPublicIp(responseObj.getIpAddress());
        response.setPublicPort(responseObj.getPublicPort());
        response.setAccountName(responseObj.getAccountName());
        response.setDomainId(responseObj.getDomainId());
        response.setDomainName(ApiDBUtils.findDomainById(responseObj.getDomainId()).getName());

        response.setResponseName(getName());
        return response;
=======
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        String description = (String)params.get(BaseCmd.Properties.DESCRIPTION.getName());
        String publicIP = (String)params.get(BaseCmd.Properties.PUBLIC_IP.getName());
        String publicPort = (String)params.get(BaseCmd.Properties.PUBLIC_PORT.getName());
        String privatePort = (String)params.get(BaseCmd.Properties.PRIVATE_PORT.getName());
        String algorithm = (String)params.get(BaseCmd.Properties.ALGORITHM.getName());

        UserVmDao _userVmDao;
        ComponentLocator locator = ComponentLocator.getLocator("management-server");
        _userVmDao = locator.getDao(UserVmDao.class);
        
        if (userId == null) {
            userId = Long.valueOf(1);
        }

        IPAddressVO ipAddr = getManagementServer().findIPAddressById(publicIP);
        if (ipAddr == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to create load balancer rule, invalid IP address " + publicIP);
        }

        VlanVO vlan = getManagementServer().findVlanById(ipAddr.getVlanDbId());
        if (vlan != null) {
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to create load balancer rule for IP address " + publicIP + ", only VirtualNetwork type IP addresses can be used for load balancers.");
            }
        } // else ERROR?

        // Verify input parameters
        Account accountByIp = getManagementServer().findAccountByIpAddress(publicIP);
        if(accountByIp == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to create load balancer rule, cannot find account owner for ip " + publicIP);
        }

        Long accountId = accountByIp.getId();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != accountId.longValue()) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to create load balancer rule, account " + account.getAccountName() + " doesn't own ip address " + publicIP);
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), accountByIp.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create load balancer rule on IP address " + publicIP + ", permission denied.");
            }
        }

        List userVmVO = _userVmDao.listByAccountId(accountId);
        
        if(userVmVO.size()==0)
        {
        	//this means there are no associated vm's to the user account, and hence, the load balancer cannot be created
        	throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "Unable to create load balancer rule, no vm for the user exists.");
        }
        	
        LoadBalancerVO existingLB = getManagementServer().findLoadBalancer(accountId, name);

        if (existingLB != null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to create load balancer rule, an existing load balancer rule with name " + name + " already exisits.");
        }

        try {
            LoadBalancerVO loadBalancer = getManagementServer().createLoadBalancer(userId, accountId, name, description, publicIP, publicPort, privatePort, algorithm);
            List> embeddedObject = new ArrayList>();
            List> returnValues = new ArrayList>();
            returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), loadBalancer.getId().toString()));
            returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), loadBalancer.getName()));
            returnValues.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), loadBalancer.getDescription()));
            returnValues.add(new Pair(BaseCmd.Properties.PUBLIC_IP.getName(), loadBalancer.getIpAddress()));
            returnValues.add(new Pair(BaseCmd.Properties.PUBLIC_PORT.getName(), loadBalancer.getPublicPort()));
            returnValues.add(new Pair(BaseCmd.Properties.PRIVATE_PORT.getName(), loadBalancer.getPrivatePort()));
            returnValues.add(new Pair(BaseCmd.Properties.ALGORITHM.getName(), loadBalancer.getAlgorithm()));
            
            Account accountTemp = getManagementServer().findAccountById(loadBalancer.getAccountId());
            if (accountTemp != null) {
            	returnValues.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountTemp.getAccountName()));
            	returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), accountTemp.getDomainId()));
            	returnValues.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(accountTemp.getDomainId()).getName()));
            }
            embeddedObject.add(new Pair("loadbalancerrule", new Object[] { returnValues } ));
            return embeddedObject;
        } catch (InvalidParameterValueException paramError) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, paramError.getMessage());
        } catch (PermissionDeniedException permissionError) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, permissionError.getMessage());
        } catch (Exception ex) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
    }

    @Override
    public ResponseObject getResponse() {
        LoadBalancerVO responseObj = (LoadBalancerVO)getResponseObject();

        LoadBalancerResponse response = new LoadBalancerResponse();
        response.setAlgorithm(responseObj.getAlgorithm());
        response.setDescription(responseObj.getDescription());
        response.setId(responseObj.getId());
        response.setName(responseObj.getName());
        response.setPrivatePort(responseObj.getPrivatePort());
        response.setPublicIp(responseObj.getIpAddress());
        response.setPublicPort(responseObj.getPublicPort());
        response.setAccountName(responseObj.getAccountName());
        response.setDomainId(responseObj.getDomainId());
        response.setDomainName(ApiDBUtils.findDomainById(responseObj.getDomainId()).getName());

        response.setResponseName(getName());
        return response;
    }
}
File
CreateLoadBalancerRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Cast expression
Comment
If statement
Method invocation
Method signature
Return statement
Try statement
Variable
Chunk
Conflicting content
        }

    }

    @Override
<<<<<<< HEAD
    public ResponseObject getResponse() {
        NetworkGroupVO group = (NetworkGroupVO)getResponseObject();

        NetworkGroupResponse response = new NetworkGroupResponse();
        response.setAccountName(group.getAccountName());
        response.setDescription(group.getDescription());
        response.setDomainId(group.getDomainId());
        response.setDomainName(ApiDBUtils.findDomainById(group.getDomainId()).getName());
        response.setId(group.getId());
        response.setName(group.getName());

        response.setResponseName(getName());
        return response;
=======
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        //Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        String description = (String)params.get(BaseCmd.Properties.DESCRIPTION.getName());
        Long accountId = null;

        if (account != null) {
            if (isAdmin(account.getType())) {
                if (domainId != null) {
                    if (!getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create network group in domain " + domainId + ", permission denied.");
                    }
                } else {
                    // the admin must be creating the network group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                        accountName = account.getAccountName();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
                accountName = account.getAccountName();
            }
        }

        if (accountId == null) {
            if ((accountName != null) && (domainId != null)) {
                Account userAccount = getManagementServer().findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                    accountName = userAccount.getAccountName();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "could not find account " + accountName + " in domain " + domainId);
                }
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create network group, no account specified.");
        boolean isNameInUse = getManagementServer().isNetworkSecurityGroupNameInUse(domainId, accountId, name);

        if (isNameInUse) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to create network group, a group with name " + name + " already exisits.");
        }

        NetworkGroupVO networkGroup = getManagementServer().createNetworkGroup(name, description, domainId, accountId, accountName);

        List> embeddedObject = new ArrayList>();
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), Long.toString(networkGroup.getId())));
        returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), networkGroup.getName()));
        returnValues.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), networkGroup.getDescription()));
        
        Account accountTemp = getManagementServer().findAccountById(networkGroup.getAccountId());
        if (accountTemp != null) {
        	returnValues.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountTemp.getAccountName()));
        	returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), accountTemp.getDomainId()));
        	returnValues.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(accountTemp.getDomainId()).getName()));
        }
        embeddedObject.add(new Pair("networkgroup", new Object[] { returnValues } ));
        return embeddedObject;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
        response.setResponseName(getName());
    }

    @Override
    public ResponseObject getResponse() {
        NetworkGroupVO group = (NetworkGroupVO)getResponseObject();

        NetworkGroupResponse response = new NetworkGroupResponse();
        response.setAccountName(group.getAccountName());
        response.setDescription(group.getDescription());
        response.setDomainId(group.getDomainId());
        response.setDomainName(ApiDBUtils.findDomainById(group.getDomainId()).getName());
        response.setId(group.getId());
        response.setName(group.getName());
        return response;
    }
}
File
CreateNetworkGroupCmd.java
Developer's decision
Version 1
Kind of conflict
Cast expression
Comment
If statement
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
File
CreatePortForwardingServiceCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
        response.setDomainId(group.getDomainId());
        response.setDomainName(ApiDBUtils.findDomainById(group.getDomainId()).getName());

<<<<<<< HEAD
        response.setResponseName(getName());
        return response;
=======
        List> embeddedObject = new ArrayList>();
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), Long.toString(securityGroup.getId())));
        returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), securityGroup.getName()));
        returnValues.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), securityGroup.getDescription()));
        
        Account accountTemp = getManagementServer().findAccountById(securityGroup.getAccountId());
        if (accountTemp != null) {
        	returnValues.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountTemp.getAccountName()));
        	returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), accountTemp.getDomainId()));
        	returnValues.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(accountTemp.getDomainId()).getName()));
        }
        embeddedObject.add(new Pair("portforwardingservice", new Object[] { returnValues } ));
        return embeddedObject;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
        response.setDomainId(group.getDomainId());
        response.setDomainName(ApiDBUtils.findDomainById(group.getDomainId()).getName());

        response.setResponseName(getName());
        return response;
    }
}
File
CreatePortForwardingServiceCmd.java
Developer's decision
Version 1
Kind of conflict
If statement
Method invocation
Return statement
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public ResponseObject getResponse() {
        NetworkRuleConfigVO netRule = (NetworkRuleConfigVO)getResponseObject();

        PortForwardingServiceRuleResponse response = new PortForwardingServiceRuleResponse();
        response.setRuleId(netRule.getId());
        response.setPortForwardingServiceId(netRule.getSecurityGroupId());
        response.setPrivatePort(netRule.getPrivatePort());
        response.setProtocol(netRule.getProtocol());
        response.setPublicPort(netRule.getPublicPort());

        response.setResponseName(getName());
        return response;
    }
=======
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        String publicPort = (String)params.get(BaseCmd.Properties.PUBLIC_PORT.getName());
        String privatePort = (String)params.get(BaseCmd.Properties.PRIVATE_PORT.getName());
        String protocol = (String)params.get(BaseCmd.Properties.PROTOCOL.getName());
        Long securityGroupId = (Long)params.get(BaseCmd.Properties.PORT_FORWARDING_SERVICE_ID.getName());

        SecurityGroupVO sg = getManagementServer().findSecurityGroupById(securityGroupId);
        if (sg == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!getManagementServer().isChildDomain(account.getDomainId(), sg.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                }
            } else if (account.getId() != sg.getAccountId()) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long jobId = getManagementServer().createOrUpdateRuleAsync(true, userId.longValue(), sg.getAccountId(), null, securityGroupId, null, publicPort, null, privatePort, protocol, null);
        long ruleId = 0;

        if (jobId == 0) {
            s_logger.warn("Unable to schedule async-job for CreatePortForwardingServiceRuleCmd command");
        } else {
            if (s_logger.isDebugEnabled())
                s_logger.debug("CreatePortForwardingServiceRuleCmd command has been accepted, job id: " + jobId);
            
            ruleId = waitInstanceCreation(jobId);
        }

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId)));
        returnValues.add(new Pair(BaseCmd.Properties.RULE_ID.getName(), Long.valueOf(ruleId))); 
        return returnValues;
    }
    
	protected long getInstanceIdFromJobSuccessResult(String result) {
		CreateOrUpdateRuleResultObject resultObject = (CreateOrUpdateRuleResultObject)SerializerHelper.fromSerializedString(result);
		if(resultObject != null) {
			return resultObject.getRuleId();
		}

		return 0;
	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    }

    @Override
    public ResponseObject getResponse() {
        NetworkRuleConfigVO netRule = (NetworkRuleConfigVO)getResponseObject();

        PortForwardingServiceRuleResponse response = new PortForwardingServiceRuleResponse();
        response.setRuleId(netRule.getId());
        response.setPortForwardingServiceId(netRule.getSecurityGroupId());
        response.setPrivatePort(netRule.getPrivatePort());
        response.setProtocol(netRule.getProtocol());
        response.setPublicPort(netRule.getPublicPort());

        response.setResponseName(getName());
        return response;
    }
}
File
CreatePortForwardingServiceRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Method declaration
Chunk
Conflicting content
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
<<<<<<< HEAD
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ServiceOfferingResponse;
=======
import com.cloud.api.ServerApiException;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.service.ServiceOfferingVO;

@Implementation(method="createServiceOffering", manager=Manager.ConfigManager)
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.service.ServiceOfferingVO;

@Implementation(method="createServiceOffering", manager=Manager.ConfigManager)
File
CreateServiceOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
		}
	}

	@Override
<<<<<<< HEAD

    public ResponseObject getResponse() {
	    ServiceOfferingVO offering = (ServiceOfferingVO)getResponseObject();

	    ServiceOfferingResponse response = new ServiceOfferingResponse();
	    response.setId(offering.getId());
	    response.setName(offering.getName());
	    response.setDisplayText(offering.getDisplayText());
	    response.setCpuNumber(offering.getCpu());
	    response.setCpuSpeed(offering.getSpeed());
	    response.setCreated(offering.getCreated());
	    response.setMemory(offering.getRamSize());
	    response.setOfferHa(offering.getOfferHA());
	    response.setStorageType(offering.getUseLocalStorage() ? "local" : "shared");
	    response.setTags(offering.getTags());

        response.setResponseName(getName());
        return response;
=======
    public List> getProperties (){
		return s_properties;
	}
	
	
	@Override
    public List> execute(Map params) {
	    // FIXME: add domain-private service offerings
//        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
//        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
//        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
		String name = (String)params.get(BaseCmd.Properties.NAME.getName());
		String displayText = (String)params.get(BaseCmd.Properties.DISPLAY_TEXT.getName());
		Long cpuNumber = (Long)params.get(BaseCmd.Properties.CPU_NUMBER.getName());
		Long cpuSpeed = (Long)params.get(BaseCmd.Properties.CPU_SPEED.getName());
		Long memory = (Long)params.get(BaseCmd.Properties.MEMORY.getName());
		String storageType = (String) params.get(BaseCmd.Properties.STORAGE_TYPE.getName());
		Boolean offerHA = (Boolean) params.get(BaseCmd.Properties.OFFER_HA.getName());
		Boolean useVirtualNetwork = (Boolean) params.get(BaseCmd.Properties.USE_VIRTUAL_NETWORK.getName());
		Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
		String tags = (String)params.get(BaseCmd.Properties.TAGS.getName());

		if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
		
		if (name.length() == 0) {
			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering: specify the name that has non-zero length");
		}

		if (displayText.length() == 0) {
			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering: specify the display text that has non-zero length");
		}

		if ((cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647)) {
			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering: specify the cpu number value between 1 and 2147483647");
		}

		if ((cpuSpeed.intValue() <= 0) || (cpuSpeed.intValue() > 2147483647)) {
			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering: specify the cpu speed value between 1 and 2147483647");
		}

		if ((memory.intValue() <= 0) || (memory.intValue() > 2147483647)) {
			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering: specify the memory value between 1 and 2147483647");
		}
		
		boolean localStorageRequired;
		if (storageType == null) {
			localStorageRequired = false;
		} else if (storageType.equals("local")) {
			localStorageRequired = true;
		} else if (storageType.equals("shared")) {
			localStorageRequired = false;
		} else {
			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Valid pool types are: 'local' and 'shared'");
		}

		if (offerHA == null) {
			offerHA = false;
		}
		
		if (useVirtualNetwork == null) {
			useVirtualNetwork = Boolean.TRUE;
		}
		
		ServiceOfferingVO offering = null;
		try {
			offering = getManagementServer().createServiceOffering(userId, name, cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), displayText, localStorageRequired, offerHA, useVirtualNetwork, tags);
		} catch (Exception ex) {
			s_logger.error("Exception creating service offering", ex);
	        throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create service offering " + name + ":  internal error.");
		List> returnValues = new ArrayList>();
        if (offering == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create service offering " + name);
        } else {
            returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), offering.getId()));
            returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), offering.getName()));
            returnValues.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), offering.getDisplayText()));
            returnValues.add(new Pair(BaseCmd.Properties.CPU_NUMBER.getName(), Integer.valueOf(offering.getCpu()).toString()));
            returnValues.add(new Pair(BaseCmd.Properties.CPU_SPEED.getName(), Integer.valueOf(offering.getSpeed()).toString()));
            returnValues.add(new Pair(BaseCmd.Properties.MEMORY.getName(), Integer.valueOf(offering.getRamSize()).toString()));
            returnValues.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(offering.getCreated())));
            storageType = offering.getUseLocalStorage() ? "local" : "shared";
            returnValues.add(new Pair(BaseCmd.Properties.STORAGE_TYPE.getName(), storageType));
            returnValues.add(new Pair(BaseCmd.Properties.OFFER_HA.getName(), offering.getOfferHA()));
            returnValues.add(new Pair(BaseCmd.Properties.USE_VIRTUAL_NETWORK.getName(), (offering.getGuestIpType().equals(NetworkOffering.GuestIpType.Virtualized))));
            returnValues.add(new Pair(BaseCmd.Properties.TAGS.getName(), offering.getTags()));
        }
        return returnValues;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	}
}
Solution content
	    ServiceOfferingResponse response = new ServiceOfferingResponse();
	}

	@Override
    public ResponseObject getResponse() {
	    ServiceOfferingVO offering = (ServiceOfferingVO)getResponseObject();

	    response.setId(offering.getId());
	    response.setName(offering.getName());
	    response.setDisplayText(offering.getDisplayText());
	    response.setCpuNumber(offering.getCpu());
	    response.setCpuSpeed(offering.getSpeed());
	    response.setCreated(offering.getCreated());
	    response.setMemory(offering.getRamSize());
	    response.setOfferHa(offering.getOfferHA());
	    response.setStorageType(offering.getUseLocalStorage() ? "local" : "shared");
	    response.setTags(offering.getTags());

        response.setResponseName(getName());
        return response;
	}
}
File
CreateServiceOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Return statement
Try statement
Variable
Chunk
Conflicting content
import org.apache.log4j.Logger;

<<<<<<< HEAD
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCreateCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.TemplateResponse;
import com.cloud.dc.DataCenterVO;
import com.cloud.storage.GuestOS;
=======
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.async.executor.CreatePrivateTemplateResultObject;
import com.cloud.serializer.SerializerHelper;
import com.cloud.server.Criteria;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.Snapshot;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCreateCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.TemplateResponse;
import com.cloud.dc.DataCenterVO;
import com.cloud.storage.GuestOS;
import com.cloud.storage.Snapshot;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
File
CreateTemplateCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
        if (isPublic == null) {
        } else {
            volume = ApiDBUtils.findVolumeById(volumeId);
        }
<<<<<<< HEAD

        VMTemplateHostVO templateHostRef = ApiDBUtils.findTemplateHostRef(template.getId(), volume.getDataCenterId());
        response.setCreated(templateHostRef.getCreated());
        response.setReady(templateHostRef != null && templateHostRef.getDownloadState() == Status.DOWNLOADED);

        GuestOS os = ApiDBUtils.findGuestOSById(template.getGuestOSId());
        if (os != null) {
            response.setOsTypeId(os.getId());
            response.setOsTypeName(os.getDisplayName());
        } else {
            response.setOsTypeId(-1L);
            response.setOsTypeName("");
=======
        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a volume with id " + volumeId);
        }

        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        if (!isAdmin) {
            if (account.getId() != volume.getAccountId()) {
            	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a volume with id " + volumeId + " for this account");
            }
        } else if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), volume.getDomainId())) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create a template from volume with id " + volumeId + ", permission denied.");
        }

        	isPublic = Boolean.FALSE;
        }   
        
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getManagementServer().getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private templates can be created.");
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }

        Account owner = ApiDBUtils.findAccountById(template.getAccountId());
Solution content
        } else {
            volume = ApiDBUtils.findVolumeById(volumeId);
        }

        VMTemplateHostVO templateHostRef = ApiDBUtils.findTemplateHostRef(template.getId(), volume.getDataCenterId());
        response.setCreated(templateHostRef.getCreated());
        response.setReady(templateHostRef != null && templateHostRef.getDownloadState() == Status.DOWNLOADED);

        GuestOS os = ApiDBUtils.findGuestOSById(template.getGuestOSId());
        if (os != null) {
            response.setOsTypeId(os.getId());
            response.setOsTypeName(os.getDisplayName());
        } else {
            response.setOsTypeId(-1L);
            response.setOsTypeName("");
        }

        Account owner = ApiDBUtils.findAccountById(template.getAccountId());
File
CreateTemplateCmd.java
Developer's decision
Version 1
Kind of conflict
If statement
Method invocation
Throw statement
Variable
Chunk
Conflicting content
        response.setDomainId(volume.getDomainId());
        response.setDiskOfferingId(volume.getDiskOfferingId());
        
<<<<<<< HEAD
        if (volume.getDiskOfferingId() != null) {
            DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
            response.setDiskOfferingName(diskOffering.getName());
            response.setDiskOfferingDisplayText(diskOffering.getDisplayText());
=======
        if(diskOfferingId != null){
        	DiskOfferingVO dOffering = getManagementServer().findDiskOfferingById(diskOfferingId.longValue());
        	
        	if(dOffering == null){
        		throw new ServerApiException(BaseCmd.PARAM_ERROR,"Diskoffering id:"+diskOfferingId+" is invalid");
        	}
        }
        
        boolean useSnapshot = false;
        if (snapshotId == null) 
        {
            if ((zoneId == null)) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Missing parameter,zoneid must be specified.");
            }
            
            if(diskOfferingId == null && size == 0)
            {
            	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Missing parameter(s),either a positive volume size or a valid disk offering id must be specified.");
            }
            else if(diskOfferingId == null && size != 0)
            {
            	//validate the size to ensure between min and max size range
            	try 
            	{
					boolean ok = getManagementServer().validateCustomVolumeSizeRange(size);
					
					if(!ok)
						throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid size for custom volume creation:");
					
				} catch (InvalidParameterValueException e) 
				{
					s_logger.warn("Invalid size for custom volume creation");
					throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid size for custom volume creation:"+e.getMessage());
				}
            	
            	//this is the case of creating var size vol with private disk offering
            	List privateTemplateList = getManagementServer().findPrivateDiskOffering();
            	diskOfferingId = privateTemplateList.get(0).getId(); //we use this id for creating volume, randomly tagging it to a pool with an offering
            }
        } 
        else 
        {
            useSnapshot = true;
            //Verify parameters
            Snapshot snapshotCheck = getManagementServer().findSnapshotById(snapshotId);
            if (snapshotCheck == null) {
                throw new ServerApiException (BaseCmd.SNAPSHOT_INVALID_PARAM_ERROR, "unable to find a snapshot with id " + snapshotId);
            }
            
            if (account != null) {
                if (isAdmin(account.getType())) {
                    Account snapshotOwner = getManagementServer().findAccountById(snapshotCheck.getAccountId());
                    if (!getManagementServer().isChildDomain(account.getDomainId(), snapshotOwner.getDomainId())) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create volume from snapshot with id " + snapshotId + ", permission denied.");
                    }
                } else if (account.getId() != snapshotCheck.getAccountId()) {
                    throw new ServerApiException(BaseCmd.SNAPSHOT_INVALID_PARAM_ERROR, "unable to find a snapshot with id " + snapshotId + " for this account");
                }
            }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }
        response.setDomainName(ApiDBUtils.findDomainById(volume.getDomainId()).getName());
        response.setStorageType("shared"); // NOTE: You can never create a local disk volume but if that changes, we need to change this
Solution content
        response.setDomainId(volume.getDomainId());
        response.setDiskOfferingId(volume.getDiskOfferingId());

        DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
        response.setDiskOfferingName(diskOffering.getName());
        response.setDiskOfferingDisplayText(diskOffering.getDisplayText());

        response.setDomainName(ApiDBUtils.findDomainById(volume.getDomainId()).getName());
        response.setStorageType("shared"); // NOTE: You can never create a local disk volume but if that changes, we need to change this
File
CreateVolumeCmd.java
Developer's decision
Combination
Kind of conflict
Comment
If statement
Method invocation
Variable
Chunk
Conflicting content
        response.setZoneId(volume.getDataCenterId());
        response.setZoneName(ApiDBUtils.findZoneById(volume.getDataCenterId()).getName());

<<<<<<< HEAD
        response.setResponseName(getName());
        return response;
=======
    	try {
    		long jobId = 0;
    		if (useSnapshot) {
                jobId = getManagementServer().createVolumeFromSnapshotAsync(userId, account.getId(), snapshotId, name);
    		} else {
    		    jobId = getManagementServer().createVolumeAsync(userId, account.getId(), name, zoneId, diskOfferingId, size);
    		}
    		
    		if (jobId == 0) {
            	s_logger.warn("Unable to schedule async-job for CreateVolume command");
            } else {
    	        if(s_logger.isDebugEnabled())
    	        	s_logger.debug("CreateVolume command has been accepted, job id: " + jobId);
            }

    		long volumeId = waitInstanceCreation(jobId);

    		List> returnValues = new ArrayList>();
            returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
            returnValues.add(new Pair(BaseCmd.Properties.VOLUME_ID.getName(), Long.valueOf(volumeId))); 
            
            return returnValues;
    	} catch (Exception ex) {
    	    s_logger.error("Failed to create volume " + (useSnapshot ? ("from snapshot " + snapshotId) : ("in zone " + zoneId + " with disk offering " + diskOfferingId)), ex);
    	    if (useSnapshot) {
    	        throw new ServerApiException(BaseCmd.CREATE_VOLUME_FROM_SNAPSHOT_ERROR, "Unable to create a volume from snapshot with id " + snapshotId + " for this account.");
    	    } else {
                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create volume: " + ex.getMessage());
    	    }
    	}
    	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
        response.setZoneId(volume.getDataCenterId());
        response.setZoneName(ApiDBUtils.findZoneById(volume.getDataCenterId()).getName());

        response.setResponseName(getName());
        return response;
    }
}
File
CreateVolumeCmd.java
Developer's decision
Version 1
Kind of conflict
Method invocation
Return statement
Try statement
Variable
Chunk
Conflicting content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
<<<<<<< HEAD
import com.cloud.api.response.SuccessResponse;

@Implementation(method="deleteDiskOffering", manager=Manager.ConfigManager)
=======
import com.cloud.storage.DiskOfferingVO;
import com.cloud.user.User;
import com.cloud.utils.Pair;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
public class DeleteDiskOfferingCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteDiskOfferingCmd.class.getName());
    private static final String s_name = "deletediskofferingresponse";
Solution content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="deleteDiskOffering", manager=Manager.ConfigManager)
public class DeleteDiskOfferingCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteDiskOfferingCmd.class.getName());
    private static final String s_name = "deletediskofferingresponse";
File
DeleteDiskOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Import
Chunk
Conflicting content
public class DeleteDiskOfferingCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteDiskOfferingCmd.class.getName());
    private static final String s_name = "deletediskofferingresponse";
<<<<<<< HEAD
=======
    private static final List> s_properties = new ArrayList>();

    static {
        s_properties.add(new Pair(BaseCmd.Properties.ID, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE));
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
Solution content
public class DeleteDiskOfferingCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteDiskOfferingCmd.class.getName());
    private static final String s_name = "deletediskofferingresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
File
DeleteDiskOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Attribute
Method invocation
Static initializer
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
    }
<<<<<<< HEAD
  
    @Override
    public ResponseObject getResponse() {
    	 SuccessResponse response = new SuccessResponse();
         Boolean responseObject = (Boolean)getResponseObject();
       
         if (responseObject != null) {
         	response.setSuccess(responseObject);
         } else {
             throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete disk offering");
         }

         response.setResponseName(getName());
         return response;
=======
    public List> getProperties() {
        return s_properties;
    }

    public List> execute(Map params) {
        Long id = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        //verify input parameters 
        DiskOfferingVO disk = getManagementServer().findDiskOfferingById(id);
        if (disk == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a disk offering with id " + id);
        }

        if(disk.getDiskSize()==0){
        	//block deletion of these disks
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR,"Cannot delete this diskoffering as it is private");
        }
        
        boolean result = getManagementServer().deleteDiskOffering(userId, id);

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.SUCCESS.getName(), Boolean.valueOf(result).toString()));
        return returnValues;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
         }
    public String getName() {
        return s_name;
    }
  
    @Override
    public ResponseObject getResponse() {
    	 SuccessResponse response = new SuccessResponse();
         Boolean responseObject = (Boolean)getResponseObject();
       
         if (responseObject != null) {
         	response.setSuccess(responseObject);
         } else {
             throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete disk offering");

         response.setResponseName(getName());
         return response;
    }
}
File
DeleteDiskOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.DeleteDomainResponse;

@Implementation(method="deleteDomain")
public class DeleteDomainCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.domain.Domain;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public class DeleteDomainCmd extends BaseCmd{
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public static final Logger s_logger = Logger.getLogger(DeleteDomainCmd.class.getName());
    private static final String s_name = "deletedomainresponse";
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.DeleteDomainResponse;

@Implementation(method="deleteDomain")
public class DeleteDomainCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteDomainCmd.class.getName());
    private static final String s_name = "deletedomainresponse";
File
DeleteDomainCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
    public ResponseObject getResponse() {
        String deleteResult = (String)getResponseObject();

<<<<<<< HEAD
        DeleteDomainResponse response = new DeleteDomainResponse();
        response.setResult(deleteResult);
=======
        // If account is null, consider System as an owner for this action
        if (account == null) {
            account = getManagementServer().findAccountById(Long.valueOf(1L));
        }

        if ((domainId.longValue() == Domain.ROOT_DOMAIN) || !getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to delete domain " + domainId + ", permission denied.");
        }

        // check if domain exists in the system
        Domain domain = getManagementServer().findDomainIdById(domainId);
    	if (domain == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find domain " + domainId);
    	}

    	long jobId = getManagementServer().deleteDomainAsync(domainId, account.getId(), cleanup); // default owner is 'system'
    	if (jobId == 0) {
    	    s_logger.warn("Unable to schedule async-job for DeleteDomain comamnd");
    	} else {
    	    if (s_logger.isDebugEnabled())
    	        s_logger.debug("DeleteDomain command has been accepted, job id: " + jobId);
    	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        response.setResponseName(getName());
        return response;
Solution content
    public ResponseObject getResponse() {
        String deleteResult = (String)getResponseObject();

        DeleteDomainResponse response = new DeleteDomainResponse();
        response.setResult(deleteResult);

        response.setResponseName(getName());
        return response;
File
DeleteDomainCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Variable
Chunk
Conflicting content
<<<<<<< HEAD

package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="deleteIpForwardingRule", manager=Manager.NetworkManager)
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.network.FirewallRuleVO;
import com.cloud.network.IPAddressVO;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
public class DeleteIPForwardingRuleCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteIPForwardingRuleCmd.class.getName());
    private static final String s_name = "deleteportforwardingruleresponse";
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="deleteIpForwardingRule", manager=Manager.NetworkManager)
public class DeleteIPForwardingRuleCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteIPForwardingRuleCmd.class.getName());
    private static final String s_name = "deleteportforwardingruleresponse";
File
DeleteIPForwardingRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Import
Chunk
Conflicting content
    public String getName() {
        return s_name;
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
	    Boolean success = (Boolean)getResponseObject();
	    SuccessResponse response = new SuccessResponse();
	    response.setSuccess(success);
	    response.setResponseName(getName());
		return response;
	}
=======
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long ruleId = (Long)params.get(BaseCmd.Properties.ID.getName());

        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        FirewallRuleVO fwRule = getManagementServer().findForwardingRuleById(ruleId);
        if (fwRule == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find port forwarding rule " + ruleId);
        }

        IPAddressVO ipAddress = getManagementServer().findIPAddressById(fwRule.getPublicIpAddress());
        if (ipAddress == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find IP address for port forwarding rule " + ruleId);
        }

        Account ruleOwner = getManagementServer().findAccountById(ipAddress.getAccountId());
        if (ruleOwner == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find owning account for port forwarding rule " + ruleId);
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!getManagementServer().isChildDomain(account.getDomainId(), ruleOwner.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to delete port forwarding rule " + ruleId + ", permission denied.");
                }
            } else if (account.getId() != ruleOwner.getId()) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to delete port forwarding rule " + ruleId + ", permission denied.");
            }
        }
        try {
            getManagementServer().deleteRule(ruleId.longValue(), userId.longValue(), ruleOwner.getId());
        } catch (InvalidParameterValueException ex1) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to delete port forwarding rule " + ruleId + ", internal error.");
        } catch (PermissionDeniedException ex2) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to delete port forwarding rule " + ruleId + ", permission denied.");
        } catch (InternalErrorException ex3) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to delete port forwarding rule " + ruleId + ", internal error.");
        }

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.SUCCESS.getName(), "true"));
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
	public ResponseObject getResponse() {
    public String getName() {
        return s_name;
    }

	@Override
	    Boolean success = (Boolean)getResponseObject();
	    SuccessResponse response = new SuccessResponse();
	    response.setSuccess(success);
	    response.setResponseName(getName());
		return response;
	}
}
File
DeleteIPForwardingRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
DeleteIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    
    public static String getStaticName() {
        return s_name;
<<<<<<< HEAD
    }
    
    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        Boolean responseObject = (Boolean)getResponseObject();
      
        if (responseObject != null) {
        	response.setSuccess(responseObject);
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete iso");
        }

        response.setResponseName(getName());
        return response;
=======
    }
    
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account) params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Long isoId = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long zoneId = (Long)params.get(BaseCmd.Properties.ZONE_ID.getName());

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        VMTemplateVO iso = getManagementServer().findTemplateById(isoId);
        if (iso == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to find ISO with given parameters.");
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (iso.getAccountId() != account.getId()) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to delete ISO with id " + isoId);
                }
            } else {
                Account isoOwner = getManagementServer().findAccountById(iso.getAccountId());
                if (!getManagementServer().isChildDomain(account.getDomainId(), isoOwner.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to delete ISO with id " + isoId + ", permission denied.");
                }
            }
        }

        try {
    		long jobId = getManagementServer().deleteIsoAsync(userId, isoId, zoneId);
    		
    		if (jobId == 0) {
            	s_logger.warn("Unable to schedule async-job for DeleteIso command");
            } else {
    	        if (s_logger.isDebugEnabled()) {
    	        	s_logger.debug("DeleteIso command has been accepted, job id: " + jobId);
    	        }
            }

    		List> returnValues = new ArrayList>();
            returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
            returnValues.add(new Pair(BaseCmd.Properties.ISO_ID.getName(), Long.valueOf(isoId))); 

            return returnValues;
    	} catch (Exception ex) {
    		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete template: " + ex.getMessage());
    	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
    
    public static String getStaticName() {
        return s_name;
    }
    
    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        Boolean responseObject = (Boolean)getResponseObject();
      
        if (responseObject != null) {
        	response.setSuccess(responseObject);
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete iso");
        }

        response.setResponseName(getName());
        return response;
    }
}
File
DeleteIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
If statement
Method declaration
Method invocation
Method signature
Return statement
Try statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="deleteLoadBalancerRule", manager=Manager.NetworkManager)
public class DeleteLoadBalancerRuleCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.network.LoadBalancerVO;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public class DeleteLoadBalancerRuleCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public static final Logger s_logger = Logger.getLogger(DeleteLoadBalancerRuleCmd.class.getName());
    private static final String s_name = "deleteloadbalancerruleresponse";
    /////////////////////////////////////////////////////
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="deleteLoadBalancerRule", manager=Manager.NetworkManager)
public class DeleteLoadBalancerRuleCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(DeleteLoadBalancerRuleCmd.class.getName());
    private static final String s_name = "deleteloadbalancerruleresponse";
    /////////////////////////////////////////////////////
File
DeleteLoadBalancerRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
    public String getName() {
        return s_name;
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
=======
    
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long loadBalancerId = (Long)params.get(BaseCmd.Properties.ID.getName());

        //Verify parameters
        LoadBalancerVO loadBalancer = getManagementServer().findLoadBalancerById(loadBalancerId.longValue());
        if (loadBalancer == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find load balancer rule, with id " + loadBalancerId);
        } else if (account != null) {
            if (!isAdmin(account.getType())) {
                if (loadBalancer.getAccountId() != account.getId()) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName() + " (id:" + loadBalancerId + ")");
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), loadBalancer.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to delete load balancer rule " + loadBalancer.getName() + " (id:" + loadBalancerId + "), permission denied.");
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long jobId = getManagementServer().deleteLoadBalancerAsync(userId, loadBalancerId.longValue());
        if (jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for DeleteLoadBalancerRule comamnd");
        } else {
	        if (s_logger.isDebugEnabled())
	        	s_logger.debug("DeleteLoadBalancerRule command has been accepted, job id: " + jobId);
        }
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
}
File
DeleteLoadBalancerRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

<<<<<<< HEAD
    public Long getId() {
        return id;
    }
=======
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != sg.getAccountId()) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a port forwarding service with id " + id + " for this account");
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), sg.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to delete port forwarding service " + id + ", permission denied.");
            }
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
Solution content
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public Long getId() {
        return id;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
File
DeletePortForwardingServiceCmd.java
Developer's decision
Version 1
Kind of conflict
If statement
Method declaration
Chunk
Conflicting content
    }
    
    @Override
<<<<<<< HEAD
    public ResponseObject getResponse() {
        UserVm userVm = (UserVm)getResponseObject();

        UserVmResponse response = new UserVmResponse();
        response.setId(userVm.getId());
        response.setName(userVm.getName());
        response.setCreated(userVm.getCreated());
        response.setZoneId(userVm.getDataCenterId());
        response.setZoneName(ApiDBUtils.findZoneById(userVm.getDataCenterId()).getName());
        response.setPrivateIp(userVm.getPrivateIpAddress());
        response.setServiceOfferingId(userVm.getServiceOfferingId());
        response.setHaEnable(userVm.isHaEnabled());
        response.setGroup(userVm.getGroup());
        if (userVm.getDisplayName() == null || userVm.getDisplayName().length() == 0) {
            response.setDisplayName(userVm.getName());
=======
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Long zoneId = (Long)params.get(BaseCmd.Properties.ZONE_ID.getName());
        Long serviceOfferingId = (Long)params.get(BaseCmd.Properties.SERVICE_OFFERING_ID.getName());
        Long diskOfferingId = (Long)params.get(BaseCmd.Properties.DISK_OFFERING_ID.getName());
        Long templateId = (Long)params.get(BaseCmd.Properties.TEMPLATE_ID.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        String displayName = (String)params.get(BaseCmd.Properties.DISPLAY_NAME.getName());
        String group = (String)params.get(BaseCmd.Properties.GROUP.getName());
        String userData = (String) params.get(BaseCmd.Properties.USER_DATA.getName());
        String networkGroupList = (String)params.get(BaseCmd.Properties.NETWORK_GROUP_LIST.getName());
        Long size = (Long)params.get(BaseCmd.Properties.SIZE.getName());
        String password = null;
        Long accountId = null;
        
        //don't accept empty group names
        if (group != null && group.isEmpty())
        	group = null;

        if(size == null)
        	size = Long.valueOf(0);
        
        VMTemplateVO template = getManagementServer().findTemplateById(templateId);
        if (template == null) {
            throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "Unable to find template with id " + templateId);
        }

    	if (diskOfferingId != null) {
    	    DiskOfferingVO diskOffering = getManagementServer().findDiskOfferingById(diskOfferingId);
    	    if ((diskOffering == null) || !DiskOfferingVO.Type.Disk.equals(diskOffering.getType())) {
                throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, "Disk offering with id " + diskOfferingId + " doesn't exist in the system");
    	    }
    	    
        	//if disk offering is set to use local storage, and local_storage is disabled, block vm deployment    	    
    	    if(diskOffering.getUseLocalStorage())
    	    {
    	    	boolean errFlag = getManagementServer().checkLocalStorageConfigVal();
    	    	
    	    	if(!errFlag)
    	    		throw new ServerApiException (BaseCmd.VM_DEPLOY_ERROR,"Please set the local storage flag to true as disk offering has local storage usage enabled");
    	    }
    	}
    	
        DataCenterVO zone = getManagementServer().findDataCenterById(zoneId);
        if (zone == null) {
        	throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, "Zone with id " + zoneId + " doesn't exist in the system");
        }

        ServiceOfferingVO serviceOffering = getManagementServer().findServiceOfferingById(serviceOfferingId);
        if (serviceOffering == null ) {
        	throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, "Service offering with id " + serviceOfferingId + " doesn't exist in the system");
        }

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") ");
                }
                if (accountName != null) {
                    Account userAccount = getManagementServer().findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((account != null) ? account.getId() : null);
            }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        } else {
            response.setDisplayName(userVm.getDisplayName());
        }
Solution content
    }
    
    @Override
    public ResponseObject getResponse() {
        UserVm userVm = (UserVm)getResponseObject();

        UserVmResponse response = new UserVmResponse();
        response.setId(userVm.getId());
        response.setName(userVm.getName());
        response.setCreated(userVm.getCreated());
        response.setZoneId(userVm.getDataCenterId());
        response.setZoneName(ApiDBUtils.findZoneById(userVm.getDataCenterId()).getName());
        response.setPrivateIp(userVm.getPrivateIpAddress());
        response.setServiceOfferingId(userVm.getServiceOfferingId());
        response.setHaEnable(userVm.isHaEnabled());

        InstanceGroupVO group = ApiDBUtils.findInstanceGroupForVM(userVm.getId());
        if (group != null) {
            response.setGroup(group.getName());
            response.setGroupId(group.getId());
        }

        if (userVm.getDisplayName() == null || userVm.getDisplayName().length() == 0) {
            response.setDisplayName(userVm.getName());
        } else {
            response.setDisplayName(userVm.getDisplayName());
        }
File
DeployVMCmd.java
Developer's decision
Manual
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="destroyVm", manager=Manager.UserVmManager)
public class DestroyVMCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.UserVmVO;

public class DestroyVMCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public static final Logger s_logger = Logger.getLogger(DestroyVMCmd.class.getName());

    private static final String s_name = "destroyvirtualmachineresponse";
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="destroyVm", manager=Manager.UserVmManager)
public class DestroyVMCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(DestroyVMCmd.class.getName());

    private static final String s_name = "destroyvirtualmachineresponse";
File
DestroyVMCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
    @Parameter(name="id", type=CommandType.LONG, required=true)
    private Long id;

<<<<<<< HEAD
    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////
=======
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + "for this account");
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to destroy virtual machine with id " + vmId + ", permission denied.");
            }
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    public Long getId() {
        return id;
Solution content
    @Parameter(name="id", type=CommandType.LONG, required=true)
    private Long id;

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public Long getId() {
        return id;
File
DestroyVMCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="detachIso", manager=Manager.TemplateManager)
public class DetachIsoCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.UserVmVO;

public class DetachIsoCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public static final Logger s_logger = Logger.getLogger(DetachIsoCmd.class.getName());

    private static final String s_name = "detachisoresponse";
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="detachIso", manager=Manager.TemplateManager)
public class DetachIsoCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(DetachIsoCmd.class.getName());

    private static final String s_name = "detachisoresponse";
File
DetachIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
    @Parameter(name="virtualmachineid", type=CommandType.LONG, required=true)
    private Long virtualMachineId;

<<<<<<< HEAD
=======
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != vmInstanceCheck.getAccountId()) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to detach ISO from virtual machine " + vmInstanceCheck.getName() + " for this account");
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstanceCheck.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to detach ISO from virtual machine " + vmInstanceCheck.getName() + ", permission denied.");
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null)
            userId = new Long(1);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
Solution content
    @Parameter(name="virtualmachineid", type=CommandType.LONG, required=true)
    private Long virtualMachineId;

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
File
DetachIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Chunk
Conflicting content
	public static final Logger s_logger = Logger.getLogger(DetachVolumeCmd.class.getName());
    private static final String s_name = "detachvolumeresponse";

<<<<<<< HEAD
    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="id", type=CommandType.LONG, required=true)
    private Long id;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public Long getId() {
        return id;
=======
    static {
    	s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.DEVICE_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_ID, Boolean.FALSE));
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }

Solution content
	public static final Logger s_logger = Logger.getLogger(DetachVolumeCmd.class.getName());
    private static final String s_name = "detachvolumeresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="id", type=CommandType.LONG)
    private Long id;

    @Parameter(name="deviceid", type=CommandType.LONG)
    private Long deviceId;

    @Parameter(name="virtualmachineid", type=CommandType.LONG)
    private Long virtualMachineId;

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public Long getId() {
        return id;
    }

    public Long getDeviceId() {
        return deviceId;
    }

    public Long getVirtualMachineId() {
        return virtualMachineId;
    }
File
DetachVolumeCmd.java
Developer's decision
Manual
Kind of conflict
Annotation
Attribute
Comment
Method invocation
Method signature
Return statement
Static initializer
Chunk
Conflicting content
	@Override
	public ResponseObject getResponse() {
    public static String getResultObjectName() {
    	return "volume";
    }
<<<<<<< HEAD

        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
=======
    
    @Override
    public List> execute(Map params) {
    	Account account = (Account) params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
    	Long volumeId = (Long) params.get(BaseCmd.Properties.ID.getName());
    	Long deviceId = (Long) params.get(BaseCmd.Properties.DEVICE_ID.getName());
    	Long instanceId = (Long) params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
    	VolumeVO volume = null;
    	
    	if((volumeId==null && (deviceId==null && instanceId==null)) || (volumeId!=null && (deviceId!=null || instanceId!=null)) || (volumeId==null && (deviceId==null || instanceId==null)))
    	{
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide either a volume id, or a tuple(device id, instance id)");
    	}

    	if(volumeId!=null)
    	{
    		deviceId = instanceId = Long.valueOf("0");
    	}
    	else
    	{
    		volumeId = Long.valueOf("0");;
    	}
    	
    	boolean isAdmin;
    	if (account == null) {
    		// Admin API call
    		isAdmin = true;
    	} else {
    		// User API call
    		isAdmin = isAdmin(account.getType());
    	}

    	// Check that the volume ID is valid
    	if(volumeId != 0)
    	{
    		volume = getManagementServer().findVolumeById(volumeId);
    		if (volume == null)
    			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId);
    	}
    	else
    	{
    		volume = getManagementServer().findVolumeByInstanceAndDeviceId(instanceId, deviceId);
    		if (volume == null)
    			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId);
    	}

    	// If the account is not an admin, check that the volume is owned by the account that was passed in
    	if (!isAdmin) {
    		if (account.getId() != volume.getAccountId())
    			throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId + " for account: " + account.getAccountName());
    	} else if (account != null) {
    	    if (!getManagementServer().isChildDomain(account.getDomainId(), volume.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to detach volume with ID: " + volumeId + ", permission denied.");
    	    }
    	}

    	try {
    		long jobId = getManagementServer().detachVolumeFromVMAsync(volumeId,deviceId,instanceId);

    		if (jobId == 0) {
            	s_logger.warn("Unable to schedule async-job for DetachVolume comamnd");
            } else {
    	        if(s_logger.isDebugEnabled())
    	        	s_logger.debug("DetachVolume command has been accepted, job id: " + jobId);
            }

    		List> returnValues = new ArrayList>();
            returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 

            return returnValues;
    	} catch (Exception ex) {
    		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to detach volume: " + ex.getMessage());
    	}
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public static String getResultObjectName() {
    	return "volume";
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
}
File
DetachVolumeCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import java.util.Map;
 */
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
 */
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
DisableAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
=======
    public List> execute(Map params) {
        Account adminAccount = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());

        if ((adminAccount != null) && !getManagementServer().isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to disable account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = getManagementServer().findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not disable system account");
        }

        long jobId = getManagementServer().disableAccountAsync(account.getId());
        if (jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for DisableAccount comamnd");
        } else {
	        if (s_logger.isDebugEnabled())
	        	s_logger.debug("DisableAccount command has been accepted, job id: " + jobId);
        }

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
        response.setResponseName(getName());
    }

    @Override
    public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        return response;
    }
}
File
DisableAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Cast expression
Comment
If statement
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
DisableUserCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

<<<<<<< HEAD
    public Long getId() {
        return id;
    }
=======
        // If the user is a System user, return an error.  We do not allow this
        Account account = getManagementServer().findAccountById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is a system user, disabling is not allowed");
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590


    /////////////////////////////////////////////////////
Solution content
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public Long getId() {
        return id;
    }

    /////////////////////////////////////////////////////
File
DisableUserCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method declaration
Method invocation
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
DisassociateIPAddrCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

<<<<<<< HEAD
    public String getIpAddress() {
        return ipAddress;
    }
=======
        Long accountId = accountByIp.getId();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != accountId.longValue()) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + ipAddress);
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), accountByIp.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to disassociate IP address " + ipAddress + ", permission denied.");
            }
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590


    /////////////////////////////////////////////////////
Solution content
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public String getIpAddress() {
        return ipAddress;
    }

    /////////////////////////////////////////////////////
File
DisassociateIPAddrCmd.java
Developer's decision
Version 1
Kind of conflict
If statement
Method declaration
Method invocation
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
EnableAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to enable account");
        }

<<<<<<< HEAD
        response.setResponseName(getName());
        return response;
=======
        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not enable system account");
        }

        boolean success = true;
        try {
            success = getManagementServer().enableAccount(account.getId());
        } catch (Exception ex) {
            s_logger.error("error enabling account " + accountName + " in domain " + domainId, ex);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error enabling account " + accountName + " in domain " + domainId);
        }

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.SUCCESS.getName(), Boolean.valueOf(success).toString()));
        return returnValues;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to enable account");
        }

        response.setResponseName(getName());
        return response;
    }
}
File
EnableAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Return statement
Try statement
Variable
Chunk
Conflicting content
import com.cloud.api.response.AccountResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.configuration.ResourceCount.ResourceType;
<<<<<<< HEAD
=======
import com.cloud.domain.Domain;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.server.Criteria;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
Solution content
import com.cloud.api.response.AccountResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.server.Criteria;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
File
ListAccountsCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.uservm.UserVm;
import com.cloud.vm.State;

<<<<<<< HEAD
@Implementation(method="searchForAccounts")
public class ListAccountsCmd extends BaseListCmd {
	public static final Logger s_logger = Logger.getLogger(ListAccountsCmd.class.getName());
    private static final String s_name = "listaccountsresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="account", type=CommandType.STRING)
    private String accountName;

    @Parameter(name="accounttype", type=CommandType.LONG)
    private Long accountType;

    @Parameter(name="domainid", type=CommandType.LONG)
    private Long domainId;

    @Parameter(name="id", type=CommandType.LONG)
    private Long id;

    @Parameter(name="iscleanuprequired", type=CommandType.BOOLEAN)
    private Boolean cleanupRequired;

    @Parameter(name="name", type=CommandType.STRING)
    private String searchName;

    @Parameter(name="state", type=CommandType.STRING)
    private String state;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public String getAccountName() {
        return accountName;
    }

    public Long getAccountType() {
        return accountType;
    }

    public Long getDomainId() {
        return domainId;
    }

    public Long getId() {
        return id;
    }

    public Boolean isCleanupRequired() {
        return cleanupRequired;
    }

    public String getSearchName() {
        return searchName;
    }

    public String getState() {
        return state;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List accounts = (List)getResponseObject();

        ListResponse response = new ListResponse();

        List accountResponses = new ArrayList();
        for (AccountVO account : accounts) {
            boolean accountIsAdmin = (account.getType() == Account.ACCOUNT_TYPE_ADMIN);

            AccountResponse acctResponse = new AccountResponse();
            acctResponse.setId(account.getId());
            acctResponse.setName(account.getAccountName());
            acctResponse.setAccountType(account.getType());
            acctResponse.setDomainId(account.getDomainId());
            acctResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());

            //get network stat
            List stats = ApiDBUtils.listUserStatsBy(account.getId());
=======
public class ListAccountsCmd extends BaseCmd{
	public static final Logger s_logger = Logger.getLogger(ListAccountsCmd.class.getName());
    private static final String s_name = "listaccountsresponse";
    private static final List> s_properties = new ArrayList>();

    static {
    	s_properties.add(new Pair(BaseCmd.Properties.ID, Boolean.FALSE));
    	s_properties.add(new Pair(BaseCmd.Properties.NAME, Boolean.FALSE));
    	s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_TYPE, Boolean.FALSE));
    	s_properties.add(new Pair(BaseCmd.Properties.STATE, Boolean.FALSE));
    	s_properties.add(new Pair(BaseCmd.Properties.IS_CLEANUP_REQUIRED, Boolean.FALSE));
    	s_properties.add(new Pair(BaseCmd.Properties.KEYWORD, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.DOMAIN_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.PAGE, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.PAGESIZE, Boolean.FALSE));
    }

    public String getName() {
        return s_name;
    }
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
    	Long id = (Long)params.get(BaseCmd.Properties.ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        Long type = (Long)params.get(BaseCmd.Properties.ACCOUNT_TYPE.getName());
        String state = (String)params.get(BaseCmd.Properties.STATE.getName()); 
        Boolean needCleanup = (Boolean)params.get(BaseCmd.Properties.IS_CLEANUP_REQUIRED.getName());
        Integer page = (Integer)params.get(BaseCmd.Properties.PAGE.getName());
        Integer pageSize = (Integer)params.get(BaseCmd.Properties.PAGESIZE.getName());
        String keyword = (String)params.get(BaseCmd.Properties.KEYWORD.getName());
        boolean isAdmin = false;
		Long accountId = null;

        String accountName = null;

        if ((account == null) || isAdmin(account.getType())) {
        	accountName = (String)params.get(BaseCmd.Properties.NAME.getName());
        	isAdmin = true;
        	if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? Domain.ROOT_DOMAIN : account.getDomainId());
        	} else if (account != null) {
        	    if (!getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
        	        throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
        	    }
        	}
        } else {
        	accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        	accountId = account.getId();
        }

        Long startIndex = Long.valueOf(0);
        int pageSizeNum = 50;
    	if (pageSize != null) {
    		pageSizeNum = pageSize.intValue();
    	}
        if (page != null) {
            int pageNum = page.intValue();
            if (pageNum > 0) {
                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
            }
        }
        Criteria c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum));
		if (isAdmin == true) {
			c.addCriteria(Criteria.ID, id);
			if (keyword == null) {
				c.addCriteria(Criteria.ACCOUNTNAME, accountName);
				c.addCriteria(Criteria.DOMAINID, domainId);
				c.addCriteria(Criteria.TYPE, type);
				c.addCriteria(Criteria.STATE, state);
				c.addCriteria(Criteria.ISCLEANUPREQUIRED, needCleanup);
			} else {
				c.addCriteria(Criteria.KEYWORD, keyword);
			}
		} else {
			c.addCriteria(Criteria.ID, accountId);
		}

        List accounts = getManagementServer().searchForAccounts(c);

        List> accountTags = new ArrayList>();
        Object[] aTag = new Object[accounts.size()];
        int i = 0;
        for (AccountVO accountO : accounts) {
        	boolean accountIsAdmin = (accountO.getType() == Account.ACCOUNT_TYPE_ADMIN);
        	
    		List> accountData = new ArrayList>();
            accountData.add(new Pair(BaseCmd.Properties.ID.getName(), Long.valueOf(accountO.getId()).toString()));
            accountData.add(new Pair(BaseCmd.Properties.NAME.getName(), accountO.getAccountName()));
            accountData.add(new Pair(BaseCmd.Properties.ACCOUNT_TYPE.getName(), Short.valueOf(accountO.getType()).toString()));
                Domain domain = getManagementServer().findDomainIdById(accountO.getDomainId());
                accountData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), Long.toString(domain.getId())));
            accountData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), domain.getName()));

            //get network stat
            List stats = getManagementServer().listUserStatsBy(accountO.getId());
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            if (stats == null) {
                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching for user stats");
            }
Solution content

import com.cloud.uservm.UserVm;
import com.cloud.vm.State;

@Implementation(method="searchForAccounts")
public class ListAccountsCmd extends BaseListCmd {
	public static final Logger s_logger = Logger.getLogger(ListAccountsCmd.class.getName());
    private static final String s_name = "listaccountsresponse";
        return searchName;
    }
    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="account", type=CommandType.STRING)
    private String accountName;

    @Parameter(name="accounttype", type=CommandType.LONG)
    private Long accountType;

    @Parameter(name="domainid", type=CommandType.LONG)
    private Long domainId;

    @Parameter(name="id", type=CommandType.LONG)
    private Long id;

    @Parameter(name="iscleanuprequired", type=CommandType.BOOLEAN)
    private Boolean cleanupRequired;

    @Parameter(name="name", type=CommandType.STRING)
    private String searchName;

    @Parameter(name="state", type=CommandType.STRING)
    private String state;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public String getAccountName() {
        return accountName;
    }

    public Long getAccountType() {
        return accountType;
    }

    public Long getDomainId() {
        return domainId;
    }

    public Long getId() {
        return id;
    }

    public Boolean isCleanupRequired() {
        return cleanupRequired;
    }

    public String getSearchName() {
    public String getState() {
        return state;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List accounts = (List)getResponseObject();

        ListResponse response = new ListResponse();

        List accountResponses = new ArrayList();
        for (AccountVO account : accounts) {
            boolean accountIsAdmin = (account.getType() == Account.ACCOUNT_TYPE_ADMIN);

            AccountResponse acctResponse = new AccountResponse();
            acctResponse.setId(account.getId());
            acctResponse.setName(account.getAccountName());
            acctResponse.setAccountType(account.getType());
            acctResponse.setDomainId(account.getDomainId());
            acctResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());

            //get network stat
            List stats = ApiDBUtils.listUserStatsBy(account.getId());
            if (stats == null) {
                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching for user stats");
            }
File
ListAccountsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Attribute
Cast expression
Class signature
Comment
For statement
If statement
Method declaration
Method invocation
Method signature
Static initializer
Variable
Chunk
Conflicting content
            long bytesSent = 0;
            long bytesReceived = 0;
            for (UserStatisticsVO stat : stats) {
<<<<<<< HEAD
                long rx = stat.getNetBytesReceived() + stat.getCurrentBytesReceived();
                long tx = stat.getNetBytesSent() + stat.getCurrentBytesSent();
                bytesReceived = bytesReceived + Long.valueOf(rx);
                bytesSent = bytesSent + Long.valueOf(tx);
            }
            acctResponse.setBytesReceived(bytesReceived);
            acctResponse.setBytesSent(bytesSent);

            // Get resource limits and counts
            
            long vmLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.user_vm, account.getId());
            String vmLimitDisplay = (accountIsAdmin || vmLimit == -1) ? "Unlimited" : String.valueOf(vmLimit);
            long vmTotal = ApiDBUtils.getResourceCount(ResourceType.user_vm, account.getId());
            String vmAvail = (accountIsAdmin || vmLimit == -1) ? "Unlimited" : String.valueOf(vmLimit - vmTotal);
            acctResponse.setVmLimit(vmLimitDisplay);
            acctResponse.setVmTotal(vmTotal);
            acctResponse.setVmAvailable(vmAvail);
            
            long ipLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.public_ip, account.getId());
            String ipLimitDisplay = (accountIsAdmin || ipLimit == -1) ? "Unlimited" : String.valueOf(ipLimit);
            long ipTotal = ApiDBUtils.getResourceCount(ResourceType.public_ip, account.getId());
            String ipAvail = (accountIsAdmin || ipLimit == -1) ? "Unlimited" : String.valueOf(ipLimit - ipTotal);
            acctResponse.setIpLimit(ipLimitDisplay);
            acctResponse.setIpTotal(ipTotal);
            acctResponse.setIpAvailable(ipAvail);
            
            long volumeLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.volume, account.getId());
            String volumeLimitDisplay = (accountIsAdmin || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit);
            long volumeTotal = ApiDBUtils.getResourceCount(ResourceType.volume, account.getId());
            String volumeAvail = (accountIsAdmin || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit - volumeTotal);
            acctResponse.setVolumeLimit(volumeLimitDisplay);
            acctResponse.setVolumeTotal(volumeTotal);
            acctResponse.setVolumeAvailable(volumeAvail);
            
            long snapshotLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.snapshot, account.getId());
            String snapshotLimitDisplay = (accountIsAdmin || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit);
            long snapshotTotal = ApiDBUtils.getResourceCount(ResourceType.snapshot, account.getId());
            String snapshotAvail = (accountIsAdmin || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit - snapshotTotal);
            acctResponse.setSnapshotLimit(snapshotLimitDisplay);
            acctResponse.setSnapshotTotal(snapshotTotal);
            acctResponse.setSnapshotAvailable(snapshotAvail);
            
            long templateLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.template, account.getId());
            String templateLimitDisplay = (accountIsAdmin || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit);
            long templateTotal = ApiDBUtils.getResourceCount(ResourceType.template, account.getId());
            String templateAvail = (accountIsAdmin || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit - templateTotal);
            acctResponse.setTemplateLimit(templateLimitDisplay);
            acctResponse.setTemplateTotal(templateTotal);
            acctResponse.setTemplateAvailable(templateAvail);
            
            // Get stopped and running VMs
            int vmStopped = 0;
            int vmRunning = 0;

            Long[] accountIds = new Long[1];
            accountIds[0] = account.getId();

            Criteria c1 = new Criteria();
            c1.addCriteria(Criteria.ACCOUNTID, accountIds);
            List virtualMachines = ApiDBUtils.searchForUserVMs(c1);

            //get Running/Stopped VMs
            for (Iterator iter = virtualMachines.iterator(); iter.hasNext();) {
                // count how many stopped/running vms we have
                UserVm vm = iter.next();

                if (vm.getState() == State.Stopped) {
                    vmStopped++;
                } else if (vm.getState() == State.Running) {
                    vmRunning++;
                }
            }

            acctResponse.setVmStopped(vmStopped);
            acctResponse.setVmRunning(vmRunning);

            //show this info to admins only
            Account ctxAccount = (Account)UserContext.current().getAccountObject();
            if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
                acctResponse.setState(account.getState());
                acctResponse.setCleanupRequired(account.getNeedsCleanup());
            }

            acctResponse.setResponseName("account");
            accountResponses.add(acctResponse);
        }

        response.setResponses(accountResponses);
        response.setResponseName(getName());
        return response;
    }
}
=======
            	long rx = stat.getNetBytesReceived() + stat.getCurrentBytesReceived();
    			long tx = stat.getNetBytesSent() + stat.getCurrentBytesSent();
                bytesReceived = bytesReceived + Long.valueOf(rx);
                bytesSent = bytesSent + Long.valueOf(tx);
            }
            accountData.add(new Pair(BaseCmd.Properties.BYTES_RECEIVED.getName(), Long.valueOf(bytesReceived).toString()));
            accountData.add(new Pair(BaseCmd.Properties.BYTES_SENT.getName(), Long.valueOf(bytesSent).toString()));

            // Get resource limits and counts
            
            long vmLimit = getManagementServer().findCorrectResourceLimit(ResourceType.user_vm, accountO.getId());
            String vmLimitDisplay = (accountIsAdmin || vmLimit == -1) ? "Unlimited" : String.valueOf(vmLimit);
            long vmTotal = getManagementServer().getResourceCount(ResourceType.user_vm, accountO.getId());
            String vmAvail = (accountIsAdmin || vmLimit == -1) ? "Unlimited" : String.valueOf(vmLimit - vmTotal);
            accountData.add(new Pair(BaseCmd.Properties.VM_LIMIT.getName(), vmLimitDisplay));
            accountData.add(new Pair(BaseCmd.Properties.VM_TOTAL.getName(), vmTotal));
            accountData.add(new Pair(BaseCmd.Properties.VM_AVAIL.getName(), vmAvail));
            
            long ipLimit = getManagementServer().findCorrectResourceLimit(ResourceType.public_ip, accountO.getId());
            String ipLimitDisplay = (accountIsAdmin || ipLimit == -1) ? "Unlimited" : String.valueOf(ipLimit);
            long ipTotal = getManagementServer().getResourceCount(ResourceType.public_ip, accountO.getId());
            String ipAvail = (accountIsAdmin || ipLimit == -1) ? "Unlimited" : String.valueOf(ipLimit - ipTotal);
            accountData.add(new Pair(BaseCmd.Properties.IP_LIMIT.getName(), ipLimitDisplay));
            accountData.add(new Pair(BaseCmd.Properties.IP_TOTAL.getName(), ipTotal));
            accountData.add(new Pair(BaseCmd.Properties.IP_AVAIL.getName(), ipAvail));
            
            long volumeLimit = getManagementServer().findCorrectResourceLimit(ResourceType.volume, accountO.getId());
            String volumeLimitDisplay = (accountIsAdmin || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit);
            long volumeTotal = getManagementServer().getResourceCount(ResourceType.volume, accountO.getId());
            String volumeAvail = (accountIsAdmin || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit - volumeTotal);
            accountData.add(new Pair(BaseCmd.Properties.VOLUME_LIMIT.getName(), volumeLimitDisplay));
            accountData.add(new Pair(BaseCmd.Properties.VOLUME_TOTAL.getName(), volumeTotal));
            accountData.add(new Pair(BaseCmd.Properties.VOLUME_AVAIL.getName(), volumeAvail));
            
            long snapshotLimit = getManagementServer().findCorrectResourceLimit(ResourceType.snapshot, accountO.getId());
            String snapshotLimitDisplay = (accountIsAdmin || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit);
            long snapshotTotal = getManagementServer().getResourceCount(ResourceType.snapshot, accountO.getId());
            String snapshotAvail = (accountIsAdmin || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit - snapshotTotal);
            accountData.add(new Pair(BaseCmd.Properties.SNAPSHOT_LIMIT.getName(), snapshotLimitDisplay));
            accountData.add(new Pair(BaseCmd.Properties.SNAPSHOT_TOTAL.getName(), snapshotTotal));
            accountData.add(new Pair(BaseCmd.Properties.SNAPSHOT_AVAIL.getName(), snapshotAvail));
            
            long templateLimit = getManagementServer().findCorrectResourceLimit(ResourceType.template, accountO.getId());
            String templateLimitDisplay = (accountIsAdmin || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit);
            long templateTotal = getManagementServer().getResourceCount(ResourceType.template, accountO.getId());
            String templateAvail = (accountIsAdmin || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit - templateTotal);
            accountData.add(new Pair(BaseCmd.Properties.TEMPLATE_LIMIT.getName(), templateLimitDisplay));
            accountData.add(new Pair(BaseCmd.Properties.TEMPLATE_TOTAL.getName(), templateTotal));
            accountData.add(new Pair(BaseCmd.Properties.TEMPLATE_AVAIL.getName(), templateAvail));
            
    	    // Get stopped and running VMs

    	    int vmStopped = 0;
    	    int vmRunning = 0;

    	    Long[] accountIds = new Long[1];
    	    accountIds[0] = accountO.getId();

    	    Criteria c1 = new Criteria();
    	    c1.addCriteria(Criteria.ACCOUNTID, accountIds);
    	    List virtualMachines = getManagementServer().searchForUserVMs(c1);

    	    //get Running/Stopped VMs
    	    for (Iterator iter = virtualMachines.iterator(); iter.hasNext();) {
    	    	// count how many stopped/running vms we have
    		    UserVm vm = iter.next();

    		  	if (vm.getState() == State.Stopped) {
    		  		vmStopped++;
    		  	} else if (vm.getState() == State.Running) {
    		  		vmRunning++;
    		  	}
    	    }

    	    accountData.add(new Pair(BaseCmd.Properties.VM_STOPPED.getName(), vmStopped));
    	    accountData.add(new Pair(BaseCmd.Properties.VM_RUNNING.getName(), vmRunning));

    	    //show this info to admins only
    	    if (isAdmin == true) {
    	    	accountData.add(new Pair(BaseCmd.Properties.STATE.getName(), accountO.getState()));
                accountData.add(new Pair(BaseCmd.Properties.IS_CLEANUP_REQUIRED.getName(), Boolean.valueOf(accountO.getNeedsCleanup()).toString()));
    	    }

            aTag[i++] = accountData;
        }
        Pair accountTag = new Pair("account", aTag);
        accountTags.add(accountTag);
        return accountTags;
    }
}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
Solution content
            long bytesSent = 0;
            long bytesReceived = 0;
            for (UserStatisticsVO stat : stats) {
                long rx = stat.getNetBytesReceived() + stat.getCurrentBytesReceived();
                long tx = stat.getNetBytesSent() + stat.getCurrentBytesSent();
                bytesReceived = bytesReceived + Long.valueOf(rx);
                bytesSent = bytesSent + Long.valueOf(tx);
            }
            acctResponse.setBytesReceived(bytesReceived);
            acctResponse.setBytesSent(bytesSent);

            // Get resource limits and counts
            
            long vmLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.user_vm, account.getId());
            String vmLimitDisplay = (accountIsAdmin || vmLimit == -1) ? "Unlimited" : String.valueOf(vmLimit);
            long vmTotal = ApiDBUtils.getResourceCount(ResourceType.user_vm, account.getId());
            String vmAvail = (accountIsAdmin || vmLimit == -1) ? "Unlimited" : String.valueOf(vmLimit - vmTotal);
            acctResponse.setVmLimit(vmLimitDisplay);
            acctResponse.setVmTotal(vmTotal);
            acctResponse.setVmAvailable(vmAvail);
            
            long ipLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.public_ip, account.getId());
            String ipLimitDisplay = (accountIsAdmin || ipLimit == -1) ? "Unlimited" : String.valueOf(ipLimit);
            long ipTotal = ApiDBUtils.getResourceCount(ResourceType.public_ip, account.getId());
            String ipAvail = (accountIsAdmin || ipLimit == -1) ? "Unlimited" : String.valueOf(ipLimit - ipTotal);
            acctResponse.setIpLimit(ipLimitDisplay);
            acctResponse.setIpTotal(ipTotal);
            acctResponse.setIpAvailable(ipAvail);
            
            long volumeLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.volume, account.getId());
            String volumeLimitDisplay = (accountIsAdmin || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit);
            long volumeTotal = ApiDBUtils.getResourceCount(ResourceType.volume, account.getId());
            String volumeAvail = (accountIsAdmin || volumeLimit == -1) ? "Unlimited" : String.valueOf(volumeLimit - volumeTotal);
            acctResponse.setVolumeLimit(volumeLimitDisplay);
            acctResponse.setVolumeTotal(volumeTotal);
            acctResponse.setVolumeAvailable(volumeAvail);
            
            long snapshotLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.snapshot, account.getId());
            String snapshotLimitDisplay = (accountIsAdmin || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit);
            long snapshotTotal = ApiDBUtils.getResourceCount(ResourceType.snapshot, account.getId());
            String snapshotAvail = (accountIsAdmin || snapshotLimit == -1) ? "Unlimited" : String.valueOf(snapshotLimit - snapshotTotal);
            acctResponse.setSnapshotLimit(snapshotLimitDisplay);
            acctResponse.setSnapshotTotal(snapshotTotal);
            acctResponse.setSnapshotAvailable(snapshotAvail);
            
            long templateLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.template, account.getId());
            String templateLimitDisplay = (accountIsAdmin || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit);
            long templateTotal = ApiDBUtils.getResourceCount(ResourceType.template, account.getId());
            String templateAvail = (accountIsAdmin || templateLimit == -1) ? "Unlimited" : String.valueOf(templateLimit - templateTotal);
            acctResponse.setTemplateLimit(templateLimitDisplay);
            acctResponse.setTemplateTotal(templateTotal);
            acctResponse.setTemplateAvailable(templateAvail);
            
            // Get stopped and running VMs
            int vmStopped = 0;
            int vmRunning = 0;

            Long[] accountIds = new Long[1];
            accountIds[0] = account.getId();

            Criteria c1 = new Criteria();
            c1.addCriteria(Criteria.ACCOUNTID, accountIds);
            List virtualMachines = ApiDBUtils.searchForUserVMs(c1);

            //get Running/Stopped VMs
            for (Iterator iter = virtualMachines.iterator(); iter.hasNext();) {
                // count how many stopped/running vms we have
                UserVm vm = iter.next();

                if (vm.getState() == State.Stopped) {
                    vmStopped++;
                } else if (vm.getState() == State.Running) {
                    vmRunning++;
                }
            }

            acctResponse.setVmStopped(vmStopped);
            acctResponse.setVmRunning(vmRunning);

            //show this info to admins only
            Account ctxAccount = (Account)UserContext.current().getAccountObject();
            if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
                acctResponse.setState(account.getState());
                acctResponse.setCleanupRequired(account.getNeedsCleanup());
            }

            acctResponse.setResponseName("account");
            accountResponses.add(acctResponse);
        }

        response.setResponses(accountResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListAccountsCmd.java
Developer's decision
Version 1
Kind of conflict
Array access
Cast expression
Comment
For statement
If statement
Method invocation
Return statement
Variable
Chunk
Conflicting content
        for (AlertVO alert : alertList) {
import org.apache.log4j.Logger;

import com.cloud.alert.AlertVO;
<<<<<<< HEAD
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.AlertResponse;
import com.cloud.api.response.ListResponse;

@Implementation(method="searchForAlerts")
public class ListAlertsCmd extends BaseListCmd {

    public static final Logger s_logger = Logger.getLogger(ListAlertsCmd.class.getName());

    private static final String s_name = "listalertsresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="type", type=CommandType.STRING)
    private String type;


    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public String getType() {
        return type;
    }


    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List alertList = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List alertResponseList = new ArrayList();
            AlertResponse alertResponse = new AlertResponse();
            alertResponse.setAlertType(alert.getType());
            alertResponse.setDescription(alert.getSubject());
            alertResponse.setLastSent(alert.getLastSent());

            alertResponse.setResponseName("alert");
            alertResponseList.add(alertResponse);
        }

        response.setResponses(alertResponseList);
        response.setResponseName(getName());
        return response;
    }
}
=======
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.server.Criteria;
import com.cloud.utils.Pair;

public class ListAlertsCmd extends BaseCmd{
	
	   public static final Logger s_logger = Logger.getLogger(ListAlertsCmd.class.getName());

	    private static final String s_name = "listalertsresponse";
	    private static final List> s_properties = new ArrayList>();
	    
	    public String getName() {
	        return s_name;
	    }
	    public List> getProperties() {
	        return s_properties;
	    }
	    
	    static {
	    	s_properties.add(new Pair(BaseCmd.Properties.TYPE, Boolean.FALSE));
	    	s_properties.add(new Pair(BaseCmd.Properties.KEYWORD, Boolean.FALSE));
	    	s_properties.add(new Pair(BaseCmd.Properties.PAGE, Boolean.FALSE));
	    	s_properties.add(new Pair(BaseCmd.Properties.PAGESIZE, Boolean.FALSE));
	    }

	    
	    @Override
	    public List> execute(Map params) {
	    	String alertType = (String)params.get(BaseCmd.Properties.TYPE.getName());
	    	String keyword = (String)params.get(BaseCmd.Properties.KEYWORD.getName());
	    	Integer page = (Integer)params.get(BaseCmd.Properties.PAGE.getName());
	    	Integer pageSize = (Integer)params.get(BaseCmd.Properties.PAGESIZE.getName());
	    	
	    	Long startIndex = Long.valueOf(0);
	        int pageSizeNum = 50;
	    	if (pageSize != null) {
	    		pageSizeNum = pageSize.intValue();
	    	}
	        if (page != null) {
	            int pageNum = page.intValue();
	            if (pageNum > 0) {
	                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
	            }
	        }
	        
	        Criteria c = new Criteria ("lastSent", Boolean.FALSE, startIndex, Long.valueOf(pageSizeNum));
	        c.addCriteria(Criteria.KEYWORD, keyword);
	        
	        if (keyword == null)
	        	c.addCriteria(Criteria.TYPE, alertType);
	        
	        List alerts = getManagementServer().searchForAlerts(c);
	        
	        if (alerts == null ) {
	        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find alerts");
	        }
	        
	        List> alertsTags = new ArrayList>();
	        Object[] aTag = new Object[alerts.size()];
	        int i=0;
	        
	        for (AlertVO alert : alerts) {
	        	List> alertData = new ArrayList>();
	        	alertData.add(new Pair(BaseCmd.Properties.TYPE.getName(), alert.getType()));
	        	alertData.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), alert.getSubject()));
	            alertData.add(new Pair(BaseCmd.Properties.SENT.getName(), getDateString(alert.getLastSent())));
	            aTag[i++] = alertData;
	        }
	        
	        Pair alertTag = new Pair("alert", aTag);
	        alertsTags.add(alertTag);
	        return alertsTags;

	    }
}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
Solution content
    }

import org.apache.log4j.Logger;

import com.cloud.alert.AlertVO;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.AlertResponse;
import com.cloud.api.response.ListResponse;

@Implementation(method="searchForAlerts")
public class ListAlertsCmd extends BaseListCmd {

    public static final Logger s_logger = Logger.getLogger(ListAlertsCmd.class.getName());

    private static final String s_name = "listalertsresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
    /////////////////////////////////////////////////////

    @Parameter(name="type", type=CommandType.STRING)
    private String type;

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////

    public String getType() {
        return type;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List alertList = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List alertResponseList = new ArrayList();
        for (AlertVO alert : alertList) {
            AlertResponse alertResponse = new AlertResponse();
            alertResponse.setAlertType(alert.getType());
            alertResponse.setDescription(alert.getSubject());
            alertResponse.setLastSent(alert.getLastSent());

            alertResponse.setResponseName("alert");
            alertResponseList.add(alertResponse);
        }

        response.setResponses(alertResponseList);
        response.setResponseName(getName());
        return response;
    }
}
File
ListAlertsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class declaration
Import
Chunk
Conflicting content
    }

<<<<<<< HEAD
        return s_name;
    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List offerings = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List diskOfferingResponses = new ArrayList();
        for (DiskOfferingVO offering : offerings) {
            DiskOfferingResponse diskOffResp = new DiskOfferingResponse();
            diskOffResp.setCreated(offering.getCreated());
            diskOffResp.setDiskSize(offering.getDiskSize());
            diskOffResp.setDisplayText(offering.getDisplayText());
            diskOffResp.setDomainId(offering.getDomainId());
            diskOffResp.setId(offering.getId());
            diskOffResp.setName(offering.getName());
            diskOffResp.setTags(offering.getTags());
            DomainVO domain = ApiDBUtils.findDomainById(offering.getDomainId());
            diskOffResp.setDomain(domain.getName());

            diskOffResp.setResponseName("diskoffering");
            diskOfferingResponses.add(diskOffResp);
        }

        response.setResponses(diskOfferingResponses);
        response.setResponseName(getName());
        return response;
=======
        Long startIndex = Long.valueOf(0);
        int pageSizeNum = 50;
    	if (pageSize != null) {
    		pageSizeNum = pageSize.intValue();
    	}
        if (page != null) {
            int pageNum = page.intValue();
            if (pageNum > 0) {
                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
            }
        }

        Criteria c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum));
        if (keyword != null) {
        	c.addCriteria(Criteria.KEYWORD, keyword);
        }else {
        	c.addCriteria(Criteria.ID, id);
            c.addCriteria(Criteria.NAME, name);
            c.addCriteria(Criteria.DOMAINID, domainId);
        }

        List offerings = getManagementServer().searchForDiskOfferings(c);

        List> offeringTags = new ArrayList>();
        Object[] diskOffTag = new Object[offerings.size()];
        int i = 0;
        for (DiskOfferingVO offering : offerings) {
            List> offeringData = new ArrayList>();

            offeringData.add(new Pair(BaseCmd.Properties.ID.getName(), Long.toString(offering.getId())));
            offeringData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), offering.getDomainId()));
            offeringData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(offering.getDomainId()).getName()));
            offeringData.add(new Pair(BaseCmd.Properties.NAME.getName(), offering.getName()));
            offeringData.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), offering.getDisplayText()));
            offeringData.add(new Pair(BaseCmd.Properties.DISK_SIZE.getName(), offering.getDiskSizeInBytes()));
            offeringData.add(new Pair(BaseCmd.Properties.CREATED.getName(), offering.getCreated()));
            offeringData.add(new Pair(BaseCmd.Properties.TAGS.getName(), offering.getTags()));
            diskOffTag[i++] = offeringData;
        }
        Pair offeringTag = new Pair("diskoffering", diskOffTag);
        offeringTags.add(offeringTag);
        return offeringTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List offerings = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List diskOfferingResponses = new ArrayList();
        for (DiskOfferingVO offering : offerings) {
            DiskOfferingResponse diskOffResp = new DiskOfferingResponse();
            diskOffResp.setCreated(offering.getCreated());
            diskOffResp.setDiskSize(offering.getDiskSize());
            diskOffResp.setDisplayText(offering.getDisplayText());
            diskOffResp.setDomainId(offering.getDomainId());
            diskOffResp.setId(offering.getId());
            diskOffResp.setName(offering.getName());
            diskOffResp.setTags(offering.getTags());
            DomainVO domain = ApiDBUtils.findDomainById(offering.getDomainId());
            diskOffResp.setDomain(domain.getName());

            diskOffResp.setResponseName("diskoffering");
            diskOfferingResponses.add(diskOffResp);
        }

        response.setResponses(diskOfferingResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListDiskOfferingsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
For statement
If statement
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
import org.apache.log4j.Logger;

<<<<<<< HEAD
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.domain.DomainVO;

@Implementation(method="searchForDomainChildren")
public class ListDomainChildrenCmd extends BaseListCmd {
=======
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.domain.Domain;
import com.cloud.server.Criteria;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public class ListDomainChildrenCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	public static final Logger s_logger = Logger.getLogger(ListDomainChildrenCmd.class.getName());

    private static final String s_name = "listdomainchildrenresponse";
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.domain.DomainVO;

@Implementation(method="searchForDomainChildren")
public class ListDomainChildrenCmd extends BaseListCmd {
	public static final Logger s_logger = Logger.getLogger(ListDomainChildrenCmd.class.getName());

    private static final String s_name = "listdomainchildrenresponse";
File
ListDomainChildrenCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
            domainResponses.add(domainResponse);
        }

<<<<<<< HEAD
        response.setResponses(domainResponses);
        response.setResponseName(getName());
        return response;
=======
        Long startIndex = Long.valueOf(0);
        int pageSizeNum = 50;
    	if (pageSize != null) {
    		pageSizeNum = pageSize.intValue();
    	}
    	
        if (page != null) {
            int pageNum = page.intValue();
            if (pageNum > 0) {
                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
            }
        }
        
        //temporary solution at API level. We need a permanent solution for all "listXXXXXXX & pageSize = -1" in the future.
        Criteria c;
        if(pageSizeNum != -1)
            c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum));
        else
        	c = new Criteria("id", Boolean.TRUE, null, null);
        
        
        if (keyword != null) {
        	c.addCriteria(Criteria.KEYWORD, keyword);
        }
        else {
        	c.addCriteria(Criteria.ID, domainId);
            c.addCriteria(Criteria.NAME, domainName);
            c.addCriteria(Criteria.ISRECURSIVE, isRecursive);
        }
        
        // TODO : Recursive listing is not supported yet 
        List domains = getManagementServer().searchForDomainChildren(c);
        
        List> domainTags = new ArrayList>();
        Object[] dTag = new Object[domains.size()];
        int i = 0;
        for (Domain domain : domains) {
            List> domainData = new ArrayList>();
            domainData.add(new Pair(BaseCmd.Properties.ID.getName(), Long.valueOf(domain.getId()).toString()));
            domainData.add(new Pair(BaseCmd.Properties.NAME.getName(), domain.getName()));
            domainData.add(new Pair(BaseCmd.Properties.LEVEL.getName(), Integer.toString(domain.getLevel())));

            domainData.add(new Pair(BaseCmd.Properties.HAS_CHILD.getName(), 
        		(domain.getChildCount()) > 0 ? "true" : "false"));
            
            if (domain.getParent() != null){
            	domainData.add(new Pair(BaseCmd.Properties.PARENT_DOMAIN_ID.getName(), domain.getParent().toString()));
            	domainData.add(new Pair(BaseCmd.Properties.PARENT_DOMAIN_NAME.getName(),getManagementServer().findDomainIdById(domain.getParent()).getName()));
            }
            dTag[i++] = domainData;
        }
        Pair domainTag = new Pair("domain", dTag);
        domainTags.add(domainTag);
        return domainTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
            domainResponses.add(domainResponse);
        }

        response.setResponses(domainResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListDomainChildrenCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
For statement
If statement
Method invocation
Return statement
Variable
Chunk
Conflicting content
import org.apache.log4j.Logger;

<<<<<<< HEAD
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.domain.DomainVO;

@Implementation(method="searchForDomains")
public class ListDomainsCmd extends BaseListCmd {
=======
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.domain.Domain;
import com.cloud.server.Criteria;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public class ListDomainsCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	public static final Logger s_logger = Logger.getLogger(ListDomainsCmd.class.getName());
	
    private static final String s_name = "listdomainsresponse";
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.domain.DomainVO;

@Implementation(method="searchForDomains")
public class ListDomainsCmd extends BaseListCmd {
	public static final Logger s_logger = Logger.getLogger(ListDomainsCmd.class.getName());
	
    private static final String s_name = "listdomainsresponse";
File
ListDomainsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
            domainResponses.add(domainResponse);
        }

<<<<<<< HEAD
        response.setResponses(domainResponses);
        response.setResponseName(getName());
        return response;
=======
        Long startIndex = Long.valueOf(0);
        int pageSizeNum = 50;
    	if (pageSize != null) {
    		pageSizeNum = pageSize.intValue();
    	}
        if (page != null) {
            int pageNum = page.intValue();
            if (pageNum > 0) {
                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
            }
        }
        
        //temporary solution at API level. We need a permanent solution for all "listXXXXXXX & pageSize = -1" in the future.
        Criteria c;
        if(pageSizeNum != -1)
            c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum));
        else
        	c = new Criteria("id", Boolean.TRUE, null, null);
        
        if (keyword != null) {
        	c.addCriteria(Criteria.KEYWORD, keyword);
        } else {
        	c.addCriteria(Criteria.ID, domainId);
            c.addCriteria(Criteria.NAME, domainName);
            c.addCriteria(Criteria.LEVEL, level);
        }
        
        List domains = getManagementServer().searchForDomains(c);
        
        List> domainTags = new ArrayList>();
        Object[] dTag = new Object[domains.size()];
        int i = 0;
        for (Domain domain : domains) {
            List> domainData = new ArrayList>();
            domainData.add(new Pair(BaseCmd.Properties.ID.getName(), Long.valueOf(domain.getId()).toString()));
            domainData.add(new Pair(BaseCmd.Properties.NAME.getName(), domain.getName()));
            domainData.add(new Pair(BaseCmd.Properties.LEVEL.getName(), Integer.toString(domain.getLevel())));
            
            if (domain.getParent() != null){
            	domainData.add(new Pair(BaseCmd.Properties.PARENT_DOMAIN_ID.getName(), domain.getParent().toString()));
            	domainData.add(new Pair(BaseCmd.Properties.PARENT_DOMAIN_NAME.getName(), 
            			getManagementServer().findDomainIdById(domain.getParent()).getName()));
            }
            dTag[i++] = domainData;
        }
        Pair domainTag = new Pair("domain", dTag);
        domainTags.add(domainTag);
        return domainTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
            domainResponses.add(domainResponse);
        }

        response.setResponses(domainResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListDomainsCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
For statement
If statement
Method invocation
Return statement
Variable
Chunk
Conflicting content
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
<<<<<<< HEAD

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.EventResponse;
import com.cloud.api.response.ListResponse;
=======
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.api.ServerApiException;
import com.cloud.domain.DomainVO;
import com.cloud.event.EventVO;
import com.cloud.user.User;
Solution content
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.EventResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.event.EventVO;
import com.cloud.user.User;
File
ListEventsCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
            responseEvent.setResponseName("event");
            eventResponses.add(responseEvent);
        }
<<<<<<< HEAD

        response.setResponses(eventResponses);
        response.setResponseName(getName());
        return response;
=======
        else {
            events = getManagementServer().searchForEvents(c);
        }

        if (events == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching for events");
        }
        List> eventTags = new ArrayList>();
        Object[] eTag = new Object[events.size()];
        int i = 0;
        for (EventVO event : events) {
            List> eventData = new ArrayList>();
            eventData.add(new Pair(BaseCmd.Properties.ID.getName(), (new Long(event.getId())).toString()));
            User user = getManagementServer().findUserById(event.getUserId());
            if (user != null) {
            	eventData.add(new Pair(BaseCmd.Properties.USERNAME.getName(), user.getUsername() ));
            }
            eventData.add(new Pair(BaseCmd.Properties.TYPE.getName(), event.getType()));
            eventData.add(new Pair(BaseCmd.Properties.LEVEL.getName(), event.getLevel()));
            eventData.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), event.getDescription()));
            Account acct = getManagementServer().findAccountById(Long.valueOf(event.getAccountId()));
            if (acct != null) {
            	eventData.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), acct.getAccountName()));
            	eventData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), Long.toString(acct.getDomainId())));
            	eventData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(acct.getDomainId()).getName()));
            }
            if (event.getCreateDate() != null) {
                eventData.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(event.getCreateDate())));
            }
            eventData.add(new Pair(BaseCmd.Properties.STATE.getName(), event.getState().toString()));
            eventData.add(new Pair(BaseCmd.Properties.PARENT_ID.getName(), (new Long(event.getStartId())).toString()));
            eTag[i++] = eventData;
        }
        Pair eventTag = new Pair("event", eTag);
        eventTags.add(eventTag);
        return eventTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
            responseEvent.setResponseName("event");
            eventResponses.add(responseEvent);
        }

        response.setResponses(eventResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListEventsCmd.java
Developer's decision
Version 1
Kind of conflict
For statement
If statement
Method invocation
Return statement
Variable
Chunk
Conflicting content
                isoResponse.setZoneName(datacenter.getName());
                            
                // If the user is an admin, add the template download status
<<<<<<< HEAD
                if (isAdmin || account.getId().longValue() == iso.getAccountId()) {
                    // add download status
                    if (isoHost.getDownloadState()!=Status.DOWNLOADED) {
                        String isoStatus = "Processing";
                        if (isoHost.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                            isoStatus = "Download Complete";
                        } else if (isoHost.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                            if (isoHost.getDownloadPercent() == 100) {
                                isoStatus = "Installing ISO";
                            } else {
                                isoStatus = isoHost.getDownloadPercent() + "% Downloaded";
                            }
                        } else {
                            isoStatus = isoHost.getErrorString();
                        }
                        isoResponse.setStatus(isoStatus);
                    } else {
                        isoResponse.setStatus("Successfully Installed");
                    }
=======
                if (isAdmin || account.getId() == iso.getAccountId()) {
                	// add download status
                	if (isoHost.getDownloadState()!=Status.DOWNLOADED) {
                		String isoStatus = "Processing";
                		if (isoHost.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                			isoStatus = "Download Complete";
                		} else if (isoHost.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                			if (isoHost.getDownloadPercent() == 100) {
                				isoStatus = "Installing ISO";
                			} else {
                				isoStatus = isoHost.getDownloadPercent() + "% Downloaded";
                			}
                		} else {
                			isoStatus = isoHost.getErrorString();
                		}
                		isoData.add(new Pair(BaseCmd.Properties.ISO_STATUS.getName(), isoStatus));
                	} else {
                		isoData.add(new Pair(BaseCmd.Properties.ISO_STATUS.getName(), "Successfully Installed"));
                	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
                }

                long isoSize = isoHost.getSize();
Solution content
                isoResponse.setZoneName(datacenter.getName());
                            
                // If the user is an admin, add the template download status
                if (isAdmin || account.getId() == iso.getAccountId()) {
                    // add download status
                    if (isoHost.getDownloadState()!=Status.DOWNLOADED) {
                        String isoStatus = "Processing";
                        if (isoHost.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                            isoStatus = "Download Complete";
                        } else if (isoHost.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                            if (isoHost.getDownloadPercent() == 100) {
                                isoStatus = "Installing ISO";
                            } else {
                                isoStatus = isoHost.getDownloadPercent() + "% Downloaded";
                            }
                        } else {
                            isoStatus = isoHost.getErrorString();
                        }
                        isoResponse.setStatus(isoStatus);
                    } else {
                        isoResponse.setStatus("Successfully Installed");
                    }
                }

                long isoSize = isoHost.getSize();
File
ListIsosCmd.java
Developer's decision
Combination
Kind of conflict
Comment
If statement
Chunk
Conflicting content
            userVmResponse.setDisplayName(instance.getDisplayName());
            userVmResponse.setPrivateIp(instance.getPrivateIpAddress());

<<<<<<< HEAD
            Account accountTemp = ApiDBUtils.findAccountById(instance.getAccountId());
            if (accountTemp != null) {
                userVmResponse.setAccountName(accountTemp.getAccountName());
                userVmResponse.setDomainId(accountTemp.getDomainId());
                userVmResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
=======
        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = getManagementServer().findAccountById(Long.valueOf(lbAcctId));
                if (!getManagementServer().isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            }

            userVmResponse.setResponseName("loadbalancerruleinstance");
Solution content
            userVmResponse.setDisplayName(instance.getDisplayName());
            userVmResponse.setPrivateIp(instance.getPrivateIpAddress());

            Account accountTemp = ApiDBUtils.findAccountById(instance.getAccountId());
            if (accountTemp != null) {
                userVmResponse.setAccountName(accountTemp.getAccountName());
                userVmResponse.setDomainId(accountTemp.getDomainId());
                userVmResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
            }

            userVmResponse.setResponseName("loadbalancerruleinstance");
File
ListLoadBalancerRuleInstancesCmd.java
Developer's decision
Version 1
Kind of conflict
If statement
Method invocation
Throw statement
Variable
Chunk
Conflicting content
                        ingressData.setEndPort(ingressRule.getEndPort());
                    }

<<<<<<< HEAD
                    if (ingressRule.getAllowedNetworkGroup() != null) {
                        ingressData.setNetworkGroupName(ingressRule.getAllowedNetworkGroup());
                        ingressData.setAccountName(ingressRule.getAllowedNetGroupAcct());
                    } else {
                        ingressData.setCidr(ingressRule.getAllowedSourceIpCidr());
=======
                if (account != null) {
                    // check that the user is the owner of the VM (admin case was already verified
                    if (account.getId() != userVM.getAccountId()) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to list network groups for virtual machine instance " + vmId + "; permission denied.");
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
                    }

                    ingressData.setResponseName("ingressrule");
Solution content
                        ingressData.setEndPort(ingressRule.getEndPort());
                    }

                    if (ingressRule.getAllowedNetworkGroup() != null) {
                        ingressData.setNetworkGroupName(ingressRule.getAllowedNetworkGroup());
                        ingressData.setAccountName(ingressRule.getAllowedNetGroupAcct());
                    } else {
                        ingressData.setCidr(ingressRule.getAllowedSourceIpCidr());
                    }

                    ingressData.setResponseName("ingressrule");
File
ListNetworkGroupsCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Throw statement
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List firewallRules = (List)getResponseObject();
        Map userVmCache = new HashMap();
        IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ipAddress);

        ListResponse response = new ListResponse();
        List fwResponses = new ArrayList();
        for (FirewallRuleVO fwRule : firewallRules) {
            FirewallRuleResponse ruleData = new FirewallRuleResponse();

            ruleData.setId(fwRule.getId());
            ruleData.setPublicPort(fwRule.getPublicPort());
            ruleData.setPrivatePort(fwRule.getPrivatePort());
            ruleData.setProtocol(fwRule.getProtocol());

            UserVmVO userVM = userVmCache.get(fwRule.getPrivateIpAddress());
            if (userVM == null) {
                Criteria c = new Criteria();
                c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddr.getAccountId()});
                c.addCriteria(Criteria.DATACENTERID, ipAddr.getDataCenterId());
                c.addCriteria(Criteria.IPADDRESS, fwRule.getPrivateIpAddress());
                List userVMs = ApiDBUtils.searchForUserVMs(c);

                if ((userVMs != null) && (userVMs.size() > 0)) {
                    userVM = userVMs.get(0);
                    userVmCache.put(fwRule.getPrivateIpAddress(), userVM);
                }
            }

            if (userVM != null) {
                ruleData.setVirtualMachineId(userVM.getId());
                ruleData.setVirtualMachineName(userVM.getName());
            }

            ruleData.setResponseName("portforwardingrule");
            fwResponses.add(ruleData);
        }

        response.setResponses(fwResponses);
        response.setResponseName(getName());
        return response;
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String ipAddress = (String)params.get(BaseCmd.Properties.IP_ADDRESS.getName());

        IPAddressVO ipAddressVO = getManagementServer().findIPAddressById(ipAddress);
        if (ipAddressVO == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find IP address " + ipAddress);
        }

        Account addrOwner = getManagementServer().findAccountById(ipAddressVO.getAccountId());

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if ((account != null) && isAdmin(account.getType())) {
            if (ipAddressVO.getAccountId() != null) {
                if ((addrOwner != null) && !getManagementServer().isChildDomain(account.getDomainId(), addrOwner.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to list port forwarding rules for address " + ipAddress + ", permission denied for account " + account.getId());
                }
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to list port forwarding rules for address " + ipAddress + ", address not in use.");
            }
        } else {
            if (account != null) {
                if ((ipAddressVO.getAccountId() == null) || (account.getId() != ipAddressVO.getAccountId().longValue())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to list port forwarding rules for address " + ipAddress + ", permission denied for account " + account.getId());
                }
                addrOwner = account;
            }
        }

        List firewallRules = getManagementServer().listIPForwarding(ipAddress, true);

        if (firewallRules == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching port forwarding rules for address " + ipAddress);
        }
        /*
        Criteria lbCriteria = new Criteria();
        lbCriteria.addCriteria(Criteria.IPADDRESS, ipAddress);
        List loadBalancers = getManagementServer().searchForLoadBalancers(lbCriteria);
        if (loadBalancers == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching load balancer rules for address " + ipAddress);
        }
        */

        Map userVmCache = new HashMap();

        List> groupsTags = new ArrayList>();
        Object[] forwardingTag = new Object[firewallRules.size()];
        int i = 0;
        for (FirewallRuleVO fwRule : firewallRules) {
            List> ruleData = new ArrayList>();

            ruleData.add(new Pair(BaseCmd.Properties.ID.getName(), fwRule.getId().toString()));
            ruleData.add(new Pair(BaseCmd.Properties.PUBLIC_PORT.getName(), fwRule.getPublicPort()));
            ruleData.add(new Pair(BaseCmd.Properties.PRIVATE_PORT.getName(), fwRule.getPrivatePort()));
            ruleData.add(new Pair(BaseCmd.Properties.PROTOCOL.getName(), fwRule.getProtocol()));

            UserVmVO userVM = userVmCache.get(fwRule.getPrivateIpAddress());
            if (userVM == null) {
                Criteria c = new Criteria();
                c.addCriteria(Criteria.ACCOUNTID, new Object[] {addrOwner.getId()});
                c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
                c.addCriteria(Criteria.IPADDRESS, fwRule.getPrivateIpAddress());
                List userVMs = getManagementServer().searchForUserVMs(c);

                if ((userVMs != null) && (userVMs.size() > 0)) {
                    userVM = userVMs.get(0);
                    userVmCache.put(fwRule.getPrivateIpAddress(), userVM);
                }
            }

            if (userVM != null) {
                ruleData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName(), Long.toString(userVM.getId())));
                ruleData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_NAME.getName(), userVM.getName()));
                ruleData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_DISPLAYNAME.getName(), userVM.getDisplayName()));
            }

            forwardingTag[i++] = ruleData;
        }
        Pair forwardingTags = new Pair("portforwardingrule", forwardingTag);
        groupsTags.add(forwardingTags);

        /*
        Object[] lbTag = new Object[loadBalancers.size()];
        i = 0;
        for (LoadBalancerVO loadBalancer : loadBalancers) {
            List> lbData = new ArrayList>();

            lbData.add(new Pair(BaseCmd.Properties.ID.getName(), loadBalancer.getId().toString()));
            lbData.add(new Pair(BaseCmd.Properties.PUBLIC_PORT.getName(), loadBalancer.getPublicPort()));
            lbData.add(new Pair(BaseCmd.Properties.PRIVATE_PORT.getName(), loadBalancer.getPrivatePort()));
            lbData.add(new Pair(BaseCmd.Properties.ALGORITHM.getName(), loadBalancer.getAlgorithm()));

            lbTag[i++] = lbData;
        }
        Pair lbTags = new Pair("loadbalancer", lbTag);
        groupsTags.add(lbTags);
        */
        return groupsTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List firewallRules = (List)getResponseObject();
        Map userVmCache = new HashMap();
        IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ipAddress);

        ListResponse response = new ListResponse();
        List fwResponses = new ArrayList();
        for (FirewallRuleVO fwRule : firewallRules) {
            FirewallRuleResponse ruleData = new FirewallRuleResponse();

            ruleData.setId(fwRule.getId());
            ruleData.setPublicPort(fwRule.getPublicPort());
            ruleData.setPrivatePort(fwRule.getPrivatePort());
            ruleData.setProtocol(fwRule.getProtocol());

            UserVmVO userVM = userVmCache.get(fwRule.getPrivateIpAddress());
            if (userVM == null) {
                Criteria c = new Criteria();
                c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddr.getAccountId()});
                c.addCriteria(Criteria.DATACENTERID, ipAddr.getDataCenterId());
                c.addCriteria(Criteria.IPADDRESS, fwRule.getPrivateIpAddress());
                List userVMs = ApiDBUtils.searchForUserVMs(c);

                if ((userVMs != null) && (userVMs.size() > 0)) {
                    userVM = userVMs.get(0);
                    userVmCache.put(fwRule.getPrivateIpAddress(), userVM);
                }
            }

            if (userVM != null) {
                ruleData.setVirtualMachineId(userVM.getId());
                ruleData.setVirtualMachineName(userVM.getName());
            }

            ruleData.setResponseName("portforwardingrule");
            fwResponses.add(ruleData);
        }

        response.setResponses(fwResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListPortForwardingRulesCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
For statement
If statement
Method declaration
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
    }

    @Override
    public List> getProperties() {
        return s_properties;
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List portForwardingServiceRules = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List ruleResponses = new ArrayList();
        for (NetworkRuleConfigVO rule : portForwardingServiceRules) {
            PortForwardingServiceRuleResponse ruleResponse = new PortForwardingServiceRuleResponse();
            ruleResponse.setRuleId(rule.getId());
            ruleResponse.setPortForwardingServiceId(rule.getSecurityGroupId());
            ruleResponse.setPublicPort(rule.getPublicPort());
            ruleResponse.setPrivatePort(rule.getPrivatePort());
            ruleResponse.setProtocol(rule.getProtocol());

            AsyncJobVO asyncJob = ApiDBUtils.findInstancePendingAsyncJob("network_rule_config", rule.getId());
            if(asyncJob != null) {
                ruleResponse.setJobId(asyncJob.getId());
                ruleResponse.setJobStatus(asyncJob.getStatus());
=======
    }
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
    	Long id = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long groupId = (Long)params.get(BaseCmd.Properties.PORT_FORWARDING_SERVICE_ID.getName());

        // FIXME:  validate that the domain admin can list network rules for the group in question
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid domain id (" + domainId + ") given, unable to list port forwarding service rules.");
                }
                if (accountName != null) {
                    Account userAcct = getManagementServer().findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = getManagementServer().findSecurityGroupById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find port forwarding service with id " + groupId);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            }

            ruleResponse.setResponseName("portforwardingservicerule");
Solution content
    @Override
    public String getName() {
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List portForwardingServiceRules = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List ruleResponses = new ArrayList();
        for (NetworkRuleConfigVO rule : portForwardingServiceRules) {
            PortForwardingServiceRuleResponse ruleResponse = new PortForwardingServiceRuleResponse();
            ruleResponse.setRuleId(rule.getId());
            ruleResponse.setPortForwardingServiceId(rule.getSecurityGroupId());
            ruleResponse.setPublicPort(rule.getPublicPort());
            ruleResponse.setPrivatePort(rule.getPrivatePort());
            ruleResponse.setProtocol(rule.getProtocol());

            AsyncJobVO asyncJob = ApiDBUtils.findInstancePendingAsyncJob("network_rule_config", rule.getId());
            if(asyncJob != null) {
                ruleResponse.setJobId(asyncJob.getId());
                ruleResponse.setJobStatus(asyncJob.getStatus());
            }

            ruleResponse.setResponseName("portforwardingservicerule");
File
ListPortForwardingServiceRulesCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
For statement
If statement
Method declaration
Method invocation
Method signature
Throw statement
Variable
Chunk
Conflicting content
import java.util.ArrayList;
import java.util.List;
<<<<<<< HEAD

import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.SnapshotScheduleResponse;
=======
import java.util.Map;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.SnapshotScheduleVO;

@Implementation(method="findRecurringSnapshotSchedule", manager=Manager.SnapshotManager)
Solution content
import java.util.ArrayList;
import java.util.List;

import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.SnapshotScheduleResponse;
import com.cloud.storage.SnapshotScheduleVO;

@Implementation(method="findRecurringSnapshotSchedule", manager=Manager.SnapshotManager)
File
ListRecurringSnapshotScheduleCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
        response.setResponseName(getName());

    @Override
        return response;
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List snapshotSchedules = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List snapshotScheduleResponses = new ArrayList();
        for (SnapshotScheduleVO snapshotSchedule : snapshotSchedules) {
            SnapshotScheduleResponse snapSchedResponse = new SnapshotScheduleResponse();
            snapSchedResponse.setId(snapshotSchedule.getId());
            snapSchedResponse.setVolumeId(snapshotSchedule.getVolumeId());
            snapSchedResponse.setSnapshotPolicyId(snapshotSchedule.getPolicyId());
            snapSchedResponse.setScheduled(snapshotSchedule.getScheduledTimestamp());

            snapSchedResponse.setResponseName("snapshot");
            snapshotScheduleResponses.add(snapSchedResponse);
        }

        response.setResponses(snapshotScheduleResponses);
=======
    public List> getProperties() {
    }
        return s_properties;
    }
    public List> execute(Map params) {
        Long volumeId = (Long)params.get(BaseCmd.Properties.VOLUME_ID.getName());
        Long policyId = (Long)params.get(BaseCmd.Properties.SNAPSHOT_POLICY_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());

        //Verify parameters
        VolumeVO volume = getManagementServer().findVolumeById(volumeId);
        if (volume == null) {
            throw new ServerApiException (BaseCmd.SNAPSHOT_INVALID_PARAM_ERROR, "unable to find a volume with id " + volumeId);
        }

        if (account != null) {
            long volAcctId = volume.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = getManagementServer().findAccountById(Long.valueOf(volAcctId));
                if (!getManagementServer().isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid volume id (" + volumeId + ") given, unable to list snapshots.");
                }
            } else if (account.getId() != volAcctId) {
                throw new ServerApiException(BaseCmd.SNAPSHOT_INVALID_PARAM_ERROR, "account " + account.getAccountName() + " does not own volume id " + volAcctId);
            }
        }

        List recurringSnapshotSchedules = getManagementServer().findRecurringSnapshotSchedule(volumeId, policyId);
        Object[] snapshotTag = new Object[recurringSnapshotSchedules.size()];
        int i = 0;
        
        for (SnapshotScheduleVO recurringSnapshotSchedule : recurringSnapshotSchedules) {
            List> snapshotData = new ArrayList>();
            snapshotData.add(new Pair(BaseCmd.Properties.ID.getName(), recurringSnapshotSchedule.getId().toString()));
            snapshotData.add(new Pair(BaseCmd.Properties.VOLUME_ID.getName(), recurringSnapshotSchedule.getVolumeId().toString()));
            snapshotData.add(new Pair(BaseCmd.Properties.SNAPSHOT_POLICY_ID.getName(), recurringSnapshotSchedule.getPolicyId().toString()));
            snapshotData.add(new Pair(BaseCmd.Properties.SCHEDULED.getName(), getDateString(recurringSnapshotSchedule.getScheduledTimestamp())));
            snapshotTag[i++] = snapshotData;
        }
        List> returnTags = new ArrayList>();
        Pair snapshotTags = new Pair("snapshot", snapshotTag);
        returnTags.add(snapshotTags);
        return returnTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List snapshotSchedules = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List snapshotScheduleResponses = new ArrayList();
        for (SnapshotScheduleVO snapshotSchedule : snapshotSchedules) {
            SnapshotScheduleResponse snapSchedResponse = new SnapshotScheduleResponse();
            snapSchedResponse.setId(snapshotSchedule.getId());
            snapSchedResponse.setVolumeId(snapshotSchedule.getVolumeId());
            snapSchedResponse.setSnapshotPolicyId(snapshotSchedule.getPolicyId());
            snapSchedResponse.setScheduled(snapshotSchedule.getScheduledTimestamp());

            snapSchedResponse.setResponseName("snapshot");
            snapshotScheduleResponses.add(snapSchedResponse);
        }

        response.setResponses(snapshotScheduleResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListRecurringSnapshotScheduleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
For statement
If statement
Method declaration
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
import org.apache.log4j.Logger;

<<<<<<< HEAD
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.offering.ServiceOffering.GuestIpType;
=======
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.server.Criteria;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.service.ServiceOfferingVO;

@Implementation(method="searchForServiceOfferings")
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.service.ServiceOfferingVO;

@Implementation(method="searchForServiceOfferings")
File
ListServiceOfferingsCmd.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
        return s_name;
    }

<<<<<<< HEAD
    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List offerings = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List offeringResponses = new ArrayList();
        for (ServiceOfferingVO offering : offerings) {
            ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();
            offeringResponse.setId(offering.getId());
            offeringResponse.setName(offering.getName());
            offeringResponse.setDisplayText(offering.getDisplayText());
            offeringResponse.setCpuNumber(offering.getCpu());
            offeringResponse.setCpuSpeed(offering.getSpeed());
            offeringResponse.setMemory(offering.getRamSize());
            offeringResponse.setCreated(offering.getCreated());
            offeringResponse.setStorageType(offering.getUseLocalStorage() ? "local" : "shared");
            offeringResponse.setOfferHa(offering.getOfferHA());
            offeringResponse.setUseVirtualNetwork(offering.getGuestIpType().equals(GuestIpType.Virtualized));
            offeringResponse.setTags(offering.getTags());

            offeringResponse.setResponseName("serviceoffering");
            offeringResponses.add(offeringResponse);
=======
    @Override
    public List> execute(Map params) {
    	String name = (String)params.get(BaseCmd.Properties.NAME.getName());
    	Long id = (Long)params.get(BaseCmd.Properties.ID.getName());
    	Long vmId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
    	String keyword = (String)params.get(BaseCmd.Properties.KEYWORD.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Integer page = (Integer)params.get(BaseCmd.Properties.PAGE.getName());
        Integer pageSize = (Integer)params.get(BaseCmd.Properties.PAGESIZE.getName());
        
        Long startIndex = Long.valueOf(0);
        int pageSizeNum = 50;
    	if (pageSize != null) {
    		pageSizeNum = pageSize.intValue();
    	}
        if (page != null) {
            int pageNum = page.intValue();
            if (pageNum > 0) {
                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
            }
        }
        Criteria c = new Criteria("created", Boolean.FALSE, startIndex, Long.valueOf(pageSizeNum));
        if (keyword != null) {
        	c.addCriteria(Criteria.KEYWORD, keyword);
        } else {
        	c.addCriteria(Criteria.ID, id);
            c.addCriteria(Criteria.NAME, name);
        }
        
        //If vmId is present in the list of parameters, verify it
        if (vmId != null) {
        	UserVmVO vmInstance = getManagementServer().findUserVMInstanceById(vmId.longValue());
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
            	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
            }
        	if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
                }
            }
        	if (keyword == null)
            	c.addCriteria(Criteria.INSTANCEID, vmId);
        }

        List offerings = getManagementServer().searchForServiceOfferings(c);
        if (offerings == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find service offerings");
        }
        List> offeringTags = new ArrayList>();
        Object[] soTag = new Object[offerings.size()];
        int i = 0;
        for (ServiceOfferingVO offering : offerings) 
        {
            List> offeringData = new ArrayList>();

            offeringData.add(new Pair(BaseCmd.Properties.ID.getName(), Long.toString(offering.getId())));
            offeringData.add(new Pair(BaseCmd.Properties.NAME.getName(), offering.getName()));
            offeringData.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), offering.getDisplayText()));
            offeringData.add(new Pair(BaseCmd.Properties.CPU_NUMBER.getName(), Integer.valueOf(offering.getCpu()).toString()));
            offeringData.add(new Pair(BaseCmd.Properties.CPU_SPEED.getName(), Integer.valueOf(offering.getSpeed()).toString()));
            offeringData.add(new Pair(BaseCmd.Properties.MEMORY.getName(), Integer.valueOf(offering.getRamSize()).toString()));
            offeringData.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(offering.getCreated())));
            String storageType = offering.getUseLocalStorage() ? "local" : "shared";
            offeringData.add(new Pair(BaseCmd.Properties.STORAGE_TYPE.getName(), storageType));
            offeringData.add(new Pair(BaseCmd.Properties.OFFER_HA.getName(), offering.getOfferHA()));
            offeringData.add(new Pair(BaseCmd.Properties.USE_VIRTUAL_NETWORK.getName(), (offering.getGuestIpType().equals(NetworkOffering.GuestIpType.Virtualized))));
            offeringData.add(new Pair(BaseCmd.Properties.TAGS.getName(), (offering.getTags())));      

            soTag[i++] = offeringData;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }

        response.setResponses(offeringResponses);
Solution content
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List offerings = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List offeringResponses = new ArrayList();
        for (ServiceOfferingVO offering : offerings) {
            ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();
            offeringResponse.setId(offering.getId());
            offeringResponse.setName(offering.getName());
            offeringResponse.setDisplayText(offering.getDisplayText());
            offeringResponse.setCpuNumber(offering.getCpu());
            offeringResponse.setCpuSpeed(offering.getSpeed());
            offeringResponse.setMemory(offering.getRamSize());
            offeringResponse.setCreated(offering.getCreated());
            offeringResponse.setStorageType(offering.getUseLocalStorage() ? "local" : "shared");
            offeringResponse.setOfferHa(offering.getOfferHA());
            offeringResponse.setUseVirtualNetwork(offering.getGuestIpType().equals(GuestIpType.Virtualized));
            offeringResponse.setTags(offering.getTags());

            offeringResponse.setResponseName("serviceoffering");
            offeringResponses.add(offeringResponse);
        }

        response.setResponses(offeringResponses);
File
ListServiceOfferingsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Array access
Cast expression
Comment
For statement
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
                snapshotResponse.setDomainId(acct.getDomainId());
                snapshotResponse.setDomainName(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
            }
<<<<<<< HEAD

            VolumeVO volume = ApiDBUtils.findVolumeById(snapshot.getVolumeId());
            String snapshotTypeStr = SnapshotType.values()[snapshot.getSnapshotType()].name();
            snapshotResponse.setSnapshotType(snapshotTypeStr);
            snapshotResponse.setVolumeId(snapshot.getVolumeId());
            snapshotResponse.setVolumeName(volume.getName());
            snapshotResponse.setVolumeType(volume.getVolumeType().name());
            snapshotResponse.setCreated(snapshot.getCreated());
            snapshotResponse.setName(snapshot.getName());

            AsyncJobVO asyncJob = ApiDBUtils.findInstancePendingAsyncJob("snapshot", snapshot.getId());
            if (asyncJob != null) {
                snapshotResponse.setJobId(asyncJob.getId());
                snapshotResponse.setJobStatus(asyncJob.getStatus());
=======
        } else {
            accountId = account.getId();
        }
            
        Long startIndex = Long.valueOf(0);
        int pageSizeNum = 50;
    	if (pageSize != null) {
    		pageSizeNum = pageSize.intValue();
    	}
        if (page != null) {
            int pageNum = page.intValue();
            if (pageNum > 0) {
                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
            }
        }
        Criteria c = new Criteria("created", Boolean.FALSE, startIndex, Long.valueOf(pageSizeNum));

        c.addCriteria(Criteria.VOLUMEID, volumeId);
        c.addCriteria(Criteria.TYPE, snapshotType); // I don't want to create a new Criteria called SNAPSHOT_TYPE
        c.addCriteria(Criteria.NAME, name);
        c.addCriteria(Criteria.ID, id);
        c.addCriteria(Criteria.KEYWORD, keyword);
        c.addCriteria(Criteria.ACCOUNTID, accountId);
        
        List snapshots = null;
		try {
			snapshots = getManagementServer().listSnapshots(c, interval);
		} catch (InvalidParameterValueException e) {
			throw new ServerApiException(SNAPSHOT_INVALID_PARAM_ERROR, e.getMessage());
		}

        if (snapshots == null) {
            throw new ServerApiException(BaseCmd.SNAPSHOT_LIST_ERROR, "unable to find snapshots for volume with id " + volumeId);
        }

        Object[] snapshotTag = new Object[snapshots.size()];
        int i = 0;

        for (Snapshot snapshot : snapshots) {
            List> snapshotData = new ArrayList>();
            snapshotData.add(new Pair(BaseCmd.Properties.ID.getName(), snapshot.getId().toString()));

            Account acct = getManagementServer().findAccountById(Long.valueOf(snapshot.getAccountId()));
            if (acct != null) {
                snapshotData.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), acct.getAccountName()));
                snapshotData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), Long.toString(acct.getDomainId())));
                snapshotData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(acct.getDomainId()).getName()));
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            }
            snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId()));
Solution content
                snapshotResponse.setDomainId(acct.getDomainId());
                snapshotResponse.setDomainName(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
            }

            VolumeVO volume = ApiDBUtils.findVolumeById(snapshot.getVolumeId());
            String snapshotTypeStr = SnapshotType.values()[snapshot.getSnapshotType()].name();
            snapshotResponse.setSnapshotType(snapshotTypeStr);
            snapshotResponse.setVolumeId(snapshot.getVolumeId());
            snapshotResponse.setVolumeName(volume.getName());
            snapshotResponse.setVolumeType(volume.getVolumeType().name());
            snapshotResponse.setCreated(snapshot.getCreated());
            snapshotResponse.setName(snapshot.getName());

            AsyncJobVO asyncJob = ApiDBUtils.findInstancePendingAsyncJob("snapshot", snapshot.getId());
            if (asyncJob != null) {
                snapshotResponse.setJobId(asyncJob.getId());
                snapshotResponse.setJobStatus(asyncJob.getStatus());
            }
            snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId()));
File
ListSnapshotsCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
For statement
If statement
Method invocation
Try statement
Variable
Chunk
Conflicting content
<<<<<<< HEAD
import com.cloud.api.ApiDBUtils;
import com.cloud.api.Parameter;

import org.apache.log4j.Logger;

import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.TemplatePermissionsResponse;
=======
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.domain.Domain;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.TemplatePermissionsResponse;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
File
ListTemplateOrIsoPermissionsCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    protected Logger getLogger() {
    	return Logger.getLogger(UpdateTemplateOrIsoPermissionsCmd.class.getName());    
    }
<<<<<<< HEAD
=======

    @Override
    public List> execute(Map params) {
        Long id = (Long)params.get(BaseCmd.Properties.ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String acctName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list " + getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = getManagementServer().findAccountByName(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = getManagementServer().findTemplateById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find " + getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
        	if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
        		throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to list permissions for " + getMediaType() + " with id " + id);
        	} else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
        		Domain accountDomain = getManagementServer().findDomainIdById(account.getDomainId());
        		Account templateAccount = getManagementServer().findAccountById(template.getAccountId());
        		Domain templateDomain = getManagementServer().findDomainIdById(templateAccount.getDomainId());        			
            	if (!templateDomain.getPath().contains(accountDomain.getPath())) {
            		throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to list permissions for " + getMediaType() + " with id " + id);
            	}
        	}                                    
        }

        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to list permissions for " + getMediaType() + " with id " + id);
        }

        List accountNames = getManagementServer().listTemplatePermissions(id);

        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        Long templateOwnerDomain = null;
        if (isAdmin) {
            Account templateOwner = getManagementServer().findAccountById(template.getAccountId());
            if (templateOwner != null) {
                templateOwnerDomain = templateOwner.getDomainId();
            }
        }

        List> embeddedObject = new ArrayList>();
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), template.getId().toString()));
        returnValues.add(new Pair(BaseCmd.Properties.IS_PUBLIC.getName(), Boolean.valueOf(template.isPublicTemplate()).toString()));
        if (isAdmin && (templateOwnerDomain != null)) {
            returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), templateOwnerDomain.toString()));
        }
        if ((accountNames != null) && !accountNames.isEmpty()) {
            for (String accountName : accountNames) {
                returnValues.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountName));
            }
        }
        embeddedObject.add(new Pair(getMediaType() + "permission", new Object[] { returnValues } ));
        return embeddedObject;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    protected Logger getLogger() {
    	return Logger.getLogger(UpdateTemplateOrIsoPermissionsCmd.class.getName());    
    }
}
File
ListTemplateOrIsoPermissionsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
<<<<<<< HEAD

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.UserVmResponse;
import com.cloud.async.AsyncJobVO;
import com.cloud.offering.ServiceOffering;
=======
import java.util.Map;
import org.apache.log4j.Logger;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.async.AsyncJobVO;
import com.cloud.domain.DomainVO;
import com.cloud.host.HostVO;
import com.cloud.server.Criteria;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.StoragePoolVO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.user.Account;
Solution content
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.UserVmResponse;
import com.cloud.async.AsyncJobVO;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.user.Account;
<<<<<<< HEAD
import com.cloud.user.UserContext;
import com.cloud.vm.UserVmVO;
=======
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.vm.InstanceGroupVO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.vm.VmStats;

@Implementation(method="searchForUserVMs")
Solution content
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VmStats;

@Implementation(method="searchForUserVMs")
File
ListVMsCmd.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
    public static final Logger s_logger = Logger.getLogger(ListVMsCmd.class.getName());

    private static final String s_name = "listvirtualmachinesresponse";
<<<<<<< HEAD
=======
    private static final List> s_properties = new ArrayList>();

    static {
    	s_properties.add(new Pair(BaseCmd.Properties.ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.NAME, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.STATE, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ZONE_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.POD_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.GROUP_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.HOST_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.KEYWORD, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.DOMAIN_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.PAGE, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.PAGESIZE, Boolean.FALSE));
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
Solution content
    public static final Logger s_logger = Logger.getLogger(ListVMsCmd.class.getName());

    private static final String s_name = "listvirtualmachinesresponse";

    /////////////////////////////////////////////////////
    //////////////// API parameters /////////////////////
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Attribute
Method invocation
Static initializer
Chunk
Conflicting content
    }

<<<<<<< HEAD
        return accountName;
    public Long getDomainId() {
        return domainId;
    }
=======
    @Override
    public List> execute(Map params) {
    	Long id = (Long)params.get(BaseCmd.Properties.ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        String name = (String) params.get(BaseCmd.Properties.NAME.getName());
        String state = (String) params.get(BaseCmd.Properties.STATE.getName());
        Long zoneId = (Long)params.get(BaseCmd.Properties.ZONE_ID.getName());
        Long podId = (Long)params.get(BaseCmd.Properties.POD_ID.getName());
        Long hostId = (Long)params.get(BaseCmd.Properties.HOST_ID.getName());
        Long groupId = (Long)params.get(BaseCmd.Properties.GROUP_ID.getName());
        String keyword = (String)params.get(BaseCmd.Properties.KEYWORD.getName());
        Integer page = (Integer)params.get(BaseCmd.Properties.PAGE.getName());
        Integer pageSize = (Integer)params.get(BaseCmd.Properties.PAGESIZE.getName());
        Long accountId = null;
        Boolean isAdmin = false;

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list virtual machines.");
                }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    public Long getHostId() {
        return hostId;
Solution content
        return accountName;
    }

    public Long getDomainId() {
        return domainId;
    }

    public Long getHostId() {
        return hostId;
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
If statement
Method declaration
Method signature
Variable
Chunk
Conflicting content
        return hostId;
    }

<<<<<<< HEAD
    public Long getId() {
        return id;
    }
=======
        if(account!=null && domainId==null){
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Please specify the domain id for this account:"+account.getId());
        }
        
        Long[] accountIds = null;
        if (accountId != null) {
            accountIds = new Long[1];
            accountIds[0] = accountId;
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    public String getInstanceName() {
        return instanceName;
Solution content
        return hostId;
    }

    public Long getId() {
        return id;
    }

    public String getInstanceName() {
        return instanceName;
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
If statement
Method declaration
Variable
Chunk
Conflicting content
        return instanceName;
    }

<<<<<<< HEAD
    public Long getPodId() {
        return podId;
    }
=======
        c.addCriteria(Criteria.ACCOUNTID, accountIds);
        c.addCriteria(Criteria.ISADMIN, isAdmin); 
        c.addCriteria(Criteria.GROUPID, groupId); 
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    public String getState() {
        return state;
Solution content
        return instanceName;
    }

    public Long getPodId() {
        return podId;
    }

    public String getState() {
        return state;
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Method declaration
Method invocation
Chunk
Conflicting content
        return state;
    }

<<<<<<< HEAD
    public Long getZoneId() {
        return zoneId;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////
=======
        if (virtualMachines == null) {
            throw new ServerApiException(BaseCmd.VM_LIST_ERROR, "unable to find virtual machines for account id " + accountName.toString());
        }
        
        Object[] vmTag = new Object[virtualMachines.size()];
        int i = 0;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    @Override
	public String getName() {
Solution content
        return state;
    }

    public Long getZoneId() {
        return zoneId;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
	public String getName() {
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method declaration
Method invocation
Variable
Chunk
Conflicting content
        return s_name;
    }

<<<<<<< HEAD
    @Override @SuppressWarnings("unchecked")
	public ResponseObject getResponse() {
        List userVms = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List vmResponses = new ArrayList();
        for (UserVmVO userVm : userVms) {
            UserVmResponse userVmResponse = new UserVmResponse();
            userVmResponse.setId(userVm.getId());
            AsyncJobVO asyncJob = ApiDBUtils.findInstancePendingAsyncJob("vm_instance", userVm.getId());
            if (asyncJob != null) {
                userVmResponse.setJobId(asyncJob.getId());
                userVmResponse.setJobStatus(asyncJob.getStatus());
            } 

            userVmResponse.setName(userVm.getName());
            userVmResponse.setCreated(userVm.getCreated());
            userVmResponse.setPrivateIp(userVm.getPrivateIpAddress());
            if (userVm.getState() != null) {
                userVmResponse.setState(userVm.getState().toString());
=======
        for (UserVm vmInstance : virtualMachines) {
    
        	//if the account is deleted, do not return the user vm 
        	Account currentVmAccount = getManagementServer().getAccount(vmInstance.getAccountId());
        	if(currentVmAccount.getRemoved()!=null)
        	{
        		continue; //not returning this vm
        	}
        	
            List> vmData = new ArrayList>();
            AsyncJobVO asyncJob = getManagementServer().findInstancePendingAsyncJob("vm_instance", vmInstance.getId());
            if(asyncJob != null) {
                vmData.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), asyncJob.getId().toString()));
                vmData.add(new Pair(BaseCmd.Properties.JOB_STATUS.getName(), String.valueOf(asyncJob.getStatus())));
            } 

            vmData.add(new Pair(BaseCmd.Properties.ID.getName(), Long.toString(vmInstance.getId())));
            vmData.add(new Pair(BaseCmd.Properties.NAME.getName(), vmInstance.getName()));
            vmData.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(vmInstance.getCreated())));
            vmData.add(new Pair(BaseCmd.Properties.IP_ADDRESS.getName(), vmInstance.getPrivateIpAddress()));
            
            if (vmInstance.getState() != null) {
                vmData.add(new Pair(BaseCmd.Properties.STATE.getName(), vmInstance.getState().toString()));
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            }

            Account acct = ApiDBUtils.findAccountById(Long.valueOf(userVm.getAccountId()));
Solution content
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
	public ResponseObject getResponse() {
        List userVms = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List vmResponses = new ArrayList();
        for (UserVmVO userVm : userVms) {
            UserVmResponse userVmResponse = new UserVmResponse();
            userVmResponse.setId(userVm.getId());
            AsyncJobVO asyncJob = ApiDBUtils.findInstancePendingAsyncJob("vm_instance", userVm.getId());
            if (asyncJob != null) {
                userVmResponse.setJobId(asyncJob.getId());
                userVmResponse.setJobStatus(asyncJob.getStatus());
            } 

            userVmResponse.setName(userVm.getName());
            userVmResponse.setCreated(userVm.getCreated());
            userVmResponse.setPrivateIp(userVm.getPrivateIpAddress());
            if (userVm.getState() != null) {
                userVmResponse.setState(userVm.getState().toString());
            }

            Account acct = ApiDBUtils.findAccountById(Long.valueOf(userVm.getAccountId()));
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
For statement
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
            Account acct = ApiDBUtils.findAccountById(Long.valueOf(userVm.getAccountId()));
            if (acct != null) {
<<<<<<< HEAD
                userVmResponse.setAccountName(acct.getAccountName());
                userVmResponse.setDomainId(acct.getDomainId());
                userVmResponse.setDomainName(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
=======
                vmData.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), acct.getAccountName()));
                vmData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), Long.toString(acct.getDomainId())));
                vmData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(acct.getDomainId()).getName()));
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            }

            userVmResponse.setHaEnable(userVm.isHaEnabled());
Solution content
            Account acct = ApiDBUtils.findAccountById(Long.valueOf(userVm.getAccountId()));
            if (acct != null) {
                userVmResponse.setAccountName(acct.getAccountName());
                userVmResponse.setDomainId(acct.getDomainId());
                userVmResponse.setDomainName(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
            }

            userVmResponse.setHaEnable(userVm.isHaEnabled());
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Method invocation
Chunk
Conflicting content
            } else {
                userVmResponse.setDisplayName(userVm.getName());
            }
<<<<<<< HEAD

            userVmResponse.setGroup(userVm.getGroup());

=======
            
            //Groups
            InstanceGroupVO group = getManagementServer().getGroupForVm(vmInstance.getId());
            if (group != null) {
            	vmData.add(new Pair(BaseCmd.Properties.GROUP_ID.getName(), group.getId()));
                vmData.add(new Pair(BaseCmd.Properties.GROUP.getName(), group.getName()));
            }
            
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            // Data Center Info
            userVmResponse.setZoneId(userVm.getDataCenterId());
            userVmResponse.setZoneName(ApiDBUtils.findZoneById(userVm.getDataCenterId()).getName());
Solution content
            } else {
                userVmResponse.setDisplayName(userVm.getName());
            }

            InstanceGroupVO group = ApiDBUtils.findInstanceGroupForVM(userVm.getId());
            if (group != null) {
                userVmResponse.setGroup(group.getName());
                userVmResponse.setGroupId(group.getId());
            }

            // Data Center Info
            userVmResponse.setZoneId(userVm.getDataCenterId());
            userVmResponse.setZoneName(ApiDBUtils.findZoneById(userVm.getDataCenterId()).getName());
File
ListVMsCmd.java
Developer's decision
Manual
Kind of conflict
Comment
If statement
Method invocation
Variable
Chunk
Conflicting content
            }
            vmData.add(new Pair(BaseCmd.Properties.GUEST_OS_ID.getName(), vmInstance.getGuestOSId()));
            
<<<<<<< HEAD
            userVmResponse.setOsTypeId(userVm.getGuestOSId());

            //network groups
            userVmResponse.setNetworkGroupList(ApiDBUtils.getNetworkGroupsNamesForVm(userVm.getId()));

            userVmResponse.setResponseName("virtualmachine");
            vmResponses.add(userVmResponse);
=======
            GuestOSVO guestOs = getManagementServer().getGuestOs(vmInstance.getGuestOSId());
            if(guestOs!=null)
            	vmData.add(new Pair(BaseCmd.Properties.OS_TYPE_ID.getName(),guestOs.getCategoryId()));

            //network groups
            vmData.add(new Pair(BaseCmd.Properties.NETWORK_GROUP_LIST.getName(), getManagementServer().getNetworkGroupsNamesForVm(vmInstance.getId())));
            
            //root device related
            VolumeVO rootVolume = getManagementServer().findRootVolume(vmInstance.getId());
            if(rootVolume!=null)
            {
            	vmData.add(new Pair(BaseCmd.Properties.ROOT_DEVICE_ID.getName(), rootVolume.getDeviceId()));
            
            	StoragePoolVO storagePool = getManagementServer().findPoolById(rootVolume.getPoolId());
            	vmData.add(new Pair(BaseCmd.Properties.ROOT_DEVICE_TYPE.getName(), storagePool.getPoolType().toString()));
            }
            
            vmTag[i++] = vmData;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }

        response.setResponses(vmResponses);
Solution content
            }
            
            userVmResponse.setOsTypeId(userVm.getGuestOSId());

            //network groups
            userVmResponse.setNetworkGroupList(ApiDBUtils.getNetworkGroupsNamesForVm(userVm.getId()));

            userVmResponse.setResponseName("virtualmachine");
            vmResponses.add(userVmResponse);
        }

        response.setResponses(vmResponses);
File
ListVMsCmd.java
Developer's decision
Version 1
Kind of conflict
Array access
Comment
If statement
Method invocation
Variable
Chunk
Conflicting content
        if (keyword != null) {
        c.addCriteria(Criteria.ACCOUNTID, accountIds);
        return s_name;
    }

<<<<<<< HEAD
    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List volumes = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List volResponses = new ArrayList();
=======
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !getManagementServer().isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = getManagementServer().findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Long[] accountIds = null;
        if (accountId != null) {
            accountIds = new Long[1];
            accountIds[0] = accountId;   
        }

        Long startIndex = Long.valueOf(0);
        int pageSizeNum = 50;
        if (pageSize != null) {
            pageSizeNum = pageSize.intValue();
        }
        if (page != null) {
            int pageNum = page.intValue();
            if (pageNum > 0) {
                startIndex = Long.valueOf(pageSizeNum * (pageNum-1));
            }
        }

        Criteria c = new Criteria("created", Boolean.FALSE, startIndex, Long.valueOf(pageSizeNum));

            c.addCriteria(Criteria.KEYWORD, keyword);
        } else {
            c.addCriteria(Criteria.ID, id);
            c.addCriteria(Criteria.INSTANCEID, vmId);
            c.addCriteria(Criteria.NAME, name);
            c.addCriteria(Criteria.VTYPE, type);
            if (isAdmin) {                
                c.addCriteria(Criteria.DATACENTERID, zoneId);
                c.addCriteria(Criteria.PODID, podId);
                c.addCriteria(Criteria.HOSTID, hostId);
                c.addCriteria(Criteria.DOMAINID, domainId);
            }
        }

        List volumes = getManagementServer().searchForVolumes(c);

        if (volumes == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find volumes");
        }

        List> volumeTags = new ArrayList>();
        Object[] vTag = new Object[volumes.size()];
        int i = 0;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        for (VolumeVO volume : volumes) {
            VolumeResponse volResponse = new VolumeResponse();
            volResponse.setId(volume.getId());
Solution content
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List volumes = (List)getResponseObject();

        ListResponse response = new ListResponse();
        List volResponses = new ArrayList();
        for (VolumeVO volume : volumes) {
            VolumeResponse volResponse = new VolumeResponse();
            volResponse.setId(volume.getId());
File
ListVolumesCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
                volResponse.setName("");
            }
            
<<<<<<< HEAD
            volResponse.setZoneId(volume.getDataCenterId());
            volResponse.setZoneName(ApiDBUtils.findZoneById(volume.getDataCenterId()).getName());

            volResponse.setVolumeType(volume.getVolumeType().toString());
            volResponse.setDeviceId(volume.getDeviceId());
            
            Long instanceId = volume.getInstanceId();
            if (instanceId != null) {
                VMInstanceVO vm = ApiDBUtils.findVMInstanceById(instanceId);
                volResponse.setVirtualMachineId(vm.getId());
                volResponse.setVirtualMachineName(vm.getName());
                volResponse.setVirtualMachineDisplayName(vm.getName());
                volResponse.setVirtualMachineState(vm.getState().toString());
            }             

            // Show the virtual size of the volume
            volResponse.setSize(volume.getSize());

            volResponse.setCreated(volume.getCreated());
            volResponse.setState(volume.getStatus().toString());
            
            Account accountTemp = ApiDBUtils.findAccountById(volume.getAccountId());
            if (accountTemp != null) {
                volResponse.setAccountName(accountTemp.getAccountName());
                volResponse.setDomainId(accountTemp.getDomainId());
                volResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
            }

            String storageType;
=======
            volumeData.add(new Pair(BaseCmd.Properties.ZONE_ID.getName(), Long.valueOf(volume.getDataCenterId()).toString()));
            volumeData.add(new Pair(BaseCmd.Properties.ZONE_NAME.getName(), getManagementServer().findDataCenterById(volume.getDataCenterId()).getName()));

            volumeData.add(new Pair(BaseCmd.Properties.TYPE.getName(), volume.getVolumeType()));
            //volumeData.add(new Pair(BaseCmd.Properties.HOST_NAME.getName(), getManagementServer().getHostBy(volume.getHostId()).getName()));

//            //volume.getDeviceId() might be null	
//            if(volume.getDeviceId() != null)
//                volumeData.add(new Pair(BaseCmd.Properties.DEVICE_ID.getName(), Long.valueOf(volume.getDeviceId()).toString()));
            
            Long instanceId = volume.getInstanceId();
            if (instanceId != null) {
                VMInstanceVO vm = getManagementServer().findVMInstanceById(instanceId);
                volumeData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName(), vm.getId()));
                volumeData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_NAME.getName(), vm.getName()));
                volumeData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_DISPLAYNAME.getName(), vm.getName()));
                volumeData.add(new Pair(BaseCmd.Properties.VIRTUAL_MACHINE_STATE.getName(), vm.getState()));
                volumeData.add(new Pair(BaseCmd.Properties.DEVICE_ID.getName(), volume.getDeviceId()));
            }

            // Show the virtual size of the volume
            long virtualSizeInBytes = volume.getSize();
            volumeData.add(new Pair(BaseCmd.Properties.SIZE.getName(), virtualSizeInBytes));

            volumeData.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(volume.getCreated())));
            volumeData.add(new Pair(BaseCmd.Properties.ATTACHED.getName(), getDateString(volume.getAttached())));
            volumeData.add(new Pair(BaseCmd.Properties.STATE.getName(),volume.getStatus()));
            
            Account accountTemp = getManagementServer().findAccountById(volume.getAccountId());

            if (accountTemp != null) {
                volumeData.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountTemp.getAccountName()));
                volumeData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), accountTemp.getDomainId()));
                volumeData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(accountTemp.getDomainId()).getName()));
            }

            String storageType;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            try {
                if(volume.getPoolId() == null){
                    storageType = "unknown";
Solution content
                volResponse.setName("");
            }
            
            volResponse.setZoneId(volume.getDataCenterId());
            volResponse.setZoneName(ApiDBUtils.findZoneById(volume.getDataCenterId()).getName());

            volResponse.setVolumeType(volume.getVolumeType().toString());
            volResponse.setDeviceId(volume.getDeviceId());
            
            Long instanceId = volume.getInstanceId();
            if (instanceId != null) {
                VMInstanceVO vm = ApiDBUtils.findVMInstanceById(instanceId);
                volResponse.setVirtualMachineId(vm.getId());
                volResponse.setVirtualMachineName(vm.getName());
                volResponse.setVirtualMachineDisplayName(vm.getName());
                volResponse.setVirtualMachineState(vm.getState().toString());
            }             

            // Show the virtual size of the volume
            volResponse.setSize(volume.getSize());

            volResponse.setCreated(volume.getCreated());
            volResponse.setState(volume.getStatus().toString());
            
            Account accountTemp = ApiDBUtils.findAccountById(volume.getAccountId());
            if (accountTemp != null) {
                volResponse.setAccountName(accountTemp.getAccountName());
                volResponse.setDomainId(accountTemp.getDomainId());
                volResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
            }

            String storageType;
            try {
                if(volume.getPoolId() == null){
                    storageType = "unknown";
File
ListVolumesCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Variable
Chunk
Conflicting content
            volResponse.setStorageType(storageType);
            
<<<<<<< HEAD
            volResponse.setDiskOfferingId(volume.getDiskOfferingId());
            if (volume.getDiskOfferingId() != null) {
                DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
                volResponse.setDiskOfferingName(diskOffering.getName());
                volResponse.setDiskOfferingDisplayText(diskOffering.getDisplayText());
            }

            Long poolId = volume.getPoolId();
            String poolName = (poolId == null) ? "none" : ApiDBUtils.findStoragePoolById(poolId).getName();
            volResponse.setStoragePoolName(poolName);

            volResponse.setResponseName("volume");
            volResponses.add(volResponse);
        }

        response.setResponses(volResponses);
        response.setResponseName(getName());
        return response;
=======
            volumeData.add(new Pair(BaseCmd.Properties.DISK_OFFERING_ID.getName(),volume.getDiskOfferingId()));
        	volumeData.add(new Pair(BaseCmd.Properties.DISK_OFFERING_NAME.getName(),getManagementServer().findDiskOfferingById(volume.getDiskOfferingId()).getName()));
        	volumeData.add(new Pair(BaseCmd.Properties.DISK_OFFERING_DISPLAY_TEXT.getName(),getManagementServer().findDiskOfferingById(volume.getDiskOfferingId()).getDisplayText()));
            Long poolId = volume.getPoolId();
            String poolName = (poolId == null) ? "none" : getManagementServer().findPoolById(poolId).getName();
            volumeData.add(new Pair(BaseCmd.Properties.STORAGE.getName(), poolName));
            volumeData.add(new Pair(BaseCmd.Properties.SOURCE_ID.getName(),volume.getSourceId()));
            volumeData.add(new Pair(BaseCmd.Properties.SOURCE_TYPE.getName(),volume.getSourceType().toString()));
            
            vTag[i++] = volumeData;
        }
        Pair volumeTag = new Pair("volume", vTag);
        volumeTags.add(volumeTag);
        return volumeTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
            volResponse.setStorageType(storageType);
            
            volResponse.setDiskOfferingId(volume.getDiskOfferingId());

            DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
            volResponse.setDiskOfferingName(diskOffering.getName());
            volResponse.setDiskOfferingDisplayText(diskOffering.getDisplayText());

            Long poolId = volume.getPoolId();
            String poolName = (poolId == null) ? "none" : ApiDBUtils.findStoragePoolById(poolId).getName();
            volResponse.setStoragePoolName(poolName);

            volResponse.setResponseName("volume");
            volResponses.add(volResponse);
        }

        response.setResponses(volResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListVolumesCmd.java
Developer's decision
Combination
Kind of conflict
Array access
If statement
Method invocation
Return statement
Variable
Chunk
Conflicting content
import com.cloud.api.ServerApiException;

import java.util.ArrayList;
import java.util.List;
<<<<<<< HEAD

import org.apache.log4j.Logger;

import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.ZoneResponse;
=======
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.dc.DataCenterVO;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
Solution content
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.ZoneResponse;
import com.cloud.dc.DataCenterVO;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
File
ListZonesByCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
            	}
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List dataCenters = (List)getResponseObject();
        Account account = (Account)UserContext.current().getAccountObject();

        ListResponse response = new ListResponse();
        List zoneResponses = new ArrayList();
        for (DataCenterVO dataCenter : dataCenters) {
            ZoneResponse zoneResponse = new ZoneResponse();
            zoneResponse.setId(dataCenter.getId());
            zoneResponse.setName(dataCenter.getName());

            if ((dataCenter.getDescription() != null) && !dataCenter.getDescription().equalsIgnoreCase("null")) {
                zoneResponse.setDescription(dataCenter.getDescription());
            }

            if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
                zoneResponse.setDns1(dataCenter.getDns1());
                zoneResponse.setDns2(dataCenter.getDns2());
                zoneResponse.setInternalDns1(dataCenter.getInternalDns1());
                zoneResponse.setInternalDns2(dataCenter.getInternalDns2());
                zoneResponse.setVlan(dataCenter.getVnet());
                zoneResponse.setGuestCidrAddress(dataCenter.getGuestNetworkCidr());
            }

            zoneResponse.setResponseName("zone");
            zoneResponses.add(zoneResponse);
        }

        response.setResponses(zoneResponses);
        response.setResponseName(getName());
        return response;
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Boolean available = (Boolean)params.get(BaseCmd.Properties.AVAILABLE.getName());
        
        List dataCenters = null;
        if (account != null) {
        	if (available != null && available) {
        		dataCenters = getManagementServer().listDataCenters();
        	} else {
        		dataCenters = getManagementServer().listDataCentersBy(account.getId());
        	}
        } else {
        	// available is kinda useless in this case because we can't exactly list by
        	// accountId if we don't have one.  In this case, we just assume the user
        	// wants all the zones.
            dataCenters = getManagementServer().listDataCenters();
        }

        if (dataCenters == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find zones for account " + account.getAccountName());
        }
        List> dcTags = new ArrayList>();
        Object[] dcInstTag = new Object[dataCenters.size()];
        int i = 0;
        for (DataCenterVO dataCenter : dataCenters) {
            List> dcData = new ArrayList>();
            dcData.add(new Pair(BaseCmd.Properties.ID.getName(), Long.toString(dataCenter.getId())));
            dcData.add(new Pair(BaseCmd.Properties.NAME.getName(), dataCenter.getName()));
            if ((dataCenter.getDescription() != null) && !dataCenter.getDescription().equalsIgnoreCase("null")) {
                dcData.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), dataCenter.getDescription()));
            }
            if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            	if (dataCenter.getDns1() != null) {
            		dcData.add(new Pair(BaseCmd.Properties.DNS1.getName(), dataCenter.getDns1()));
            	if (dataCenter.getDns2() != null) {
            		dcData.add(new Pair(BaseCmd.Properties.DNS2.getName(), dataCenter.getDns2()));
            	}
                if (dataCenter.getInternalDns1() != null) {
                    dcData.add(new Pair(BaseCmd.Properties.INTERNAL_DNS1.getName(), dataCenter.getInternalDns1()));
                }
                if (dataCenter.getInternalDns2() != null) {
                    dcData.add(new Pair(BaseCmd.Properties.INTERNAL_DNS2.getName(), dataCenter.getInternalDns2()));
                }
                if (dataCenter.getVnet() != null) {
                    dcData.add(new Pair("vlan", dataCenter.getVnet()));
                }
                if (dataCenter.getGuestNetworkCidr() != null) {
            		dcData.add(new Pair(BaseCmd.Properties.GUEST_CIDR_ADDRESS.getName(), dataCenter.getGuestNetworkCidr()));
            	}
            }

            dcInstTag[i++] = dcData;
        }
        Pair dcTag = new Pair("zone", dcInstTag);
        dcTags.add(dcTag);
        return dcTags;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }

    @Override @SuppressWarnings("unchecked")
    public ResponseObject getResponse() {
        List dataCenters = (List)getResponseObject();
        Account account = (Account)UserContext.current().getAccountObject();

        ListResponse response = new ListResponse();
        List zoneResponses = new ArrayList();
        for (DataCenterVO dataCenter : dataCenters) {
            ZoneResponse zoneResponse = new ZoneResponse();
            zoneResponse.setId(dataCenter.getId());
            zoneResponse.setName(dataCenter.getName());

            if ((dataCenter.getDescription() != null) && !dataCenter.getDescription().equalsIgnoreCase("null")) {
                zoneResponse.setDescription(dataCenter.getDescription());
            }

            if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
                zoneResponse.setDns1(dataCenter.getDns1());
                zoneResponse.setDns2(dataCenter.getDns2());
                zoneResponse.setInternalDns1(dataCenter.getInternalDns1());
                zoneResponse.setInternalDns2(dataCenter.getInternalDns2());
                zoneResponse.setVlan(dataCenter.getVnet());
                zoneResponse.setGuestCidrAddress(dataCenter.getGuestNetworkCidr());
            }

            zoneResponse.setResponseName("zone");
            zoneResponses.add(zoneResponse);
        }

        response.setResponses(zoneResponses);
        response.setResponseName(getName());
        return response;
    }
}
File
ListZonesByCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
For statement
If statement
Method declaration
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
 */
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="lockAccount", manager=Manager.ManagementServer)
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
public class LockAccountCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(LockAccountCmd.class.getName());
Solution content
 */
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="lockAccount", manager=Manager.ManagementServer)
public class LockAccountCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(LockAccountCmd.class.getName());
File
LockAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Import
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
=======
    }
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account adminAccount = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());

        if ((adminAccount != null) && !getManagementServer().isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = getManagementServer().findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }
        boolean success = getManagementServer().lockAccount(account.getId());
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.SUCCESS.getName(), Boolean.valueOf(success).toString()));
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
}
File
LockAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="maintain", manager=Manager.AgentManager)
public class PrepareForMaintenanceCmd extends BaseAsyncCmd {
	public static final Logger s_logger = Logger.getLogger(PrepareForMaintenanceCmd.class.getName());	
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.HostVO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.utils.Pair;

public class PrepareForMaintenanceCmd extends BaseCmd {
	public static final Logger s_logger = Logger.getLogger(PrepareForMaintenanceCmd.class.getName());
	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    private static final String s_name = "preparehostformaintenanceresponse";

    /////////////////////////////////////////////////////
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="maintain", manager=Manager.AgentManager)
public class PrepareForMaintenanceCmd extends BaseAsyncCmd {
	public static final Logger s_logger = Logger.getLogger(PrepareForMaintenanceCmd.class.getName());
	
    private static final String s_name = "preparehostformaintenanceresponse";

    /////////////////////////////////////////////////////
File
PrepareForMaintenanceCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Attribute
Class signature
Import
Method invocation
Chunk
Conflicting content
    public static String getResultObjectName() {
    	return "host";
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
=======
    
    @Override
    public List> execute(Map params) {
        Long hostId = (Long)params.get(BaseCmd.Properties.ID.getName());
        
        //verify input parameters
    	HostVO host = getManagementServer().getHostBy(hostId);
    	if (host == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Host with id " + hostId.toString() + " doesn't exist");
    	}
        
    	//if this is the only host in the pool, you cannot enable maintenance on this host
    	boolean maintenable = getManagementServer().checkIfMaintenable(host.getId());
    	
    	if(!maintenable)
    	{
    		s_logger.warn("Unable to schedule host maintenance -- there is no host to take over as master in the pool");
    		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to schedule host maintenance -- there is no host to take over as master in the pool");
    	}
    	
    	long jobId = 0;
    	try {
    		jobId = getManagementServer().prepareForMaintenanceAsync(hostId);
    	} catch (InvalidParameterValueException e) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to prepare host for maintenance: " + e.getMessage());
    	}
    	
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for PrepareForMaintenance command");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("PrepareForMaintenance command has been accepted, job id: " + jobId);
        }
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public static String getResultObjectName() {
    	return "host";
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
}
File
PrepareForMaintenanceCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import org.apache.log4j.Logger;

<<<<<<< HEAD
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
=======
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Status;
import com.cloud.storage.StoragePoolVO;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

@Implementation(method="preparePrimaryStorageForMaintenance", manager=Manager.StorageManager)
public class PreparePrimaryStorageForMaintenanceCmd extends BaseAsyncCmd {
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="preparePrimaryStorageForMaintenance", manager=Manager.StorageManager)
public class PreparePrimaryStorageForMaintenanceCmd extends BaseAsyncCmd {
File
PreparePrimaryStorageForMaintenanceCmd.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
    public static String getResultObjectName() {
    	return "primarystorage";
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
=======
    
    @Override
    public List> execute(Map params) {
        Long storagePoolId = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        //verify input parameters
    	StoragePoolVO storagePool = getManagementServer().findPoolById(storagePoolId);
    	
    	if (storagePool == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Primary storage with id " + storagePoolId + " doesn't exist");
    	}
        
    	if (!storagePool.getStatus().equals(Status.Up)) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Primary storage with id " + storagePoolId + " is not ready for migration, as the status is:"+storagePool.getStatus().toString());
    	}
    	
    	if(getManagementServer().getPsMaintenanceCount(storagePool.getPodId()) > 0){
    		throw new ServerApiException(BaseCmd.INTERNAL_ERROR,"There already exist other storage pools in maintenance process");
    	}

    	long jobId = 0;
    	try {
    		jobId = getManagementServer().preparePrimaryStorageForMaintenanceAsync(storagePoolId);
    	} catch (InvalidParameterValueException e) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to prepare primary storage for maintenance: " + e.getMessage());
    	}
    	
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for PreparePrimaryStorageForMaintenance comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("PreparePrimaryStorageForMaintenance command has been accepted, job id: " + jobId);
        }
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        returnValues.add(new Pair(BaseCmd.Properties.STATE.getName(), Status.PrepareForMaintenance)); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public static String getResultObjectName() {
    	return "primarystorage";
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
}
File
PreparePrimaryStorageForMaintenanceCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content

package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;
@Implementation(method="rebootVirtualMachine", manager=Manager.UserVmManager)
public class RebootVMCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.UserVmVO;

public class RebootVMCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public static final Logger s_logger = Logger.getLogger(RebootVMCmd.class.getName());
    private static final String s_name = "rebootvirtualmachineresponse";
   
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="rebootVirtualMachine", manager=Manager.UserVmManager)
public class RebootVMCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(RebootVMCmd.class.getName());
    private static final String s_name = "rebootvirtualmachineresponse";
   
File
RebootVMCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
    public String getName() {
        return s_name;
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
=======
    
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.ID.getName());
        
        //Verify input parameters
        UserVmVO vmInstance = getManagementServer().findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                // the domain in which the VM lives is not in the admin's domain tree
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to reboot virtual machine with id " + vmId + ", invalid id given.");
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long jobId = getManagementServer().rebootVirtualMachineAsync(userId.longValue(), vmId.longValue());
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for RebootVM comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("RebootVM command has been accepted, job id: " + jobId);
        }
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
}
File
RebootVMCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.dc.DataCenterVO;
<<<<<<< HEAD
=======
import com.cloud.storage.Storage.FileSystem;
import com.cloud.storage.Storage.ImageFormat;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
Solution content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.dc.DataCenterVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
File
RegisterIsoCmd.java
Developer's decision
Manual
Kind of conflict
Import
Chunk
Conflicting content
<<<<<<< HEAD
    }

	@Override
    @Override
    public String getName() {
        return s_name;
	public ResponseObject getResponse() {
	    VMTemplateVO template = (VMTemplateVO)getResponseObject();

	    ListResponse response = new ListResponse();
	    List responses = new ArrayList();
	    List zones = null;

	    if (zoneId != null) {
	        zones = new ArrayList();
	        zones.add(ApiDBUtils.findZoneById(zoneId));
	    } else {
	        zones = ApiDBUtils.listZones();   
	    }

	    for (DataCenterVO zone : zones) {
	        TemplateResponse templateResponse = new TemplateResponse();
	        templateResponse.setId(template.getId());
	        templateResponse.setName(template.getName());
	        templateResponse.setDisplayText(template.getDisplayText());
	        templateResponse.setPublic(template.isPublicTemplate());

	        VMTemplateHostVO isoHostRef = ApiDBUtils.findTemplateHostRef(template.getId(), zone.getId());
	        if (isoHostRef != null) {
	            templateResponse.setCreated(isoHostRef.getCreated());
	            templateResponse.setReady(isoHostRef.getDownloadState() == Status.DOWNLOADED);
	        }

	        templateResponse.setFeatured(template.isFeatured());
            templateResponse.setBootable(template.isBootable());
            templateResponse.setOsTypeId(template.getGuestOSId());
            templateResponse.setOsTypeName(ApiDBUtils.findGuestOSById(template.getGuestOSId()).getName());
              
            Account owner = ApiDBUtils.findAccountById(template.getAccountId());
            if (owner != null) {
                templateResponse.setAccountId(owner.getId());
                templateResponse.setAccount(owner.getAccountName());
                templateResponse.setDomainId(owner.getDomainId());
            }

            templateResponse.setZoneId(zone.getId());
            templateResponse.setZoneName(zone.getName());
            templateResponse.setResponseName("iso");

            responses.add(templateResponse);
	    }
        response.setResponseName(getName());
        response.setResponses(responses);
        return response;
	}
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        String displayText = (String)params.get(BaseCmd.Properties.DISPLAY_TEXT.getName());
        String url = (String)params.get(BaseCmd.Properties.URL.getName());
        Boolean isPublic = (Boolean)params.get(BaseCmd.Properties.IS_PUBLIC.getName());
        Boolean featured = (Boolean)params.get(BaseCmd.Properties.IS_FEATURED.getName());
        Long guestOSId = (Long) params.get(BaseCmd.Properties.OS_TYPE_ID.getName());
        Boolean bootable = (Boolean) params.get(BaseCmd.Properties.BOOTABLE.getName());
        Long zoneId = (Long) params.get(BaseCmd.Properties.ZONE_ID.getName());

        if (isPublic == null) {
            isPublic = Boolean.FALSE;
        }
        
        if (zoneId.longValue() == -1) {
        	zoneId = null;
        }
        
        long accountId = 1L; // default to system account
        if (account != null) {
            accountId = account.getId();
        }
        
        Account accountObj;
        if (account == null) {
        	accountObj = getManagementServer().findAccountById(accountId);
        } else {
        	accountObj = account;
        }
        
        boolean isAdmin = (accountObj.getType() == Account.ACCOUNT_TYPE_ADMIN);
        
        if (!isAdmin && zoneId == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid zone Id.");
        }
        
        if((!url.toLowerCase().endsWith("iso"))&&(!url.toLowerCase().endsWith("iso.zip"))&&(!url.toLowerCase().endsWith("iso.bz2"))
        		&&(!url.toLowerCase().endsWith("iso.gz"))){
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid iso");
        }
        
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getManagementServer().getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private ISOs can be created.");
        }
        
        if (!isAdmin || featured == null) {
        	featured = Boolean.FALSE;
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(1);
        }
        
        if (bootable == null) {
        	bootable = Boolean.TRUE;
        }

        //removing support for file:// type urls (bug: 4239)
        if(url.toLowerCase().contains("file://")){
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "File:// type urls are currently unsupported");
        }
        
        Long templateId;
        try {
        	templateId = getManagementServer().createTemplate(userId, zoneId, name, displayText, isPublic.booleanValue(), featured.booleanValue(), ImageFormat.ISO.toString(), FileSystem.cdfs.toString(), url, null, true, 64 /*bits*/, false, guestOSId, bootable);
        } catch (Exception ex) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
        }
        
            
        VMTemplateVO template = getManagementServer().findTemplateById(templateId);        
        List> isoTags = new ArrayList>();
    	List iTagList = new ArrayList();
        if (template != null) {
        	List zones = null;
        	
        	if (zoneId != null) {
        		zones = new ArrayList();
        		zones.add(getManagementServer().findDataCenterById(zoneId));
        	} else {
        		zones = getManagementServer().listDataCenters();   
        	}
        	
        	for (DataCenterVO zone : zones) {
        		VMTemplateHostVO isoHostRef = getManagementServer().findTemplateHostRef(templateId, zone.getId());                		

        		// Use embeded object for response
        		List> listForEmbeddedObject = new ArrayList>();
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.ID.getName(), template.getId().toString()));
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.NAME.getName(), template.getName()));
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), template.getDisplayText()));
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.IS_PUBLIC.getName(), Boolean.valueOf(template.isPublicTemplate()).toString()));
        		
        		if (isoHostRef != null) {
        			listForEmbeddedObject.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(isoHostRef.getCreated())));
        		}
        		
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.IS_READY.getName(), (isoHostRef != null && isoHostRef.getDownloadState() == Status.DOWNLOADED)));
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.IS_FEATURED.getName(), Boolean.valueOf(template.isFeatured()).toString()));
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.BOOTABLE.getName(), Boolean.valueOf(template.isBootable()).toString()));
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.OS_TYPE_ID.getName(), template.getGuestOSId()));
        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.OS_TYPE_NAME.getName(), getManagementServer().findGuestOSById(template.getGuestOSId()).getName()));
        				
        		Account owner = getManagementServer().findAccountById(template.getAccountId());
        		if (owner != null) {
        			listForEmbeddedObject.add(new Pair(BaseCmd.Properties.ACCOUNT_ID.getName(), owner.getId()));
        			listForEmbeddedObject.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), owner.getAccountName()));
        			listForEmbeddedObject.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), owner.getDomainId()));
        		}

        		listForEmbeddedObject.add(new Pair(BaseCmd.Properties.ZONE_ID.getName(), zone.getId()));
    			listForEmbeddedObject.add(new Pair(BaseCmd.Properties.ZONE_NAME.getName(), zone.getName()));

    			iTagList.add(listForEmbeddedObject);            		
        	}
        }
        
        Object[] iTag = new Object[iTagList.size()];
        for (int i = 0; i < iTagList.size(); i++) {
        	iTag[i] = iTagList.get(i);
        }
                               
        Pair templateTag = new Pair("iso", iTag);
        isoTags.add(templateTag);

        return isoTags;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
	    VMTemplateVO template = (VMTemplateVO)getResponseObject();

	    ListResponse response = new ListResponse();
	    List responses = new ArrayList();
	    List zones = null;

	    if (zoneId != null) {
	        zones = new ArrayList();
	        zones.add(ApiDBUtils.findZoneById(zoneId));
	    } else {
	        zones = ApiDBUtils.listZones();   
	    }

	    for (DataCenterVO zone : zones) {
	        TemplateResponse templateResponse = new TemplateResponse();
	        templateResponse.setId(template.getId());
	        templateResponse.setName(template.getName());
	        templateResponse.setDisplayText(template.getDisplayText());
	        templateResponse.setPublic(template.isPublicTemplate());

	        VMTemplateHostVO isoHostRef = ApiDBUtils.findTemplateHostRef(template.getId(), zone.getId());
	        if (isoHostRef != null) {
	            templateResponse.setCreated(isoHostRef.getCreated());
	            templateResponse.setReady(isoHostRef.getDownloadState() == Status.DOWNLOADED);
	        }

	        templateResponse.setFeatured(template.isFeatured());
            templateResponse.setBootable(template.isBootable());
            templateResponse.setOsTypeId(template.getGuestOSId());
            templateResponse.setOsTypeName(ApiDBUtils.findGuestOSById(template.getGuestOSId()).getName());
              
            Account owner = ApiDBUtils.findAccountById(template.getAccountId());
            if (owner != null) {
                templateResponse.setAccountId(owner.getId());
                templateResponse.setAccount(owner.getAccountName());
                templateResponse.setDomainId(owner.getDomainId());
            }

            templateResponse.setZoneId(zone.getId());
            templateResponse.setZoneName(zone.getName());
            templateResponse.setResponseName("iso");

            responses.add(templateResponse);
	    }
        response.setResponseName(getName());
        response.setResponses(responses);
        return response;
	}
}
File
RegisterIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }

	@Override
	public ResponseObject getResponse() {
        VMTemplateVO template = (VMTemplateVO)getResponseObject();

        ListResponse response = new ListResponse();
        List responses = new ArrayList();
        List zones = null;

        if (zoneId != null) {
            zones = new ArrayList();
            zones.add(ApiDBUtils.findZoneById(zoneId));
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        String displayText = (String)params.get(BaseCmd.Properties.DISPLAY_TEXT.getName()); 
        Integer bits = (Integer)params.get(BaseCmd.Properties.BITS.getName());
        Boolean passwordEnabled = (Boolean)params.get(BaseCmd.Properties.PASSWORD_ENABLED.getName());
        Boolean requiresHVM = (Boolean)params.get(BaseCmd.Properties.REQUIRES_HVM.getName());
        String url = (String)params.get(BaseCmd.Properties.URL.getName());
        Boolean isPublic = (Boolean)params.get(BaseCmd.Properties.IS_PUBLIC.getName());
        Boolean featured = (Boolean)params.get(BaseCmd.Properties.IS_FEATURED.getName());
        String format = (String)params.get(BaseCmd.Properties.FORMAT.getName());
        Long guestOSId = (Long) params.get(BaseCmd.Properties.OS_TYPE_ID.getName());
        Long zoneId = (Long) params.get(BaseCmd.Properties.ZONE_ID.getName());

        //parameters verification
        if (bits == null) {
            bits = Integer.valueOf(64);
        }
        if (passwordEnabled == null) {
            passwordEnabled = false;
        }
        if (requiresHVM == null) {
            requiresHVM = true;
        }
        if (isPublic == null) {
            isPublic = Boolean.FALSE;
        }
        
        if (zoneId.longValue() == -1) {
        	zoneId = null;
        }
                
        long accountId = 1L; // default to system account
        if (account != null) {
            accountId = account.getId();
        }
        
        Account accountObj;
        if (account == null) {
        	accountObj = getManagementServer().findAccountById(accountId);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        } else {
            zones = ApiDBUtils.listZones();   
        }
Solution content
    @Override
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
        VMTemplateVO template = (VMTemplateVO)getResponseObject();

        ListResponse response = new ListResponse();
        List responses = new ArrayList();
        List zones = null;

        if (zoneId != null) {
            zones = new ArrayList();
            zones.add(ApiDBUtils.findZoneById(zoneId));
        } else {
            zones = ApiDBUtils.listZones();   
        }
File
RegisterTemplateCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Variable
Chunk
Conflicting content
<<<<<<< HEAD
import java.util.List;
package com.cloud.api.commands;


import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.response.SuccessResponse;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;

@Implementation(method="removeFromLoadBalancer", manager=Manager.NetworkManager)
public class RemoveFromLoadBalancerRuleCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.network.LoadBalancerVO;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public class RemoveFromLoadBalancerRuleCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public static final Logger s_logger = Logger.getLogger(RemoveFromLoadBalancerRuleCmd.class.getName());

    private static final String s_name = "removefromloadbalancerruleresponse";
Solution content
package com.cloud.api.commands;

import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="removeFromLoadBalancer", manager=Manager.NetworkManager)
public class RemoveFromLoadBalancerRuleCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(RemoveFromLoadBalancerRuleCmd.class.getName());

    private static final String s_name = "removefromloadbalancerruleresponse";
File
RemoveFromLoadBalancerRuleCmd.java
Developer's decision
Combination
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
    public String getName() {
        return s_name;
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
	    Boolean success = (Boolean)getResponseObject();
	    SuccessResponse response = new SuccessResponse();
	    response.setSuccess(success);
	    response.setResponseName(getName());
	    return response;
	}
=======
    
    public List> getProperties() {
        return s_properties;
    }
    
    @Override
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long loadBalancerId = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long instanceId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
        String instanceIds = (String)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_IDS.getName());

        if ((instanceId == null) && (instanceIds == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No virtual machine id specified.");
        }

        List instanceIdList = new ArrayList();
        if (instanceIds != null) {
            StringTokenizer st = new StringTokenizer(instanceIds, ",");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                try {
                    Long nextInstanceId = Long.parseLong(token);
                    instanceIdList.add(nextInstanceId);
                } catch (NumberFormatException nfe) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "The virtual machine id " + token + " is not a valid parameter.");
                }
            }
        } else {
            instanceIdList.add(instanceId);
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        LoadBalancerVO loadBalancer = getManagementServer().findLoadBalancerById(loadBalancerId.longValue());

        if (loadBalancer == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find load balancer rule with id " + loadBalancerId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (loadBalancer.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName() +
                        " (id:" + loadBalancer.getId() + ")");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), loadBalancer.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid load balancer rule id (" + loadBalancer.getId() + ") given, unable to remove virtual machine instances.");
            }
        }

        long jobId = getManagementServer().removeFromLoadBalancerAsync(userId.longValue(), loadBalancerId.longValue(), instanceIdList);
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for RemoveFromLoadBalancerRule comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("RemoveFromLoadBalancerRule command has been accepted, job id: " + jobId);
        }
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
	    Boolean success = (Boolean)getResponseObject();
	    SuccessResponse response = new SuccessResponse();
	    response.setSuccess(success);
	    response.setResponseName(getName());
	    return response;
	}
}
File
RemoveFromLoadBalancerRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="removeSecurityGroup", manager=Manager.ManagementServer)
public class RemovePortForwardingServiceCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.network.SecurityGroupVO;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.UserVmVO;

public class RemovePortForwardingServiceCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	public static final Logger s_logger = Logger.getLogger(RemovePortForwardingServiceCmd.class.getName());

    private static final String s_name = "removeportforwardingserviceresponse";
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="removeSecurityGroup", manager=Manager.ManagementServer)
public class RemovePortForwardingServiceCmd extends BaseAsyncCmd {
	public static final Logger s_logger = Logger.getLogger(RemovePortForwardingServiceCmd.class.getName());

    private static final String s_name = "removeportforwardingserviceresponse";
File
RemovePortForwardingServiceCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
            }
        }
    public String getName() {
        return s_name;
    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
=======
    
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
    	Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Long securityGroupId = (Long)params.get(BaseCmd.Properties.ID.getName());
        String publicIp = (String)params.get(BaseCmd.Properties.PUBLIC_IP.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
        
        //verify input parameters
        SecurityGroupVO securityG = getManagementServer().findSecurityGroupById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
        
        UserVmVO vmInstance = getManagementServer().findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = getManagementServer().findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }
        
        long jobId = getManagementServer().removeSecurityGroupAsync(userId, securityGroupId, publicIp, vmId);
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for RemovePortForwardingServiceCmd comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("RemovePortForwardingServiceCmd command has been accepted, job id: " + jobId);
        }
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
        Boolean success = (Boolean)getResponseObject();
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(success);
        response.setResponseName(getName());
        return response;
	}
}
File
RemovePortForwardingServiceCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="resetVMPassword", manager=Manager.UserVmManager)
public class ResetVMPasswordCmd extends BaseAsyncCmd {
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.UserVmVO;

public class ResetVMPasswordCmd extends BaseCmd {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	public static final Logger s_logger = Logger.getLogger(ResetVMPasswordCmd.class.getName());

	private static final String s_name = "resetpasswordforvirtualmachineresponse";
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.SuccessResponse;

@Implementation(method="resetVMPassword", manager=Manager.UserVmManager)
public class ResetVMPasswordCmd extends BaseAsyncCmd {
	public static final Logger s_logger = Logger.getLogger(ResetVMPasswordCmd.class.getName());

	private static final String s_name = "resetpasswordforvirtualmachineresponse";
File
ResetVMPasswordCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Class signature
Import
Chunk
Conflicting content
	@Override
        response.setResponseName(getName());
        return response;
	}
<<<<<<< HEAD
=======
    public List> execute(Map params) {
		Long vmId = (Long)params.get(BaseCmd.Properties.ID.getName());
	    Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String password = null;

        //Verify input parameters
        UserVmVO vmInstance = getManagementServer().findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to reset password.");
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(1);
        }

    	VMTemplateVO template = getManagementServer().findTemplateById(vmInstance.getTemplateId());
    	if (template.getEnablePassword()) {
            password = getManagementServer().generateRandomPassword();
    	} else {
    		password = "saved_password";
    	}
    	
    	long jobId = getManagementServer().resetVMPasswordAsync(userId.longValue(), vmId, password);
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for ResetVMPassword comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("ResetVMPassword command has been accepted, job id: " + jobId);
        }
    	
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
        response.setResponseName(getName());
        return response;
	}
}
File
ResetVMPasswordCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.ApiConstants;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCmd;
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.ApiConstants;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
File
StartVMCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
            response.setHostId(vm.getHostId());
        }
        
<<<<<<< HEAD
        String templateName = "ISO Boot";
        boolean templatePasswordEnabled = false;
        String templateDisplayText = "ISO Boot";
        
        VMTemplateVO template = ApiDBUtils.findTemplateById(vm.getTemplateId());
        if (template != null) {
            templateName = template.getName();
            templatePasswordEnabled = template.getEnablePassword();
            templateDisplayText = template.getDisplayText();
             if (templateDisplayText == null) {
                templateDisplayText = templateName;
             }
        }

        response.setTemplateId(vm.getTemplateId());
        response.setTemplateName(templateName);
        response.setTemplateDisplayText(templateDisplayText);
        response.setPasswordEnabled(templatePasswordEnabled);
        if (templatePasswordEnabled) {
            response.setPassword(null); // FIXME:  Where should password come from?  In the old framework, password was always passed
                                        //         in to composeResultObject() as null, so that behavior is preserved...
        } else {
            response.setPassword("");
        }

        String isoName = null;
        if (vm.getIsoId() != null) {
            VMTemplateVO iso = ApiDBUtils.findTemplateById(vm.getIsoId().longValue());
            if (iso != null) {
                isoName = iso.getName();
            }
        }

        response.setIsoId(vm.getIsoId());
        response.setIsoName(isoName);

        ServiceOffering offering = ApiDBUtils.findServiceOfferingById(vm.getServiceOfferingId());
        response.setServiceOfferingId(vm.getServiceOfferingId());
        response.setServiceOfferingName(offering.getName());

        response.setCpuNumber(offering.getCpu());
        response.setCpuSpeed(offering.getSpeed());
        response.setMemory(offering.getRamSize());
        
        //Network groups
        response.setNetworkGroupList(ApiDBUtils.getNetworkGroupsNamesForVm(vm.getId()));

        response.setResponseName(getName());
        return response;
	}
=======
        //if account is removed, return error
        if(account!=null && account.getRemoved() != null)
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account " + account.getId()+" is removed");
        
        //Verify input parameters
        UserVmVO vmInstanceCheck = getManagementServer().findUserVMInstanceById(vmId.longValue());
        if (vmInstanceCheck == null) {
        	throw new ServerApiException (BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstanceCheck.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstanceCheck.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to start virtual machine.");
            }
        }

        if(!getManagementServer().isPoolUp(vmId)){
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR,"Storage pool for this vm is under maintenance");
        }
        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long jobId = getManagementServer().startVirtualMachineAsync(userId.longValue(), vmId.longValue(), null);
        if(jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for StartVM comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("StartVM command has been accepted, job id: " + jobId);
        }
        
        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 
        
        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
            response.setHostId(vm.getHostId());
        }
        
        String templateName = "ISO Boot";
        boolean templatePasswordEnabled = false;
        String templateDisplayText = "ISO Boot";
        
        VMTemplateVO template = ApiDBUtils.findTemplateById(vm.getTemplateId());
        if (template != null) {
            templateName = template.getName();
            templatePasswordEnabled = template.getEnablePassword();
            templateDisplayText = template.getDisplayText();
             if (templateDisplayText == null) {
                templateDisplayText = templateName;
             }
        }

        response.setTemplateId(vm.getTemplateId());
        response.setTemplateName(templateName);
        response.setTemplateDisplayText(templateDisplayText);
        response.setPasswordEnabled(templatePasswordEnabled);
        if (templatePasswordEnabled) {
            response.setPassword(null); // FIXME:  Where should password come from?  In the old framework, password was always passed
                                        //         in to composeResultObject() as null, so that behavior is preserved...
        } else {
            response.setPassword("");
        }

        String isoName = null;
        if (vm.getIsoId() != null) {
            VMTemplateVO iso = ApiDBUtils.findTemplateById(vm.getIsoId().longValue());
            if (iso != null) {
                isoName = iso.getName();
            }
        }

        response.setIsoId(vm.getIsoId());
        response.setIsoName(isoName);

        ServiceOffering offering = ApiDBUtils.findServiceOfferingById(vm.getServiceOfferingId());
        response.setServiceOfferingId(vm.getServiceOfferingId());
        response.setServiceOfferingName(offering.getName());

        response.setCpuNumber(offering.getCpu());
        response.setCpuSpeed(offering.getSpeed());
        response.setMemory(offering.getRamSize());
        
        //Network groups
        response.setNetworkGroupList(ApiDBUtils.getNetworkGroupsNamesForVm(vm.getId()));

        response.setResponseName(getName());
        return response;
	}
}
File
StartVMCmd.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Return statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.response.UserVmResponse;
import com.cloud.api.ApiDBUtils;
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
File
StopVMCmd.java
Developer's decision
Manual
Kind of conflict
Import
Chunk
Conflicting content
    public String getName() {
        UserVm vm = (UserVm)getResponseObject();
        return s_name;

    }
<<<<<<< HEAD

	@Override
	public ResponseObject getResponse() {
        UserVmResponse response = new UserVmResponse();
        response.setId(vm.getId());
        response.setName(vm.getName());
        response.setCreated(vm.getCreated());
        response.setZoneId(vm.getDataCenterId());
        response.setZoneName(ApiDBUtils.findZoneById(vm.getDataCenterId()).getName());
        response.setPrivateIp(vm.getPrivateIpAddress());
        response.setServiceOfferingId(vm.getServiceOfferingId());
        response.setHaEnable(vm.isHaEnabled());
        if (vm.getDisplayName() == null || vm.getDisplayName().length() == 0) {
            response.setDisplayName(vm.getName());
        } else {
            response.setDisplayName(vm.getDisplayName());
        }

        if (vm.getGroup() != null) {
            response.setGroup(vm.getGroup());
        }

        if (vm.getState() != null) {
            response.setState(vm.getState().toString());
        }

        Account acct = ApiDBUtils.findAccountById(vm.getAccountId());
        if (acct != null) {
            response.setAccountName(acct.getAccountName());
            response.setDomainId(acct.getDomainId());
            response.setDomainName(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
        }

        if (BaseCmd.isAdmin(acct.getType()) && (vm.getHostId() != null)) {
            response.setHostName(ApiDBUtils.findHostById(vm.getHostId()).getName());
            response.setHostId(vm.getHostId());
        }
        
        String templateName = "ISO Boot";
        boolean templatePasswordEnabled = false;
        String templateDisplayText = "ISO Boot";
        
        VMTemplateVO template = ApiDBUtils.findTemplateById(vm.getTemplateId());
        if (template != null) {
            templateName = template.getName();
            templatePasswordEnabled = template.getEnablePassword();
            templateDisplayText = template.getDisplayText();
             if (templateDisplayText == null) {
                templateDisplayText = templateName;
             }
        }

        response.setTemplateId(vm.getTemplateId());
        response.setTemplateName(templateName);
        response.setTemplateDisplayText(templateDisplayText);
        response.setPasswordEnabled(templatePasswordEnabled);
        if (templatePasswordEnabled) {
            response.setPassword(null); // FIXME:  Where should password come from?  In the old framework, password was always passed
                                        //         in to composeResultObject() as null, so that behavior is preserved...
        } else {
            response.setPassword("");
        }

        String isoName = null;
        if (vm.getIsoId() != null) {
            VMTemplateVO iso = ApiDBUtils.findTemplateById(vm.getIsoId().longValue());
            if (iso != null) {
                isoName = iso.getName();
            }
        }

        response.setIsoId(vm.getIsoId());
        response.setIsoName(isoName);

        ServiceOffering offering = ApiDBUtils.findServiceOfferingById(vm.getServiceOfferingId());
        response.setServiceOfferingId(vm.getServiceOfferingId());
        response.setServiceOfferingName(offering.getName());

        response.setCpuNumber(offering.getCpu());
        response.setCpuSpeed(offering.getSpeed());
        response.setMemory(offering.getRamSize());
        
        //Network groups
        response.setNetworkGroupList(ApiDBUtils.getNetworkGroupsNamesForVm(vm.getId()));

        response.setResponseName(getName());
        return response;
	}
=======

    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());

        // Verify input parameters
        UserVmVO vmInstance = getManagementServer().findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to sop virtual machine.");
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long jobId = getManagementServer().stopVirtualMachineAsync(userId.longValue(), vmId.longValue());
        if (jobId == 0) {
        	s_logger.warn("Unable to schedule async-job for StopVM comamnd");
        } else {
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("StopVM command has been accepted, job id: " + jobId);
        }

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); 

        return returnValues;
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public String getName() {
        return s_name;
    }

	@Override
	public ResponseObject getResponse() {
        UserVm vm = (UserVm)getResponseObject();

        UserVmResponse response = new UserVmResponse();
        response.setId(vm.getId());
        response.setName(vm.getName());
        response.setCreated(vm.getCreated());
        response.setZoneId(vm.getDataCenterId());
        response.setZoneName(ApiDBUtils.findZoneById(vm.getDataCenterId()).getName());
        response.setPrivateIp(vm.getPrivateIpAddress());
        response.setServiceOfferingId(vm.getServiceOfferingId());
        response.setHaEnable(vm.isHaEnabled());
        if (vm.getDisplayName() == null || vm.getDisplayName().length() == 0) {
            response.setDisplayName(vm.getName());
        } else {
            response.setDisplayName(vm.getDisplayName());
        }

        InstanceGroupVO group = ApiDBUtils.findInstanceGroupForVM(vm.getId());
        if (group != null) {
            response.setGroup(group.getName());
            response.setGroupId(group.getId());
        }

        if (vm.getState() != null) {
            response.setState(vm.getState().toString());
        }

        Account acct = ApiDBUtils.findAccountById(vm.getAccountId());
        if (acct != null) {
            response.setAccountName(acct.getAccountName());
            response.setDomainId(acct.getDomainId());
            response.setDomainName(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
        }

        if (BaseCmd.isAdmin(acct.getType()) && (vm.getHostId() != null)) {
            response.setHostName(ApiDBUtils.findHostById(vm.getHostId()).getName());
            response.setHostId(vm.getHostId());
        }
        
        String templateName = "ISO Boot";
        boolean templatePasswordEnabled = false;
        String templateDisplayText = "ISO Boot";
        
        VMTemplateVO template = ApiDBUtils.findTemplateById(vm.getTemplateId());
        if (template != null) {
            templateName = template.getName();
            templatePasswordEnabled = template.getEnablePassword();
            templateDisplayText = template.getDisplayText();
             if (templateDisplayText == null) {
                templateDisplayText = templateName;
             }
        }

        response.setTemplateId(vm.getTemplateId());
        response.setTemplateName(templateName);
        response.setTemplateDisplayText(templateDisplayText);
        response.setPasswordEnabled(templatePasswordEnabled);
        if (templatePasswordEnabled) {
            response.setPassword(null); // FIXME:  Where should password come from?  In the old framework, password was always passed
                                        //         in to composeResultObject() as null, so that behavior is preserved...
        } else {
            response.setPassword("");
        }

        String isoName = null;
        if (vm.getIsoId() != null) {
            VMTemplateVO iso = ApiDBUtils.findTemplateById(vm.getIsoId().longValue());
            if (iso != null) {
                isoName = iso.getName();
            }
        }

        response.setIsoId(vm.getIsoId());
        response.setIsoName(isoName);

        ServiceOffering offering = ApiDBUtils.findServiceOfferingById(vm.getServiceOfferingId());
        response.setServiceOfferingId(vm.getServiceOfferingId());
        response.setServiceOfferingName(offering.getName());

        response.setCpuNumber(offering.getCpu());
        response.setCpuSpeed(offering.getSpeed());
        response.setMemory(offering.getRamSize());
        
        //Network groups
        response.setNetworkGroupList(ApiDBUtils.getNetworkGroupsNamesForVm(vm.getId()));

        response.setResponseName(getName());
        return response;
	}
}
File
StopVMCmd.java
Developer's decision
Manual
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
UpdateAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }
    
    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        Boolean responseObject = (Boolean)getResponseObject();
      
        if (responseObject != null) {
        	response.setSuccess(responseObject);
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update account");
        }

        response.setResponseName(getName());
        return response;
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName());
        String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName());
        String newAccountName = (String)params.get(BaseCmd.Properties.NEW_NAME.getName());
        Account adminAccount = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());;
        Boolean updateAccountResult = false;
        Account account = null;

        // check if account exists in the system
        account = getManagementServer().findAccountByName(accountName, domainId);
    	if (account == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find account " + accountName + " in domain " + domainId);
    	}

    	if ((adminAccount != null) && !getManagementServer().isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid account " + accountName + " in domain " + domainId + " given, unable to update account.");
    	}

    	// don't allow modify system account
    	if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not modify system account");
    	}

        try {
        	getManagementServer().updateAccount(account.getId(), newAccountName);
        	account = getManagementServer().findAccountById(account.getId());
        	if (account.getAccountName().equals(newAccountName)) {
        		updateAccountResult = true;
        	}
        } catch (Exception ex) {
            s_logger.error("Exception updating account", ex);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update account " + accountName + " in domain " + domainId + ":  internal error.");
        }

        List> returnValues = new ArrayList>();
        if (updateAccountResult == true) {
        	returnValues.add(new Pair(BaseCmd.Properties.SUCCESS.getName(), new Boolean(true)));
        } else {
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update account " + accountName + " in domain " + domainId);
        }
        return returnValues;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }

    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        Boolean responseObject = (Boolean)getResponseObject();
      
        if (responseObject != null) {
        	response.setSuccess(responseObject);
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update account");
        }

        response.setResponseName(getName());
        return response;
    }
}
File
UpdateAccountCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Return statement
Try statement
Variable
Chunk
Conflicting content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
<<<<<<< HEAD
import com.cloud.api.response.SuccessResponse;

@Implementation(method="updateDomain", manager=Manager.ManagementServer)
=======
import com.cloud.domain.Domain;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
public class UpdateDomainCmd extends BaseCmd{
    public static final Logger s_logger = Logger.getLogger(UpdateDomainCmd.class.getName());
    private static final String s_name = "updatedomainresponse";
Solution content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.SuccessResponse;
@Implementation(method="updateDomain", manager=Manager.ManagementServer)
public class UpdateDomainCmd extends BaseCmd {
    public static final Logger s_logger = Logger.getLogger(UpdateDomainCmd.class.getName());
    private static final String s_name = "updatedomainresponse";
File
UpdateDomainCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Import
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }
    
    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        Boolean responseObject = (Boolean)getResponseObject();
      
        if (responseObject != null) {
        	response.setSuccess(responseObject);
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update domain");
        }
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long domainId = (Long)params.get(BaseCmd.Properties.ID.getName());
        String newName = (String)params.get(BaseCmd.Properties.NAME.getName());
        Boolean editDomainResult = false;

        //check if domain exists in the system
    	Domain domain = getManagementServer().findDomainIdById(domainId);
    	if (domain == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "ROOT domain can not be edited");
    	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        response.setResponseName(getName());
        return response;
Solution content
    @Override
    public String getName() {
        return s_name;
    }
    
    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        Boolean responseObject = (Boolean)getResponseObject();
      
        if (responseObject != null) {
        	response.setSuccess(responseObject);
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update domain");
        }

        response.setResponseName(getName());
        return response;
File
UpdateDomainCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Variable
Chunk
Conflicting content
        return s_name;
=======
    public String getName() {
    /////////////////////////////////////////////////////

    @Override
<<<<<<< HEAD
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String publicIp = (String)params.get(BaseCmd.Properties.PUBLIC_IP.getName());
        String publicPort = (String)params.get(BaseCmd.Properties.PUBLIC_PORT.getName());
        String privateIp = (String)params.get(BaseCmd.Properties.PRIVATE_IP.getName());
        String privatePort = (String)params.get(BaseCmd.Properties.PRIVATE_PORT.getName());
        String protocol = (String)params.get(BaseCmd.Properties.PROTOCOL.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.VIRTUAL_MACHINE_ID.getName());
        UserVmVO userVM = null;

        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = getManagementServer().findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = getManagementServer().searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = getManagementServer().findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!getManagementServer().isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }

        long jobId = getManagementServer().updatePortForwardingRuleAsync(userId, ipAddressVO.getAccountId().longValue(), publicIp, privateIp, publicPort, privatePort, protocol);

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId).toString()));
        return returnValues;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }

	@Override
Solution content
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

	@Override
File
UpdateIPForwardingRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Attribute
Cast expression
Comment
If statement
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
UpdateIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
public class UpdateIsoCmd extends UpdateTemplateOrIsoCmd {
    public static final Logger s_logger = Logger.getLogger(UpdateIsoCmd.class.getName());
    private static final String s_name = "updateisoresponse";
<<<<<<< HEAD

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////
    
    public Boolean isPasswordEnabled() {
        return null;
    }
    
    public String getFormat() {
        return null;
    }
    
    
    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }
    
    public ResponseObject getResponse() {
        TemplateResponse response = new TemplateResponse();
        VMTemplateVO responseObject = (VMTemplateVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setName(responseObject.getName());
            response.setDisplayText(responseObject.getDisplayText());
            response.setPublic(responseObject.isPublicTemplate());
            response.setCreated(responseObject.getCreated());
            response.setFormat(responseObject.getFormat());
            response.setOsTypeId(responseObject.getGuestOSId());
            response.setBootable(responseObject.isBootable());
            
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update iso");
        }

        response.setResponseName(getName());
        return response;
=======
    private static final List> s_properties = new ArrayList>();

    static {
        s_properties.add(new Pair(BaseCmd.Properties.ID, Boolean.TRUE));
        s_properties.add(new Pair(BaseCmd.Properties.NAME, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.OS_TYPE_ID, Boolean.FALSE));
        s_properties.add(new Pair(BaseCmd.Properties.BOOTABLE, Boolean.FALSE));
    }

    @Override
    public String getName() {
        return s_name;
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String displayText = (String)params.get(BaseCmd.Properties.DISPLAY_TEXT.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        Long isoId = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long guestOSId = (Long) params.get(BaseCmd.Properties.OS_TYPE_ID.getName());
        Boolean bootable = (Boolean) params.get(BaseCmd.Properties.BOOTABLE.getName());

        VMTemplateVO iso = getManagementServer().findTemplateById(isoId.longValue());
        if ((iso == null) || iso.getFormat() != Storage.ImageFormat.ISO) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ISO with id " + isoId);
        }

        // do a permission check
        if (account != null) {
            Long isoOwner = iso.getAccountId();
            if (!isAdmin(account.getType())) {
                if ((isoOwner == null) || (account.getId() != isoOwner.longValue())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to modify ISO with id " + isoId);
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long isoOwnerDomainId = getManagementServer().findDomainIdByAccountId(isoOwner);
                if (!getManagementServer().isChildDomain(account.getDomainId(), isoOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to modify ISO with id " + isoId);
                }
            }
        }
        
        // do the update
        boolean success = false;
        try {
        	success = getManagementServer().updateTemplate(isoId, name, displayText, null, guestOSId, null, bootable);
        } catch (Exception ex) {
        	 s_logger.error("Exception editing ISO", ex);
             throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update ISO " + isoId + ": " + ex.getMessage());
        }

        VMTemplateVO updatedIso = getManagementServer().findTemplateById(isoId);
        if (success) {
            List> isoData = new ArrayList>();
            isoData.add(new Pair(BaseCmd.Properties.ID.getName(), updatedIso.getId().toString()));
            isoData.add(new Pair(BaseCmd.Properties.NAME.getName(), updatedIso.getName()));
            isoData.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), updatedIso.getDisplayText()));
            isoData.add(new Pair(BaseCmd.Properties.IS_PUBLIC.getName(), Boolean.valueOf(updatedIso.isPublicTemplate()).toString()));
            isoData.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(updatedIso.getCreated())));
            isoData.add(new Pair(BaseCmd.Properties.FORMAT.getName(), updatedIso.getFormat()));
            isoData.add(new Pair(BaseCmd.Properties.OS_TYPE_ID.getName(), updatedIso.getGuestOSId()));
            isoData.add(new Pair(BaseCmd.Properties.BOOTABLE.getName(), updatedIso.isBootable()));
            // add account ID and name
            Account owner = getManagementServer().findAccountById(updatedIso.getAccountId());
            if (owner != null) {
                isoData.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), owner.getAccountName()));
                isoData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), owner.getDomainId()));
                isoData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(owner.getDomainId()).getName()));
            }
            return isoData;
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "internal error updating ISO");
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }
}
Solution content
    }
    
        return null;
public class UpdateIsoCmd extends UpdateTemplateOrIsoCmd {
    public static final Logger s_logger = Logger.getLogger(UpdateIsoCmd.class.getName());
    private static final String s_name = "updateisoresponse";

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////
    
    public Boolean isPasswordEnabled() {
    public String getFormat() {
        return null;
    }
    
    
    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }
    
    public ResponseObject getResponse() {
        TemplateResponse response = new TemplateResponse();
        VMTemplateVO responseObject = (VMTemplateVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setName(responseObject.getName());
            response.setDisplayText(responseObject.getDisplayText());
            response.setPublic(responseObject.isPublicTemplate());
            response.setCreated(responseObject.getCreated());
            response.setFormat(responseObject.getFormat());
            response.setOsTypeId(responseObject.getGuestOSId());
            response.setBootable(responseObject.isBootable());
            
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update iso");
        }

        response.setResponseName(getName());
        return response;
    }
}
File
UpdateIsoCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Attribute
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Return statement
Static initializer
Try statement
Variable
Chunk
Conflicting content
        }


    /////////////////////////////////////////////////////

    @Override
<<<<<<< HEAD
    public String getName() {
        return s_name;
=======
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        String description = (String)params.get(BaseCmd.Properties.DESCRIPTION.getName());
        String privatePort = (String)params.get(BaseCmd.Properties.PRIVATE_PORT.getName());
        String algorithm = (String)params.get(BaseCmd.Properties.ALGORITHM.getName());
        Long loadBalancerId = (Long)params.get(BaseCmd.Properties.ID.getName());

        if (userId == null) {
            userId = Long.valueOf(1);
        LoadBalancerVO lb = getManagementServer().findLoadBalancerById(loadBalancerId);
        if (lb == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find load balancer rule " + loadBalancerId + " for update.");
        }
        // Verify input parameters
        Account lbOwner = getManagementServer().findAccountById(lb.getAccountId());
        if (lbOwner == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update load balancer rule, cannot find owning account");
        }

        Long accountId = lbOwner.getId();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != accountId.longValue()) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update load balancer rule, permission denied");
                }
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), lbOwner.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update load balancer rule, permission denied.");
            }
        }

        long jobId = getManagementServer().updateLoadBalancerRuleAsync(userId, lb.getAccountId(), lb.getId().longValue(), name, description, privatePort, algorithm);

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId).toString()));
        return returnValues;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }

	@Override
Solution content
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

	@Override
File
UpdateLoadBalancerRuleCmd.java
Developer's decision
Version 1
Kind of conflict
Attribute
Cast expression
Comment
If statement
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
<<<<<<< HEAD
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.offering.ServiceOffering.GuestIpType;
=======
import com.cloud.api.ServerApiException;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.service.ServiceOfferingVO;

@Implementation(method="updateServiceOffering", manager=Manager.ConfigManager)
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.service.ServiceOfferingVO;

@Implementation(method="updateServiceOffering", manager=Manager.ConfigManager)
File
UpdateServiceOfferingCmd.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }

    @Override
    public ResponseObject getResponse() {
        ServiceOfferingVO offering = (ServiceOfferingVO) getResponseObject();

        ServiceOfferingResponse response = new ServiceOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setCpuNumber(offering.getCpu());
        response.setCpuSpeed(offering.getSpeed());
        response.setCreated(offering.getCreated());
        String storageType = offering.getUseLocalStorage() ? "local" : "shared";
        response.setStorageType(storageType);
        response.setOfferHa(offering.getOfferHA());
        response.setUseVirtualNetwork(offering.getGuestIpType().equals(GuestIpType.Virtualized));
        response.setTags(offering.getTags());

        response.setResponseName(getName());
        return response;
    }
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long offeringId = (Long)params.get(BaseCmd.Properties.ID.getName());
        String name = (String)params.get(BaseCmd.Properties.NAME.getName());
        String displayText = (String)params.get(BaseCmd.Properties.DISPLAY_TEXT.getName());
        Boolean offerHA = (Boolean) params.get(BaseCmd.Properties.OFFER_HA.getName());
        Boolean useVirtualNetwork = (Boolean) params.get(BaseCmd.Properties.USE_VIRTUAL_NETWORK.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
        String tags = (String)params.get(BaseCmd.Properties.TAGS.getName());
        
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // Verify input parameters
        ServiceOfferingVO offering = getManagementServer().findServiceOfferingById(offeringId);
    	if (offering == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find service offering " + offeringId);
    	}

    	
        try {     
        	offering = getManagementServer().updateServiceOffering(userId, offeringId, name, displayText, offerHA, useVirtualNetwork, tags);
        } catch (Exception ex) {
            s_logger.error("Exception updating service offering", ex);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update service offering " + offeringId + ":  internal error.");
        }

        List> returnValues = new ArrayList>();
        if (offering != null) {
        	returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), offeringId.toString()));
            returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), offering.getName()));
            returnValues.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), offering.getDisplayText()));
            returnValues.add(new Pair(BaseCmd.Properties.CPU_NUMBER.getName(), Integer.valueOf(offering.getCpu()).toString()));
            returnValues.add(new Pair(BaseCmd.Properties.CPU_SPEED.getName(), Integer.valueOf(offering.getSpeed()).toString()));
            returnValues.add(new Pair(BaseCmd.Properties.MEMORY.getName(), Integer.valueOf(offering.getRamSize()).toString()));
            returnValues.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(offering.getCreated())));
            String storageType = offering.getUseLocalStorage() ? "local" : "shared";
            returnValues.add(new Pair(BaseCmd.Properties.STORAGE_TYPE.getName(), storageType));
            returnValues.add(new Pair(BaseCmd.Properties.OFFER_HA.getName(), offering.getOfferHA()));
            returnValues.add(new Pair(BaseCmd.Properties.USE_VIRTUAL_NETWORK.getName(), (offering.getGuestIpType().equals(NetworkOffering.GuestIpType.Virtualized))));
            returnValues.add(new Pair(BaseCmd.Properties.TAGS.getName(), offering.getTags()));
        } else {
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update service offering " + offeringId);
        }
        return returnValues;
    }  
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }

    @Override
    public ResponseObject getResponse() {
        ServiceOfferingVO offering = (ServiceOfferingVO) getResponseObject();

        ServiceOfferingResponse response = new ServiceOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setCpuNumber(offering.getCpu());
        response.setCpuSpeed(offering.getSpeed());
        response.setCreated(offering.getCreated());
        String storageType = offering.getUseLocalStorage() ? "local" : "shared";
        response.setStorageType(storageType);
        response.setOfferHa(offering.getOfferHA());
        response.setUseVirtualNetwork(offering.getGuestIpType().equals(GuestIpType.Virtualized));
        response.setTags(offering.getTags());

        response.setResponseName(getName());
        return response;
    }
}
File
UpdateServiceOfferingCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import com.cloud.api.Implementation;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
<<<<<<< HEAD
import com.cloud.api.response.TemplateResponse;
=======
import com.cloud.storage.GuestOS;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.VMTemplateVO;

@Implementation(method="updateTemplate", manager=Manager.ManagementServer)
Solution content
import com.cloud.api.Implementation;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.TemplateResponse;
import com.cloud.storage.VMTemplateVO;

@Implementation(method="updateTemplate", manager=Manager.ManagementServer)
File
UpdateTemplateCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
            response.setName(responseObject.getName());
	public static final Logger s_logger = Logger.getLogger(UpdateTemplateCmd.class.getName());
    private static final String s_name = "updatetemplateresponse";

<<<<<<< HEAD
    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////
    
    public Boolean isBootable() {
        return null;
    }

    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

    public ResponseObject getResponse() {
        TemplateResponse response = new TemplateResponse();
        VMTemplateVO responseObject = (VMTemplateVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setDisplayText(responseObject.getDisplayText());
            response.setPublic(responseObject.isPublicTemplate());
            response.setCreated(responseObject.getCreated());
            response.setFormat(responseObject.getFormat());
            response.setOsTypeId(responseObject.getGuestOSId());
            response.setPasswordEnabled(responseObject.getEnablePassword());
            response.setCrossZones(responseObject.isCrossZones());
=======
        
        boolean success = false;
        try {
        	success = getManagementServer().updateTemplate(templateId, name, displayText, format, guestOSId, passwordEnabled, null);
        } catch (Exception ex) {
        	 s_logger.error("Exception editing template", ex);
             throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update template " + templateId + ": " + ex.getMessage());
        }

        VMTemplateVO updatedTemplate = getManagementServer().findTemplateById(templateId);
        if (success) {
            List> templateData = new ArrayList>();
            templateData.add(new Pair(BaseCmd.Properties.ID.getName(), updatedTemplate.getId().toString()));
            templateData.add(new Pair(BaseCmd.Properties.NAME.getName(), updatedTemplate.getName()));
            templateData.add(new Pair(BaseCmd.Properties.DISPLAY_TEXT.getName(), updatedTemplate.getDisplayText()));
            templateData.add(new Pair(BaseCmd.Properties.IS_PUBLIC.getName(), Boolean.valueOf(updatedTemplate.isPublicTemplate()).toString()));
            templateData.add(new Pair(BaseCmd.Properties.CREATED.getName(), getDateString(updatedTemplate.getCreated())));
            templateData.add(new Pair(BaseCmd.Properties.FORMAT.getName(), updatedTemplate.getFormat()));
            GuestOS os = getManagementServer().findGuestOSById(updatedTemplate.getGuestOSId());
            if (os != null) {
            	templateData.add(new Pair(BaseCmd.Properties.OS_TYPE_ID.getName(), os.getId()));
                templateData.add(new Pair(BaseCmd.Properties.OS_TYPE_NAME.getName(), os.getDisplayName()));
            } else {
            	templateData.add(new Pair(BaseCmd.Properties.OS_TYPE_ID.getName(), -1));
                templateData.add(new Pair(BaseCmd.Properties.OS_TYPE_NAME.getName(), ""));
            }            
            templateData.add(new Pair(BaseCmd.Properties.PASSWORD_ENABLED.getName(), updatedTemplate.getEnablePassword()));
            templateData.add(new Pair(BaseCmd.Properties.CROSS_ZONES.getName(), Boolean.valueOf(updatedTemplate.isCrossZones()).toString()));            
            templateData.add(new Pair(BaseCmd.Properties.IS_FEATURED.getName(), Boolean.valueOf(updatedTemplate.isFeatured()).toString()));
            
            // add account ID and name
            Account owner = getManagementServer().findAccountById(updatedTemplate.getAccountId());
            if (owner != null) {
                templateData.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), owner.getAccountName()));
                templateData.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), owner.getDomainId()));
                templateData.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(owner.getDomainId()).getName()));
            } 
            return templateData;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update template");
        }
Solution content
        return null;
    }

	public static final Logger s_logger = Logger.getLogger(UpdateTemplateCmd.class.getName());
    private static final String s_name = "updatetemplateresponse";

    /////////////////////////////////////////////////////
    /////////////////// Accessors ///////////////////////
    /////////////////////////////////////////////////////
    
    public Boolean isBootable() {
    /////////////////////////////////////////////////////
    /////////////// API Implementation///////////////////
    /////////////////////////////////////////////////////

    @Override
    public String getName() {
        return s_name;
    }

    public ResponseObject getResponse() {
        TemplateResponse response = new TemplateResponse();
        VMTemplateVO responseObject = (VMTemplateVO)getResponseObject();
        if (responseObject != null) {
            response.setId(responseObject.getId());
            response.setName(responseObject.getName());
            response.setDisplayText(responseObject.getDisplayText());
            response.setPublic(responseObject.isPublicTemplate());
            response.setCreated(responseObject.getCreated());
            response.setFormat(responseObject.getFormat());
            response.setOsTypeId(responseObject.getGuestOSId());
            response.setPasswordEnabled(responseObject.getEnablePassword());
            response.setCrossZones(responseObject.isCrossZones());
        } else {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update template");
        }
File
UpdateTemplateCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Return statement
Try statement
Variable
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
File
UpdateVMCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    @Override
    public String getName() {
        return s_name;
<<<<<<< HEAD
    }
    
    public static String getResultObjectName() {
    	return "virtualmachine";
    }    

    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(Boolean.TRUE);
        response.setResponseName(getName());
        return response;
    }
=======
    }
    @Override
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());
    	Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long vmId = (Long)params.get(BaseCmd.Properties.ID.getName());
        String group = (String)params.get(BaseCmd.Properties.GROUP.getName());
        String displayName = (String)params.get(BaseCmd.Properties.DISPLAY_NAME.getName());
        Boolean enable = (Boolean)params.get(BaseCmd.Properties.HA_ENABLE.getName());
        UserVmVO vmInstance = null;

        // default userId to SYSTEM user
        if (userId == null) {
            userId = Long.valueOf(1);
        }
        
        //don't accept empty parameter for the group
        if (group != null && group.isEmpty())
        	group = null;

        // Verify input parameters
        try {
        	vmInstance = getManagementServer().findUserVMInstanceById(vmId.longValue());
        } catch (Exception ex1) {
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find virtual machine by id");
        }

        if (vmInstance == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find virtual machine with id " + vmId);
        }

        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to update virtual machine.");
            }
        }

    	if (displayName == null) {
    		displayName = vmInstance.getDisplayName();
    	}
    	
    	if (enable == null) {
    		enable = vmInstance.isHaEnabled();
    	}

    	long accountId = vmInstance.getAccountId();

        try {     
        	getManagementServer().updateVirtualMachine(vmId, displayName, group, enable, userId, accountId);
        } catch (Exception ex) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update virtual machine" + vmId + ":  internal error.");
        }

        List> returnValues = new ArrayList>();
        returnValues.add(new Pair(BaseCmd.Properties.SUCCESS.getName(), Boolean.TRUE));
        return returnValues;
    }  
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    @Override
    public String getName() {
        return s_name;
    }
    
    public static String getResultObjectName() {
    	return "virtualmachine";
    }    

    @Override
    public ResponseObject getResponse() {
        SuccessResponse response = new SuccessResponse();
        response.setSuccess(Boolean.TRUE);
        response.setResponseName(getName());
        return response;
    }
}
File
UpdateVMCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
package com.cloud.api.commands;

<<<<<<< HEAD
import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
=======
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
Solution content
package com.cloud.api.commands;

import org.apache.log4j.Logger;

import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseCmd.Manager;
import com.cloud.api.Implementation;
File
UpgradeVMCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
=======
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
<<<<<<< HEAD
import com.cloud.api.response.UpgradeVmResponse;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.exception.InvalidParameterValueException;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.user.Account;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VmStats;
Solution content
import com.cloud.api.Parameter;
import com.cloud.api.ResponseObject;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.UpgradeVmResponse;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VmStats;
File
UpgradeVMCmd.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
    public static String getResultObjectName() {
    	return "virtualmachine";
    }    
<<<<<<< HEAD
    
    @Override
    public ResponseObject getResponse() {
        UserVmVO userVm = (UserVmVO)getResponseObject();

        UpgradeVmResponse response = new UpgradeVmResponse();
        if (userVm != null) {
    		Account acct = ApiDBUtils.findAccountById(userVm.getAccountId());
    		response.setAccount(acct.getAccountName());

    		ServiceOffering offering = ApiDBUtils.findServiceOfferingById(userVm.getServiceOfferingId());
    		response.setCpuSpeed(offering.getSpeed());
    		response.setMemory(offering.getRamSize());
    		if (((ServiceOfferingVO)offering).getDisplayText() != null) {
    		    response.setServiceOfferingName(((ServiceOfferingVO)offering).getDisplayText());
    		} else {
    		    response.setServiceOfferingName(offering.getName());
    		}

    		response.setServiceOfferingId(userVm.getServiceOfferingId());
    		
    		VmStats vmStats = ApiDBUtils.getVmStatistics(userVm.getId());
    		if (vmStats != null) {
    		    response.setCpuUsed((long) vmStats.getCPUUtilization());
    		    response.setNetworkKbsRead((long) vmStats.getNetworkReadKBs());
    		    response.setNetworkKbsWrite((long) vmStats.getNetworkWriteKBs());
    		}
    		
    		response.setCreated(userVm.getCreated());
    		response.setDisplayName(userVm.getDisplayName());
    		response.setDomain(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
    		response.setDomainId(acct.getDomainId());
    		response.setHaEnable(userVm.isHaEnabled());

    		if (userVm.getHostId() != null) {
    		    response.setHostId(userVm.getHostId());
    			response.setHostName(ApiDBUtils.findHostById(userVm.getHostId()).getName());
    		}
    		response.setIpAddress(userVm.getPrivateIpAddress());
    		response.setName(userVm.getName());
    		response.setState(userVm.getState().toString());
    		response.setZoneId(userVm.getDataCenterId());
    		response.setZoneName(ApiDBUtils.findZoneById(userVm.getDataCenterId()).getName());
    		
    		VMTemplateVO template = ApiDBUtils.findTemplateById(userVm.getTemplateId());
    		response.setPasswordEnabled(template.getEnablePassword());
    		response.setTemplateDisplayText(template.getDisplayText());
    		response.setTemplateId(template.getId());
    		response.setTemplateName(template.getName());
        } else {
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update zone; internal error.");
=======
    
    public List> getProperties() {
        return s_properties;
    }

    @Override
    public List> execute(Map params) {
        Long virtualMachineId = (Long)params.get(BaseCmd.Properties.ID.getName());
        Long serviceOfferingId = (Long)params.get(BaseCmd.Properties.SERVICE_OFFERING_ID.getName());
        Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName());
        Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName());

        // Verify input parameters
        UserVmVO vmInstance = getManagementServer().findUserVMInstanceById(virtualMachineId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + virtualMachineId);
        }       

        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + virtualMachineId + " for this account");
            } else if (!getManagementServer().isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + virtualMachineId + ") given, unable to upgrade virtual machine.");
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }

        response.setResponseName(getName());
Solution content
    public static String getResultObjectName() {
    	return "virtualmachine";
    }
    
    @Override
    public ResponseObject getResponse() {
        UserVmVO userVm = (UserVmVO)getResponseObject();

        UpgradeVmResponse response = new UpgradeVmResponse();
        if (userVm != null) {
    		Account acct = ApiDBUtils.findAccountById(userVm.getAccountId());
    		response.setAccount(acct.getAccountName());

    		ServiceOffering offering = ApiDBUtils.findServiceOfferingById(userVm.getServiceOfferingId());
    		response.setCpuSpeed(offering.getSpeed());
    		response.setMemory(offering.getRamSize());
    		if (((ServiceOfferingVO)offering).getDisplayText() != null) {
    		    response.setServiceOfferingName(((ServiceOfferingVO)offering).getDisplayText());
    		} else {
    		    response.setServiceOfferingName(offering.getName());
    		}

    		response.setServiceOfferingId(userVm.getServiceOfferingId());
    		
    		VmStats vmStats = ApiDBUtils.getVmStatistics(userVm.getId());
    		if (vmStats != null) {
    		    response.setCpuUsed((long) vmStats.getCPUUtilization());
    		    response.setNetworkKbsRead((long) vmStats.getNetworkReadKBs());
    		    response.setNetworkKbsWrite((long) vmStats.getNetworkWriteKBs());
    		}
    		
    		response.setCreated(userVm.getCreated());
    		response.setDisplayName(userVm.getDisplayName());
    		response.setDomain(ApiDBUtils.findDomainById(acct.getDomainId()).getName());
    		response.setDomainId(acct.getDomainId());
    		response.setHaEnable(userVm.isHaEnabled());

    		if (userVm.getHostId() != null) {
    		    response.setHostId(userVm.getHostId());
    			response.setHostName(ApiDBUtils.findHostById(userVm.getHostId()).getName());
    		}
    		response.setIpAddress(userVm.getPrivateIpAddress());
    		response.setName(userVm.getName());
    		response.setState(userVm.getState().toString());
    		response.setZoneId(userVm.getDataCenterId());
    		response.setZoneName(ApiDBUtils.findZoneById(userVm.getDataCenterId()).getName());
    		
    		VMTemplateVO template = ApiDBUtils.findTemplateById(userVm.getTemplateId());
    		response.setPasswordEnabled(template.getEnablePassword());
    		response.setTemplateDisplayText(template.getDisplayText());
    		response.setTemplateId(template.getId());
    		response.setTemplateName(template.getName());
        } else {
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update zone; internal error.");
        }

        response.setResponseName(getName());
File
UpgradeVMCmd.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Throw statement
Variable
Chunk
Conflicting content
//				VMTemplateHostVO templateHostRef = managementServer.findTemplateHostRef(param.getTemplateId(), destZone.getId());
				long guestOsId = template.getGuestOSId();
		        Account owner = managementServer.findAccountById(template.getAccountId());
<<<<<<< HEAD
//		        DomainVO domain = managementServer.findDomainIdById(owner.getDomainId());
//		        String guestOSName = managementServer.findGuestOSById(guestOsId).getName();
//				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, composeResultObject(template, templateHostRef, destZone,guestOSName, owner, domain));
=======
		        Domain domain = managementServer.findDomainIdById(owner.getDomainId());
		        String guestOSName = managementServer.findGuestOSById(guestOsId).getName();
				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, composeResultObject(template, templateHostRef, destZone,guestOSName, owner, domain));
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
			} else {
				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, BaseCmd.INTERNAL_ERROR, "Failed to copy template.");
			}
Solution content
//				VMTemplateHostVO templateHostRef = managementServer.findTemplateHostRef(param.getTemplateId(), destZone.getId());
				long guestOsId = template.getGuestOSId();
		        Account owner = managementServer.findAccountById(template.getAccountId());
//		        DomainVO domain = managementServer.findDomainIdById(owner.getDomainId());
//		        String guestOSName = managementServer.findGuestOSById(guestOsId).getName();
//				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, composeResultObject(template, templateHostRef, destZone,guestOSName, owner, domain));
			} else {
				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, BaseCmd.INTERNAL_ERROR, "Failed to copy template.");
			}
File
CopyTemplateExecutor.java
Developer's decision
Version 1
Kind of conflict
Comment
Method invocation
Variable
Chunk
Conflicting content
<<<<<<< HEAD
//TODO -- This will be removed
///**
// *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
// * 
// * This software is licensed under the GNU General Public License v3 or later.
// * 
// * It is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or any later version.
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU General Public License for more details.
// * 
// * You should have received a copy of the GNU General Public License
// * along with this program.  If not, see .
// * 
// */
//
//package com.cloud.async.executor;
//
//import org.apache.log4j.Logger;
//
//import com.cloud.api.BaseCmd;
//import com.cloud.async.AsyncJobManager;
//import com.cloud.async.AsyncJobResult;
//import com.cloud.async.AsyncJobVO;
//import com.cloud.async.BaseAsyncJobExecutor;
//import com.cloud.serializer.GsonHelper;
//import com.cloud.server.ManagementServer;
//import com.cloud.service.ServiceOfferingVO;
//import com.cloud.storage.VMTemplateVO;
//import com.cloud.user.Account;
//import com.cloud.uservm.UserVm;
//import com.cloud.vm.UserVmVO;
//import com.cloud.vm.VMInstanceVO;
//import com.cloud.vm.VmStats;
//import com.google.gson.Gson;
//
//public class UpgradeVMExecutor extends BaseAsyncJobExecutor {
//    public static final Logger s_logger = Logger.getLogger(UpgradeVMExecutor.class.getName());
//	
//	public boolean execute() {
//		AsyncJobManager asyncMgr = getAsyncJobMgr();
//    	AsyncJobVO job = getJob();
//    	Gson gson = GsonHelper.getBuilder().create();
//		
//		if(getSyncSource() == null) {
//	    	VMOperationParam param = gson.fromJson(job.getCmdInfo(), VMOperationParam.class);
//	    	asyncMgr.syncAsyncJobExecution(job.getId(), "UserVM", param.getVmId());
//	    	
//	    	// always true if it does not have sync-source
//	    	return true;
//		} else {
//			ManagementServer managementServer = asyncMgr.getExecutorContext().getManagementServer();
//			UpgradeVMParam param = gson.fromJson(job.getCmdInfo(), UpgradeVMParam.class);
//			
//			try {
//				asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", param.getVmId());
//			    boolean success = managementServer.upgradeVirtualMachine(param.getUserId(), 
import org.apache.log4j.Logger;
package com.cloud.async.executor;
//			    	param.getVmId(), param.getServiceOfferingId(), param.getEventId());
//	
//		        if (success) {
//		        	//get the upgraded vm to compose the result object
//		        	UserVmVO userVm = managementServer.findUserVMInstanceById(param.getVmId());
//					asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, 
//							composeResultObject(userVm, managementServer));
//					
//		        } else {
//					asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, 
//						BaseCmd.VM_CHANGE_SERVICE_ERROR, 
//						composeResultObject(null, managementServer));
//		        }
//			} catch(Exception e) {
//				s_logger.warn("Unable to upgrade VM " + param.getVmId() + ":" + e.getMessage(), e);
//				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, 
//					BaseCmd.INTERNAL_ERROR, 
//					e.getMessage());
//			}
//			return true;
//		}
//	}
//	
//	private VmResultObject composeResultObject(UserVmVO vm, ManagementServer ms)
//	{
//		if(vm == null)
//			return null;
//		
//		VmResultObject resultObj = new VmResultObject();
//		Account acct = ms.findAccountById(Long.valueOf(vm.getAccountId()));
//		resultObj.setAccount(acct.getAccountName());
//		
//		ServiceOfferingVO offering = ms.findServiceOfferingById(vm.getServiceOfferingId());
//		resultObj.setCpuSpeed(offering.getSpeed());
//		resultObj.setMemory(offering.getRamSize());
//		if(offering.getDisplayText()!=null)
//			resultObj.setServiceOfferingName(offering.getDisplayText());
//		else
//			resultObj.setServiceOfferingName(offering.getName());
//		resultObj.setServiceOfferingId(vm.getServiceOfferingId());
//		
//		VmStats vmStats = ms.getVmStatistics(vm.getId());
//		if(vmStats != null)
//		{
//			resultObj.setCpuUsed((long) vmStats.getCPUUtilization());
//			resultObj.setNetworkKbsRead((long) vmStats.getNetworkReadKBs());
//			resultObj.setNetworkKbsWrite((long) vmStats.getNetworkWriteKBs());
//		}
//		
//		resultObj.setCreated(vm.getCreated());
//		resultObj.setDisplayName(vm.getDisplayName());
//		resultObj.setDomain(ms.findDomainIdById(acct.getDomainId()).getName());
//		resultObj.setDomainId(acct.getDomainId());
//		resultObj.setHaEnable(vm.isHaEnabled());
//		if(vm.getHostId() != null)
//		{
//			resultObj.setHostId(vm.getHostId());
//			resultObj.setHostName(ms.getHostBy(vm.getHostId()).getName());
//		}
//		resultObj.setIpAddress(vm.getPrivateIpAddress());
//		resultObj.setName(vm.getName());
//		resultObj.setState(vm.getState().toString());
//		resultObj.setZoneId(vm.getDataCenterId());
//		resultObj.setZoneName(ms.findDataCenterById(vm.getDataCenterId()).getName());
//		
//		VMTemplateVO template = ms.findTemplateById(vm.getTemplateId());
//		resultObj.setPasswordEnabled(template.getEnablePassword());
//		resultObj.setTemplateDisplayText(template.getDisplayText());
//		resultObj.setTemplateId(template.getId());
//		resultObj.setTemplateName(template.getName());
//		
//		return resultObj;
//	}
//}
=======
/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */


import com.cloud.api.BaseCmd;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.serializer.GsonHelper;
import com.cloud.server.ManagementServer;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VmStats;
import com.google.gson.Gson;

public class UpgradeVMExecutor extends BaseAsyncJobExecutor {
    public static final Logger s_logger = Logger.getLogger(UpgradeVMExecutor.class.getName());
	
	public boolean execute() {
		AsyncJobManager asyncMgr = getAsyncJobMgr();
    	AsyncJobVO job = getJob();
    	Gson gson = GsonHelper.getBuilder().create();
		
		if(getSyncSource() == null) {
	    	VMOperationParam param = gson.fromJson(job.getCmdInfo(), VMOperationParam.class);
	    	asyncMgr.syncAsyncJobExecution(job.getId(), "UserVM", param.getVmId());
	    	
	    	// always true if it does not have sync-source
	    	return true;
		} else {
			ManagementServer managementServer = asyncMgr.getExecutorContext().getManagementServer();
			UpgradeVMParam param = gson.fromJson(job.getCmdInfo(), UpgradeVMParam.class);
			
			try {
				asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", param.getVmId());
			    boolean success = managementServer.upgradeVirtualMachine(param.getUserId(), 
			    	param.getVmId(), param.getServiceOfferingId(), param.getEventId());
	
		        if (success) {
		        	//get the upgraded vm to compose the result object
		        	UserVmVO userVm = managementServer.findUserVMInstanceById(param.getVmId());
					asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, 
							composeResultObject(userVm, managementServer));
					
		        } else {
					asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, 
						BaseCmd.VM_CHANGE_SERVICE_ERROR, 
						composeResultObject(null, managementServer));
		        }
			} catch(Exception e) {
				s_logger.warn("Unable to upgrade VM " + param.getVmId() + ":" + e.getMessage(), e);
				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, 
					BaseCmd.INTERNAL_ERROR, 
					e.getMessage());
			}
			return true;
		}
	}
	
	private VmResultObject composeResultObject(UserVmVO vm, ManagementServer ms)
	{
		if(vm == null)
			return null;
		
		VmResultObject resultObj = new VmResultObject();
		Account acct = ms.findAccountById(Long.valueOf(vm.getAccountId()));
		resultObj.setAccount(acct.getAccountName());
		
		ServiceOfferingVO offering = ms.findServiceOfferingById(vm.getServiceOfferingId());
		resultObj.setCpuSpeed(offering.getSpeed());
		resultObj.setMemory(offering.getRamSize());
		if(offering.getName()!=null)
			resultObj.setServiceOfferingName(offering.getName());
		else
			resultObj.setServiceOfferingName(offering.getDisplayText());
		resultObj.setServiceOfferingId(vm.getServiceOfferingId());
		
		VmStats vmStats = ms.getVmStatistics(vm.getId());
		if(vmStats != null)
		{
			resultObj.setCpuUsed((long) vmStats.getCPUUtilization());
			resultObj.setNetworkKbsRead((long) vmStats.getNetworkReadKBs());
			resultObj.setNetworkKbsWrite((long) vmStats.getNetworkWriteKBs());
		}
		
		resultObj.setCreated(vm.getCreated());
		resultObj.setDisplayName(vm.getDisplayName());
		resultObj.setDomain(ms.findDomainIdById(acct.getDomainId()).getName());
		resultObj.setDomainId(acct.getDomainId());
		resultObj.setHaEnable(vm.isHaEnabled());
		if(vm.getHostId() != null)
		{
			resultObj.setHostId(vm.getHostId());
			resultObj.setHostName(ms.getHostBy(vm.getHostId()).getName());
		}
		resultObj.setIpAddress(vm.getPrivateIpAddress());
		resultObj.setName(vm.getName());
		resultObj.setState(vm.getState().toString());
		resultObj.setZoneId(vm.getDataCenterId());
		resultObj.setZoneName(ms.findDataCenterById(vm.getDataCenterId()).getName());
		
		VMTemplateVO template = ms.findTemplateById(vm.getTemplateId());
		resultObj.setPasswordEnabled(template.getEnablePassword());
		resultObj.setTemplateDisplayText(template.getDisplayText());
		resultObj.setTemplateId(template.getId());
		resultObj.setTemplateName(template.getName());
		resultObj.setId(vm.getId());
		
		return resultObj;
	}
}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
Solution content
//TODO -- This will be removed
///**
// *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
// * 
// * This software is licensed under the GNU General Public License v3 or later.
// * 
//		else
// * It is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or any later version.
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU General Public License for more details.
// * 
// * You should have received a copy of the GNU General Public License
// * along with this program.  If not, see .
// * 
// */
//
//package com.cloud.async.executor;
//
//import org.apache.log4j.Logger;
//
//import com.cloud.api.BaseCmd;
//import com.cloud.async.AsyncJobManager;
//import com.cloud.async.AsyncJobResult;
//import com.cloud.async.AsyncJobVO;
//import com.cloud.async.BaseAsyncJobExecutor;
//import com.cloud.serializer.GsonHelper;
//import com.cloud.server.ManagementServer;
//import com.cloud.service.ServiceOfferingVO;
//import com.cloud.storage.VMTemplateVO;
//import com.cloud.user.Account;
//import com.cloud.uservm.UserVm;
//import com.cloud.vm.UserVmVO;
//import com.cloud.vm.VMInstanceVO;
//import com.cloud.vm.VmStats;
//import com.google.gson.Gson;
//
//public class UpgradeVMExecutor extends BaseAsyncJobExecutor {
//    public static final Logger s_logger = Logger.getLogger(UpgradeVMExecutor.class.getName());
//	
//	public boolean execute() {
//		AsyncJobManager asyncMgr = getAsyncJobMgr();
//    	AsyncJobVO job = getJob();
//    	Gson gson = GsonHelper.getBuilder().create();
//		
//		if(getSyncSource() == null) {
//	    	VMOperationParam param = gson.fromJson(job.getCmdInfo(), VMOperationParam.class);
//	    	asyncMgr.syncAsyncJobExecution(job.getId(), "UserVM", param.getVmId());
//	    	
//	    	// always true if it does not have sync-source
//	    	return true;
//		} else {
//			ManagementServer managementServer = asyncMgr.getExecutorContext().getManagementServer();
//			UpgradeVMParam param = gson.fromJson(job.getCmdInfo(), UpgradeVMParam.class);
//			
//			try {
//				asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", param.getVmId());
//			    boolean success = managementServer.upgradeVirtualMachine(param.getUserId(), 
//			    	param.getVmId(), param.getServiceOfferingId(), param.getEventId());
//	
//		        if (success) {
//		        	//get the upgraded vm to compose the result object
//		        	UserVmVO userVm = managementServer.findUserVMInstanceById(param.getVmId());
//					asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, 
//							composeResultObject(userVm, managementServer));
//					
//		        } else {
//					asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, 
//						BaseCmd.VM_CHANGE_SERVICE_ERROR, 
//						composeResultObject(null, managementServer));
//		        }
//			} catch(Exception e) {
//				s_logger.warn("Unable to upgrade VM " + param.getVmId() + ":" + e.getMessage(), e);
//				asyncMgr.completeAsyncJob(getJob().getId(), AsyncJobResult.STATUS_FAILED, 
//					BaseCmd.INTERNAL_ERROR, 
//					e.getMessage());
//			}
//			return true;
//		}
//	}
//	
//	private VmResultObject composeResultObject(UserVmVO vm, ManagementServer ms)
//	{
//		if(vm == null)
//			return null;
//		
//		VmResultObject resultObj = new VmResultObject();
//		Account acct = ms.findAccountById(Long.valueOf(vm.getAccountId()));
//		resultObj.setAccount(acct.getAccountName());
//		
//		ServiceOfferingVO offering = ms.findServiceOfferingById(vm.getServiceOfferingId());
//		resultObj.setCpuSpeed(offering.getSpeed());
//		resultObj.setMemory(offering.getRamSize());
//		if(offering.getDisplayText()!=null)
//			resultObj.setServiceOfferingName(offering.getDisplayText());
//			resultObj.setServiceOfferingName(offering.getName());
//		resultObj.setServiceOfferingId(vm.getServiceOfferingId());
//		
//		VmStats vmStats = ms.getVmStatistics(vm.getId());
//		if(vmStats != null)
//		{
//			resultObj.setCpuUsed((long) vmStats.getCPUUtilization());
//			resultObj.setNetworkKbsRead((long) vmStats.getNetworkReadKBs());
//			resultObj.setNetworkKbsWrite((long) vmStats.getNetworkWriteKBs());
//		}
//		
//		resultObj.setCreated(vm.getCreated());
//		resultObj.setDisplayName(vm.getDisplayName());
//		resultObj.setDomain(ms.findDomainIdById(acct.getDomainId()).getName());
//		resultObj.setDomainId(acct.getDomainId());
//		resultObj.setHaEnable(vm.isHaEnabled());
//		if(vm.getHostId() != null)
//		{
//			resultObj.setHostId(vm.getHostId());
//			resultObj.setHostName(ms.getHostBy(vm.getHostId()).getName());
//		}
//		resultObj.setIpAddress(vm.getPrivateIpAddress());
//		resultObj.setName(vm.getName());
//		resultObj.setState(vm.getState().toString());
//		resultObj.setZoneId(vm.getDataCenterId());
//		resultObj.setZoneName(ms.findDataCenterById(vm.getDataCenterId()).getName());
//		
//		VMTemplateVO template = ms.findTemplateById(vm.getTemplateId());
//		resultObj.setPasswordEnabled(template.getEnablePassword());
//		resultObj.setTemplateDisplayText(template.getDisplayText());
//		resultObj.setTemplateId(template.getId());
//		resultObj.setTemplateName(template.getName());
//		
//		return resultObj;
//	}
//}
File
UpgradeVMExecutor.java
Developer's decision
Version 1
Kind of conflict
Class declaration
Comment
Import
Package declaration
Chunk
Conflicting content
        resultObject.setMemory(String.valueOf(offering.getRamSize()));
        
        //Network groups
<<<<<<< HEAD
//        resultObject.setNetworkGroupList(managementServer.getNetworkGroupsNamesForVm(vm.getId()));
=======
        resultObject.setNetworkGroupList(managementServer.getNetworkGroupsNamesForVm(vm.getId()));
        
        if(vm.getHostId()!=null)
        {
        	resultObject.setHostid(vm.getHostId());
        	if(managementServer.getHostBy(vm.getHostId())!=null)
        	{
                resultObject.setHostname(managementServer.getHostBy(vm.getHostId()).getName());
        	}
               
        }
         
        //root device related
        VolumeVO rootVolume = managementServer.findRootVolume(vm.getId());
        if(rootVolume!=null)
        {
        	resultObject.setRootDeviceId(rootVolume.getDeviceId());
        	StoragePoolVO storagePool = managementServer.findPoolById(rootVolume.getPoolId());
        	resultObject.setRootDeviceType(storagePool.getPoolType().toString());
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        
		return resultObject;
	}
Solution content
        resultObject.setMemory(String.valueOf(offering.getRamSize()));
        
        //Network groups
//        resultObject.setNetworkGroupList(managementServer.getNetworkGroupsNamesForVm(vm.getId()));
        
		return resultObject;
	}
File
VMExecutorHelper.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Variable
Chunk
Conflicting content
	 * @param size
	 * @return ID
	 */
<<<<<<< HEAD
	DiskOfferingVO createDiskOffering(CreateDiskOfferingCmd cmd) throws InvalidParameterValueException;

	/**
	 * Creates a new disk offering
	 * @param domainId
	 * @param name
	 * @param description
	 * @param numGibibytes
	 * @param tags
	 * @return newly created disk offering
	 */
	DiskOfferingVO createDiskOffering(long domainId, String name, String description, int numGibibytes, String tags) throws InvalidParameterValueException;
    
=======
	DiskOfferingVO createDiskOffering(long userId, long domainId, String name, String description, int numGibibytes, String tags);
	
	 /**
     * Deletes a disk offering
     * @param userId
     * @param diskOfferingId
     */
    boolean deleteDiskOffering(long userId, long diskOfferingId);
	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	/**
	 * Creates a new pod
	 * @param userId
Solution content
	 * @param size
	 * @return ID
	 */
	DiskOfferingVO createDiskOffering(CreateDiskOfferingCmd cmd) throws InvalidParameterValueException;

	/**
	 * Creates a new disk offering
	 * @param domainId
	 * @param name
	 * @param description
	 * @param numGibibytes
	 * @param tags
	 * @return newly created disk offering
	 */
	DiskOfferingVO createDiskOffering(long domainId, String name, String description, int numGibibytes, String tags) throws InvalidParameterValueException;
    
	/**
	 * Creates a new pod
	 * @param userId
File
ConfigurationManager.java
Developer's decision
Version 1
Kind of conflict
Comment
Method interface
Chunk
Conflicting content
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
<<<<<<< HEAD
import com.cloud.vm.State;
=======
import com.cloud.vm.SecondaryStorageVmVO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
Solution content
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.State;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
File
ConfigurationManagerImpl.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
	@Inject AccountDao _accountDao;
	@Inject EventDao _eventDao;
	@Inject UserDao _userDao;
<<<<<<< HEAD
	@Inject DataCenterDao _dcDao;
	@Inject HostPodDao _hostPodDao;
	@Inject AccountManager _accountMgr;
	@Inject NetworkManager _networkMgr;
=======
	@Inject ConsoleProxyDao _consoleDao;
	@Inject SecondaryStorageVmDao _secStorageDao;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
	public boolean _premium;

	private int _maxVolumeSizeInGb;
Solution content
	@Inject AccountDao _accountDao;
	@Inject EventDao _eventDao;
	@Inject UserDao _userDao;
	@Inject DataCenterDao _dcDao;
	@Inject HostPodDao _hostPodDao;
	@Inject AccountManager _accountMgr;
	@Inject NetworkManager _networkMgr;
	@Inject ConsoleProxyDao _consoleDao;
	@Inject SecondaryStorageVmDao _secStorageDao;
	public boolean _premium;

	private int _maxVolumeSizeInGb;
File
ConfigurationManagerImpl.java
Developer's decision
Concatenation
Kind of conflict
Attribute
Chunk
Conflicting content
    	
    	HostPodVO pod = _podDao.findById(podId);
    	DataCenterVO zone = _zoneDao.findById(pod.getDataCenterId());
<<<<<<< HEAD
=======

    	_podDao.expunge(podId);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	
    	//Delete the pod and private IP addresses in the pod
    	if (_podDao.delete(podId) && _privateIpAddressDao.deleteIpAddressByPod(podId)) {
Solution content
    	HostPodVO pod = _podDao.findById(podId);
    	DataCenterVO zone = _zoneDao.findById(pod.getDataCenterId());

    	//Delete the pod and private IP addresses in the pod
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Method invocation
Chunk
Conflicting content
		
		return pod;
    }
<<<<<<< HEAD

    @Override
    public HostPodVO createPod(CreatePodCmd cmd) throws InvalidParameterValueException, InternalErrorException {
        String cidr = cmd.getCidr();
        String endIp = cmd.getEndIp();
        String gateway = cmd.getGateway();
        String name = cmd.getPodName();
        String startIp = cmd.getStartIp();
        Long zoneId = cmd.getZoneId();

        //verify input parameters
        DataCenterVO zone = _zoneDao.findById(zoneId);
        if (zone == null) {
            throw new InvalidParameterValueException("Failed to create pod " + name + " -- unable to find zone " + zoneId);
        }

        if (endIp != null && startIp == null) {
            throw new InvalidParameterValueException("Failed to create pod " + name + " -- if an end IP is specified, a start IP must be specified.");
        }

        Long userId = UserContext.current().getUserId();
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        return createPod(userId.longValue(), name, zoneId, gateway, cidr, startIp, endIp);
    }

    @Override @DB
=======
    
    @Override
    @DB
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public HostPodVO createPod(long userId, String podName, long zoneId, String gateway, String cidr, String startIp, String endIp) throws InvalidParameterValueException, InternalErrorException {
    	checkPodAttributes(-1, podName, zoneId, gateway, cidr, startIp, endIp, true);
		
Solution content
        //verify input parameters
		
		return pod;
    }

    @Override
    public HostPodVO createPod(CreatePodCmd cmd) throws InvalidParameterValueException, InternalErrorException {
        String cidr = cmd.getCidr();
        String endIp = cmd.getEndIp();
        String gateway = cmd.getGateway();
        String name = cmd.getPodName();
        String startIp = cmd.getStartIp();
        Long zoneId = cmd.getZoneId();

        DataCenterVO zone = _zoneDao.findById(zoneId);
        if (zone == null) {
            throw new InvalidParameterValueException("Failed to create pod " + name + " -- unable to find zone " + zoneId);
        }

        if (endIp != null && startIp == null) {
            throw new InvalidParameterValueException("Failed to create pod " + name + " -- if an end IP is specified, a start IP must be specified.");
        }

        Long userId = UserContext.current().getUserId();
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        return createPod(userId.longValue(), name, zoneId, gateway, cidr, startIp, endIp);
    }

    @Override @DB
    public HostPodVO createPod(long userId, String podName, long zoneId, String gateway, String cidr, String startIp, String endIp) throws InvalidParameterValueException, InternalErrorException {
    	checkPodAttributes(-1, podName, zoneId, gateway, cidr, startIp, endIp, true);
		
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    		}
    	}
    	
<<<<<<< HEAD
    	//To modify a zone, we need to make sure there are no domr's associated with it
    	//1. List all the domain router objs
    	//2. Check if any of these has the current data center associated
    	//3. If yes, throw exception
    	//4, If no, edit
    	List allDomainRoutersAvailable = _domrDao.listAll();
    	
    	for(DomainRouterVO domR : allDomainRoutersAvailable)
    	{
    		if(domR.getDataCenterId() == zoneId)
    		{
    			throw new InternalErrorException("The zone is not editable because there are domR's associated with the zone.");
    		}
    	}
    	
    	//5. Reached here, hence editable   	
=======
    	
    	DataCenterVO zone = _zoneDao.findById(zoneId);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	String oldZoneName = zone.getName();
    	
    	if (zoneName == null) {
Solution content
    		}
    	}

    	String oldZoneName = zone.getName();
    	
    	if (zoneName == null) {
File
ConfigurationManagerImpl.java
Developer's decision
None
Kind of conflict
Comment
For statement
Method invocation
Variable
Chunk
Conflicting content
    	
    	return zone;
    }
<<<<<<< HEAD

    @Override @DB
=======
    
    @Override
    @DB
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String vnetRange, String guestCidr) throws InvalidParameterValueException, InternalErrorException {
        int vnetStart, vnetEnd;
        if (vnetRange != null) {
Solution content
    	
    	return zone;
    }

    @Override @DB
    public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String vnetRange, String guestCidr) throws InvalidParameterValueException, InternalErrorException {
        int vnetStart, vnetEnd;
        if (vnetRange != null) {
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Chunk
Conflicting content
        return zone;
        saveConfigurationEvent(userId, null, EventTypes.EVENT_ZONE_CREATE, "Successfully created new zone with name: " + zoneName + ".", "dcId=" + zone.getId(), "dns1=" + dns1, "dns2=" + dns2, "internalDns1=" + internalDns1, "internalDns2=" + internalDns2, "vnetRange=" + vnetRange, "guestCidr=" + guestCidr);
        
<<<<<<< HEAD
    }

    @Override
    public DataCenterVO createZone(CreateZoneCmd cmd) throws InvalidParameterValueException, InternalErrorException {
        // grab parameters from the command
        Long userId = UserContext.current().getUserId();
        String zoneName = cmd.getZoneName();
        String dns1 = cmd.getDns1();
        String dns2 = cmd.getDns2();
        String internalDns1 = cmd.getInternalDns1();
        String internalDns2 = cmd.getInternalDns2();
        String vnetRange = cmd.getVlan();
        String guestCidr = cmd.getGuestCidrAddress();

        if (userId == null) {
            userId = User.UID_SYSTEM;
        }

        return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, vnetRange, guestCidr);
    }

    @Override
    public ServiceOfferingVO createServiceOffering(CreateServiceOfferingCmd cmd) throws InvalidParameterValueException {
        Long userId = UserContext.current().getUserId();
        if (userId == null) {
            userId = User.UID_SYSTEM;
        }

        String name = cmd.getServiceOfferingName();
        if ((name == null) || (name.length() == 0)) {
            throw new InvalidParameterValueException("Failed to create service offering: specify the name that has non-zero length");
        }

        String displayText = cmd.getDisplayText();
        if ((displayText == null) || (displayText.length() == 0)) {
            throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the display text that has non-zero length");
        }

        Long cpuNumber = cmd.getCpuNumber();
        if ((cpuNumber == null) || (cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647)) {
            throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu number value between 1 and 2147483647");
        }

        Long cpuSpeed = cmd.getCpuSpeed();
        if ((cpuSpeed == null) || (cpuSpeed.intValue() <= 0) || (cpuSpeed.intValue() > 2147483647)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering " + name + ": specify the cpu speed value between 1 and 2147483647");
        }

        Long memory = cmd.getMemory();
        if ((memory == null) || (memory.intValue() <= 0) || (memory.intValue() > 2147483647)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering " + name + ": specify the memory value between 1 and 2147483647");
        }

        boolean localStorageRequired = false;
        String storageType = cmd.getStorageType();
        if (storageType == null) {
            localStorageRequired = false;
        } else if (storageType.equals("local")) {
            localStorageRequired = true;
        } else if (storageType.equals("shared")) {
            localStorageRequired = false;
        } else {
            throw new InvalidParameterValueException("Invalid storage type " + storageType + " specified, valid types are: 'local' and 'shared'");
        }

        Boolean offerHA = cmd.getOfferHa();
        if (offerHA == null) {
            offerHA = false;
        }

        Boolean useVirtualNetwork = cmd.getUseVirtualNetwork();
        if (useVirtualNetwork == null) {
            useVirtualNetwork = Boolean.TRUE;
        }

        return createServiceOffering(userId, cmd.getServiceOfferingName(), cpuSpeed.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(),
                localStorageRequired, offerHA, useVirtualNetwork, cmd.getTags());
    }

=======
    	checkZoneParameters(zoneName, dns1, dns2, internalDns1, internalDns2,true);
		
		// Create the new zone in the database
		DataCenterVO zone = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, vnetRange, guestCidr);
		zone = _zoneDao.persist(zone);
		
		// Add vnet entries for the new zone
    	_zoneDao.addVnet(zone.getId(), vnetStart, vnetEnd);
		
		saveConfigurationEvent(userId, null, EventTypes.EVENT_ZONE_CREATE, "Successfully created new zone with name: " + zoneName + ".", "dcId=" + zone.getId(), "dns1=" + dns1, "dns2=" + dns2, "internalDns1=" + internalDns1, "internalDns2=" + internalDns2, "vnetRange=" + vnetRange, "guestCidr=" + guestCidr);
    	
		return zone;
    }
    
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    @Override
    public ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, boolean useVirtualNetwork, String tags) {
    	String networkRateStr = _configDao.getValue("network.throttling.rate");
Solution content

        saveConfigurationEvent(userId, null, EventTypes.EVENT_ZONE_CREATE, "Successfully created new zone with name: " + zoneName + ".", "dcId=" + zone.getId(), "dns1=" + dns1, "dns2=" + dns2, "internalDns1=" + internalDns1, "internalDns2=" + internalDns2, "vnetRange=" + vnetRange, "guestCidr=" + guestCidr);

        return zone;
    }

    @Override
    public DataCenterVO createZone(CreateZoneCmd cmd) throws InvalidParameterValueException, InternalErrorException {
        // grab parameters from the command
        Long userId = UserContext.current().getUserId();
        String zoneName = cmd.getZoneName();
        String dns1 = cmd.getDns1();
        String dns2 = cmd.getDns2();
        String internalDns1 = cmd.getInternalDns1();
        String internalDns2 = cmd.getInternalDns2();
        String vnetRange = cmd.getVlan();
        String guestCidr = cmd.getGuestCidrAddress();

        if (userId == null) {
            userId = User.UID_SYSTEM;
        }

        return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, vnetRange, guestCidr);
    }

    @Override
    public ServiceOfferingVO createServiceOffering(CreateServiceOfferingCmd cmd) throws InvalidParameterValueException {
        Long userId = UserContext.current().getUserId();
        if (userId == null) {
            userId = User.UID_SYSTEM;
        }

        String name = cmd.getServiceOfferingName();
        if ((name == null) || (name.length() == 0)) {
            throw new InvalidParameterValueException("Failed to create service offering: specify the name that has non-zero length");
        }

        String displayText = cmd.getDisplayText();
        if ((displayText == null) || (displayText.length() == 0)) {
            throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the display text that has non-zero length");
        }

        Long cpuNumber = cmd.getCpuNumber();
        if ((cpuNumber == null) || (cpuNumber.intValue() <= 0) || (cpuNumber.intValue() > 2147483647)) {
            throw new InvalidParameterValueException("Failed to create service offering " + name + ": specify the cpu number value between 1 and 2147483647");
        }

        Long cpuSpeed = cmd.getCpuSpeed();
        if ((cpuSpeed == null) || (cpuSpeed.intValue() <= 0) || (cpuSpeed.intValue() > 2147483647)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering " + name + ": specify the cpu speed value between 1 and 2147483647");
        }
        Long memory = cmd.getMemory();
        if ((memory == null) || (memory.intValue() <= 0) || (memory.intValue() > 2147483647)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Failed to create service offering " + name + ": specify the memory value between 1 and 2147483647");
        }

        boolean localStorageRequired = false;
        String storageType = cmd.getStorageType();
        if (storageType == null) {
            localStorageRequired = false;
        } else if (storageType.equals("local")) {
            localStorageRequired = true;
        } else if (storageType.equals("shared")) {
            localStorageRequired = false;
        } else {
            throw new InvalidParameterValueException("Invalid storage type " + storageType + " specified, valid types are: 'local' and 'shared'");
        }

        Boolean offerHA = cmd.getOfferHa();
        if (offerHA == null) {
            offerHA = false;
        }

        Boolean useVirtualNetwork = cmd.getUseVirtualNetwork();
        if (useVirtualNetwork == null) {
            useVirtualNetwork = Boolean.TRUE;
        }

        return createServiceOffering(userId, cmd.getServiceOfferingName(), cpuSpeed.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(),
                localStorageRequired, offerHA, useVirtualNetwork, cmd.getTags());
    }

    @Override
    public ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, boolean useVirtualNetwork, String tags) {
    	String networkRateStr = _configDao.getValue("network.throttling.rate");
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Comment
Method declaration
Method invocation
Return statement
Variable
Chunk
Conflicting content
    	}
    }
    
<<<<<<< HEAD
    public ServiceOfferingVO updateServiceOffering(UpdateServiceOfferingCmd cmd) {
    	String displayText = cmd.getDisplayText();
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	Boolean ha = cmd.getOfferHa();
    	String tags = cmd.getTags();
    	Boolean useVirtualNetwork = cmd.getUseVirtualNetwork();
    	Long userId = UserContext.current().getUserId();

        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // Verify input parameters
        ServiceOfferingVO offeringHandle = _serviceOfferingDao.findById(id);;
    	if (offeringHandle == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find service offering " + id);
    	}
    	
    	boolean updateNeeded = (name != null || displayText != null || ha != null || useVirtualNetwork != null || tags != null);
=======
    @Override
    public ServiceOfferingVO updateServiceOffering(long userId, long serviceOfferingId, String name, String displayText, Boolean offerHA, Boolean useVirtualNetwork, String tags) {
    	boolean updateNeeded = (name != null || displayText != null || offerHA != null || useVirtualNetwork != null || tags != null);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	if (!updateNeeded) {
    		return _serviceOfferingDao.findById(id);
    	}
Solution content
    	String name = cmd.getName();
    	Boolean ha = cmd.getOfferHa();
    	}
    }

    public ServiceOfferingVO updateServiceOffering(UpdateServiceOfferingCmd cmd) {
    	String displayText = cmd.getDisplayText();
    	Long id = cmd.getId();
    	String tags = cmd.getTags();
    	Boolean useVirtualNetwork = cmd.getUseVirtualNetwork();
    	Long userId = UserContext.current().getUserId();

        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // Verify input parameters
        ServiceOfferingVO offeringHandle = _serviceOfferingDao.findById(id);;
    	if (offeringHandle == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find service offering " + id);
    	}
    	
    	boolean updateNeeded = (name != null || displayText != null || ha != null || useVirtualNetwork != null || tags != null);
    	if (!updateNeeded) {
    		return _serviceOfferingDao.findById(id);
    	}
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Comment
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
        return createDiskOffering(domainId, name, description, numGibibytes, tags);
    }
    
<<<<<<< HEAD
    public DiskOfferingVO updateDiskOffering(UpdateDiskOfferingCmd cmd) throws InvalidParameterValueException{
    	Long diskOfferingId = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String tags = cmd.getTags();
    	
    	//Check if diskOffering exists
    	DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
    	
    	if (diskOffering == null) {
    		throw new InvalidParameterValueException("Unable to find disk offering by id " + diskOfferingId);
    	}
    	
=======
    @Override
    public DiskOfferingVO updateDiskOffering(long userId, long diskOfferingId, String name, String displayText, String tags) {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	boolean updateNeeded = (name != null || displayText != null || tags != null);
    	if (!updateNeeded) {
    		return _diskOfferingDao.findById(diskOfferingId);
Solution content
        return createDiskOffering(domainId, name, description, numGibibytes, tags);
    }

    public DiskOfferingVO updateDiskOffering(UpdateDiskOfferingCmd cmd) throws InvalidParameterValueException{
    	Long diskOfferingId = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String tags = cmd.getTags();
    	
    	//Check if diskOffering exists
    	DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
    	
    	if (diskOffering == null) {
    		throw new InvalidParameterValueException("Unable to find disk offering by id " + diskOfferingId);
    	}
    	
    	boolean updateNeeded = (name != null || displayText != null || tags != null);
    	if (!updateNeeded) {
    		return _diskOfferingDao.findById(diskOfferingId);
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Comment
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
    	}
    }
    
<<<<<<< HEAD
    
    public boolean deleteDiskOffering(DeleteDiskOfferingCmd cmd) throws InvalidParameterValueException{
    	Long diskOfferingId = cmd.getId();
    	
    	DiskOfferingVO offering = _diskOfferingDao.findById(diskOfferingId);
    	
    	if (offering == null) {
    		throw new InvalidParameterValueException("Unable to find disk offering by id " + diskOfferingId);
    	}
    	
    	if (_diskOfferingDao.remove(diskOfferingId)) {
=======
    @Override
    public boolean deleteServiceOffering(long userId, long serviceOfferingId) {
    	ServiceOfferingVO offering = _serviceOfferingDao.findById(serviceOfferingId);
    	
    	if (_serviceOfferingDao.remove(serviceOfferingId)) {
    		saveConfigurationEvent(userId, null, EventTypes.EVENT_SERVICE_OFFERING_DELETE, "Successfully deleted service offering with name: " + offering.getName(), "soId=" + serviceOfferingId, "name=" + offering.getName(),
    				"displayText=" + offering.getDisplayText(), "offerHA=" + offering.getOfferHA(), "useVirtualNetwork=" + (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized));
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    		return true;
    	} else {
    		return false;
Solution content
    	}
    }

    public boolean deleteDiskOffering(DeleteDiskOfferingCmd cmd) throws InvalidParameterValueException{
    	Long diskOfferingId = cmd.getId();
    	
    	DiskOfferingVO offering = _diskOfferingDao.findById(diskOfferingId);
    	
    	if (offering == null) {
    		throw new InvalidParameterValueException("Unable to find disk offering by id " + diskOfferingId);
    	}
    	
    	if (_diskOfferingDao.remove(diskOfferingId)) {
    		return true;
    	} else {
    		return false;
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
    }

    
<<<<<<< HEAD
    public boolean deleteServiceOffering(DeleteServiceOfferingCmd cmd) throws InvalidParameterValueException{
    	
        Long offeringId = cmd.getId();
        Long userId = UserContext.current().getUserId();
        
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
 
        //Verify service offering id
        ServiceOfferingVO offering = _serviceOfferingDao.findById(offeringId);
    	if (offering == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find service offering " + offeringId);
    	} else if (offering.getRemoved() != null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find service offering " + offeringId);
    	}
    	
    	if (_serviceOfferingDao.remove(offeringId)) {
    		saveConfigurationEvent(userId, null, EventTypes.EVENT_SERVICE_OFFERING_EDIT, "Successfully deleted service offering with name: " + offering.getName(), "soId=" + offeringId, "name=" + offering.getName(),
    				"displayText=" + offering.getDisplayText(), "offerHA=" + offering.getOfferHA(), "useVirtualNetwork=" + (offering.getGuestIpType() == GuestIpType.Virtualized));
    		return true;
    	} else {
    		return false;
    	}
    }

=======
    @Override
    public DiskOfferingVO createDiskOffering(long userId, long domainId, String name, String description, int numGibibytes, String tags) {
    	long diskSize = numGibibytes * 1024;
    	tags = cleanupTags(tags);
		DiskOfferingVO newDiskOffering = new DiskOfferingVO(domainId, name, description, diskSize,tags);
		
		if ((newDiskOffering = _diskOfferingDao.persist(newDiskOffering)) != null) {
		    saveConfigurationEvent(userId, null, EventTypes.EVENT_DISK_OFFERING_CREATE, "Successfully created new disk offering with name: " 
		                           + name + ".", "doId=" + newDiskOffering.getId(), "name=" + name, "diskSize=" + diskSize, "description=" 
		                           + description, "tags=" + tags);
		    return newDiskOffering;
		} else {
		    return null;
		}
    }
    
    @Override
    public boolean deleteDiskOffering(long userId, long diskOfferingId) {
        DiskOfferingVO offering = _diskOfferingDao.findById(diskOfferingId);
        
        if (_diskOfferingDao.remove(diskOfferingId)) {
            saveConfigurationEvent(userId, null, EventTypes.EVENT_DISK_OFFERING_DELETE, "Successfully deleted disk offering with name: " 
                    + offering.getName(), "doId=" + offering.getId(), "name=" + offering.getName(), "diskSize=" + offering.getDiskSize(), 
                    "description=" + offering.getDisplayText(), "tags=" + offering.getTags());
            return true;
        } else {
            return false;
        }
    }
    
    @Override
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public String changePrivateIPRange(boolean add, long podId, String startIP, String endIP) throws InvalidParameterValueException {
    	checkPrivateIpRangeErrors(podId, startIP, endIP);
    	
Solution content
    }

    public boolean deleteServiceOffering(DeleteServiceOfferingCmd cmd) throws InvalidParameterValueException{
    	
        Long offeringId = cmd.getId();
        Long userId = UserContext.current().getUserId();
        
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
 
        //Verify service offering id
        ServiceOfferingVO offering = _serviceOfferingDao.findById(offeringId);
    	if (offering == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find service offering " + offeringId);
    	} else if (offering.getRemoved() != null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find service offering " + offeringId);
    	}
    	
    	if (_serviceOfferingDao.remove(offeringId)) {
    		saveConfigurationEvent(userId, null, EventTypes.EVENT_SERVICE_OFFERING_EDIT, "Successfully deleted service offering with name: " + offering.getName(), "soId=" + offeringId, "name=" + offering.getName(),
    				"displayText=" + offering.getDisplayText(), "offerHA=" + offering.getOfferHA(), "useVirtualNetwork=" + (offering.getGuestIpType() == GuestIpType.Virtualized));
    		return true;
    	} else {
    		return false;
    	}
    }

    public String changePrivateIPRange(boolean add, long podId, String startIP, String endIP) throws InvalidParameterValueException {
    	checkPrivateIpRangeErrors(podId, startIP, endIP);
    	
File
ConfigurationManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
			return genChangeRangeSuccessString(problemIPs, add);
		}
    }
<<<<<<< HEAD

    @Override
//    public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException {    		
    public VlanVO createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InvalidParameterValueException, InternalErrorException, InsufficientCapacityException {
        Long userId = UserContext.current().getUserId();
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        // If forVirtualNetworks isn't specified, default it to true
        Boolean forVirtualNetwork = cmd.isForVirtualNetwork();
        if (forVirtualNetwork == null) {
            forVirtualNetwork = Boolean.TRUE;
        }

        // If the VLAN id is null, default it to untagged
        String vlanId = cmd.getVlan();
        if (vlanId == null) {
            vlanId = Vlan.UNTAGGED;
        }

        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account account = null;
        if ((accountName != null) && (domainId != null)) {
            account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid account.");
            }
        }       
        
        VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        Long zoneId = cmd.getZoneId();
        Long podId = cmd.getPodId();
        String startIP = cmd.getStartIp();
        String endIP = cmd.getEndIp();
        String vlanGateway = cmd.getGateway();
        String vlanNetmask = cmd.getNetmask();

=======
    
    @Override
    public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws InvalidParameterValueException, InternalErrorException {    		
    	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
		//check for hypervisor type to be xenserver
		String hypervisorType = _configDao.getValue("hypervisor.type");
				
Solution content
			return genChangeRangeSuccessString(problemIPs, add);
		}
    }

    @Override
    public VlanVO createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InvalidParameterValueException, InternalErrorException, InsufficientCapacityException {
        Long userId = UserContext.current().getUserId();
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        // If forVirtualNetworks isn't specified, default it to true
        Boolean forVirtualNetwork = cmd.isForVirtualNetwork();
        if (forVirtualNetwork == null) {
            forVirtualNetwork = Boolean.TRUE;
        }

        // If the VLAN id is null, default it to untagged
        String vlanId = cmd.getVlan();
        if (vlanId == null) {
            vlanId = Vlan.UNTAGGED;
        }

        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account account = null;
        if ((accountName != null) && (domainId != null)) {
            account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please specify a valid account.");
            }
        }       
        
        VlanType vlanType = forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        Long zoneId = cmd.getZoneId();
        Long podId = cmd.getPodId();
        String startIP = cmd.getStartIp();
        String endIP = cmd.getEndIp();
        String vlanGateway = cmd.getGateway();
        String vlanNetmask = cmd.getNetmask();

		//check for hypervisor type to be xenserver
		String hypervisorType = _configDao.getValue("hypervisor.type");
				
File
ConfigurationManagerImpl.java
Developer's decision
Combination
Kind of conflict
Annotation
Comment
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
	    	}
	    	
		}
<<<<<<< HEAD

=======
		
		//if we have an ip range for vlan id=x, vlantype=y; we should
		 //only allow adding another range with id=x for same type y
		if(!vlanId.equals(Vlan.UNTAGGED))
		{
			VlanVO vlanHandle = _vlanDao.findByZoneAndVlanId(zoneId, vlanId);
			
			if(vlanHandle!=null && !vlanHandle.getVlanType().equals(vlanType))
				throw new InvalidParameterValueException("This vlan id is already associated with the vlan type "+vlanHandle.getVlanType().toString()
						+",whilst you are trying to associate it with vlan type "+vlanType.toString());
		}
		
    	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	DataCenterVO zone;
    	if (zoneId == null || ((zone = _zoneDao.findById(zoneId)) == null)) {
			throw new InvalidParameterValueException("Please specify a valid zone.");
Solution content
	    	}
	    	
		}

        //if we have an ip range for vlan id=x, vlantype=y; we should
	    //only allow adding another range with id=x for same type y
        if (!vlanId.equals(Vlan.UNTAGGED)) {
            VlanVO vlanHandle = _vlanDao.findByZoneAndVlanId(zoneId, vlanId);

            if (vlanHandle!=null && !vlanHandle.getVlanType().equals(vlanType))
                throw new InvalidParameterValueException("This vlan id is already associated with the vlan type "+vlanHandle.getVlanType().toString()
                        +",whilst you are trying to associate it with vlan type "+vlanType.toString());
        }

    	DataCenterVO zone;
    	if (zoneId == null || ((zone = _zoneDao.findById(zoneId)) == null)) {
			throw new InvalidParameterValueException("Please specify a valid zone.");
File
ConfigurationManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Comment
If statement
Chunk
Conflicting content
        		}
        		
        		// Make sure the specified account isn't already assigned to a VLAN in this zone
<<<<<<< HEAD
        		List accountVlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(account.getId());
        		for (AccountVlanMapVO accountVlanMap : accountVlanMaps) {
        			VlanVO vlan = _vlanDao.findById(accountVlanMap.getVlanDbId());
        			if (vlan.getDataCenterId() == zone.getId().longValue()) {
        				throw new InvalidParameterValueException("The account " + account.getAccountName() + " is already assigned to an IP range in zone " + zone.getName() + ".");
        			}
        		}
=======
//        		List accountVlanMaps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId);
//        		for (AccountVlanMapVO accountVlanMap : accountVlanMaps) {
//        			VlanVO vlan = _vlanDao.findById(accountVlanMap.getVlanDbId());
//        			if (vlan.getDataCenterId() == zone.getId()) {
//        				throw new InvalidParameterValueException("The account " + account.getAccountName() + " is already assigned to an IP range in zone " + zone.getName() + ".");
//        			}
//        		}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    		} else if (podId != null) {
    			// Pod-wide VLANs must be untagged
        		if (!vlanId.equals(Vlan.UNTAGGED)) {
Solution content
        		}
    		} else if (podId != null) {
    			// Pod-wide VLANs must be untagged
        		if (!vlanId.equals(Vlan.UNTAGGED)) {
File
ConfigurationManagerImpl.java
Developer's decision
None
Kind of conflict
Comment
For statement
Method invocation
Variable
Chunk
Conflicting content
    public boolean stop(ConsoleProxyVO vm, long startEventId) throws AgentUnavailableException {
        return false;
    }
<<<<<<< HEAD

    @Override
    public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) {
        return null;
    }

    @Override
    public boolean destroyConsoleProxy(DestroyConsoleProxyCmd cmd) throws ServerApiException {
        return false;
    }

	@Override
	public boolean destroyProxy(long proxyVmId, long startEventId) {
		return false;
	}

	@Override
	public boolean rebootProxy(long proxyVmId, long startEventId) {
		return false;
	}

	@Override
	public boolean stopProxy(long proxyVmId, long startEventId) {
		return false;
	}

	@Override
	public String getName() {
		return _name;
	}

    @Override
    public Command cleanup(ConsoleProxyVO vm, String vmName) {
        return new StopCommand(vm, vmName, null);
    }

    @Override
    public boolean completeMigration(ConsoleProxyVO vm, HostVO host) throws AgentUnavailableException, OperationTimedoutException {
        return false;
    }

    @Override
    public void completeStartCommand(ConsoleProxyVO vm) {
    }

    @Override
    public void completeStopCommand(ConsoleProxyVO vm) {
    }

    @Override
    public Long convertToId(String vmName) {
        if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) {
            return null;
        }
        return VirtualMachineName.getConsoleProxyId(vmName);
    }

    @Override
    public boolean destroy(ConsoleProxyVO vm) throws AgentUnavailableException {
        return false;
    }

    @Override
    public ConsoleProxyVO get(long id) {
        return null;
    }

    @Override
    public boolean migrate(ConsoleProxyVO vm, HostVO host) throws AgentUnavailableException, OperationTimedoutException {
        return false;
    }

    @Override
    public HostVO prepareForMigration(ConsoleProxyVO vm) throws InsufficientCapacityException, StorageUnavailableException {
        return null;
    }

    @Override
    public ConsoleProxyVO start(long vmId, long startEventId) throws InsufficientCapacityException, StorageUnavailableException, ConcurrentOperationException {
        return null;
    }

    @Override
    public boolean stop(ConsoleProxyVO vm, long startEventId) throws AgentUnavailableException {
        return false;
    }
}
=======
}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
Solution content
    public boolean stop(ConsoleProxyVO vm, long startEventId) throws AgentUnavailableException {
        return false;
    }

    @Override
    public boolean destroyConsoleProxy(DestroyConsoleProxyCmd cmd) throws ServerApiException {
        return false;
    }
}
File
AgentBasedConsoleProxyManager.java
Developer's decision
Combination
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
 */
package com.cloud.consoleproxy;

<<<<<<< HEAD:server/src/com/cloud/consoleproxy/ConsoleProxyListener.java
=======
import org.apache.log4j.Logger;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590:server/src/com/cloud/consoleproxy/ConsoleProxyListener.java
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
Solution content
 */
package com.cloud.consoleproxy;

import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
File
ConsoleProxyListener.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.host.Status;

public class ConsoleProxyListener implements Listener {
<<<<<<< HEAD:server/src/com/cloud/consoleproxy/ConsoleProxyListener.java
    ConsoleProxyManager _proxyMgr = null;
=======
    private final static Logger s_logger = Logger.getLogger(ConsoleProxyListener.class);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590:server/src/com/cloud/consoleproxy/ConsoleProxyListener.java

    AgentHook _proxyMgr = null;
Solution content
import com.cloud.host.Status;

public class ConsoleProxyListener implements Listener {
    AgentHook _proxyMgr = null;
File
ConsoleProxyListener.java
Developer's decision
None
Kind of conflict
Attribute
Method invocation
Chunk
Conflicting content
import com.cloud.maid.StackMaid;
import com.cloud.network.IpAddrAllocator;
import com.cloud.network.IpAddrAllocator.networkInfo;
<<<<<<< HEAD
=======
import com.cloud.network.NetworkConfigurationVO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.network.NetworkManager;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.offering.NetworkOffering;
Solution content
import com.cloud.maid.StackMaid;
import com.cloud.network.IpAddrAllocator;
import com.cloud.network.IpAddrAllocator.networkInfo;
import com.cloud.network.NetworkConfigurationVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.offering.NetworkOffering;
File
ConsoleProxyManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
<<<<<<< HEAD
import com.cloud.storage.dao.StoragePoolDao;
=======
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VolumeDao;
Solution content
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VolumeDao;
File
ConsoleProxyManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineName;
<<<<<<< HEAD
=======
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VmManager;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
Solution content
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachineName;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VmManager;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
File
ConsoleProxyManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
// because sooner or later, it will be driven into Running state
//
@Local(value = { ConsoleProxyManager.class })
<<<<<<< HEAD
public class ConsoleProxyManagerImpl implements ConsoleProxyManager,
		VirtualMachineManager {
	private static final Logger s_logger = Logger
			.getLogger(ConsoleProxyManagerImpl.class);

	private static final int DEFAULT_FIND_HOST_RETRY_COUNT = 2;
	private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30
	// seconds
	private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1000; // 1 second

	private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3
	// seconds
	private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC = 180; // 3
	// minutes

	private static final int API_WAIT_TIMEOUT = 5000; // 5 seconds (in
	// milliseconds)
	private static final int STARTUP_DELAY = 60000; // 60 seconds

	private int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT;
	private int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT;

	private String _mgmt_host;
	private int _mgmt_port = 8250;

	private String _name;
	private Adapters _consoleProxyAllocators;

	private ConsoleProxyDao _consoleProxyDao;
	private DataCenterDao _dcDao;
	private VlanDao _vlanDao;
	private VMTemplateDao _templateDao;
	private IPAddressDao _ipAddressDao;
	private VolumeDao _volsDao;
	private HostPodDao _podDao;
	private HostDao _hostDao;
	private StoragePoolDao _storagePoolDao;
	private ConfigurationDao _configDao;
	
	private VMInstanceDao _instanceDao;
	private AccountDao _accountDao;

	private VMTemplateHostDao _vmTemplateHostDao;
	private CapacityDao _capacityDao;
	private HighAvailabilityDao _haDao;



	private AgentManager _agentMgr;
					
	private NetworkManager _networkMgr;
	private StorageManager _storageMgr;
	private HighAvailabilityManager _haMgr;
	private EventDao _eventDao;
	@Inject
	ServiceOfferingDao _offeringDao;
	private IpAddrAllocator _IpAllocator;
	private ConsoleProxyListener _listener;

	private ServiceOfferingVO _serviceOffering;
	private VMTemplateVO _template;

	private AsyncJobManager _asyncMgr;

	private final ScheduledExecutorService _capacityScanScheduler = Executors
			.newScheduledThreadPool(1, new NamedThreadFactory("CP-Scan"));
	private final ExecutorService _requestHandlerScheduler = Executors
			.newCachedThreadPool(new NamedThreadFactory("Request-handler"));

	private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL;
	private int _capacityPerProxy = ConsoleProxyManager.DEFAULT_PROXY_CAPACITY;
	private int _standbyCapacity = ConsoleProxyManager.DEFAULT_STANDBY_CAPACITY;

	private int _proxyRamSize;
	private int _find_host_retry = DEFAULT_FIND_HOST_RETRY_COUNT;
	private int _ssh_retry;
	private int _ssh_sleep;
	private boolean _use_lvm;
	private boolean _use_storage_vm;

	private String _domain;
	private String _instance;

	// private String _privateNetmask;
	private int _proxyCmdPort = DEFAULT_PROXY_CMD_PORT;
	private int _proxySessionTimeoutValue = DEFAULT_PROXY_SESSION_TIMEOUT;
	private boolean _sslEnabled = false;

	private final GlobalLock _capacityScanLock = GlobalLock
			.getInternLock(getCapacityScanLockName());
	private final GlobalLock _allocProxyLock = GlobalLock
			.getInternLock(getAllocProxyLockName());

	public ConsoleProxyVO assignProxy(final long dataCenterId, final long vmId) {

		final Pair result = new Pair(
				this, null);

		_requestHandlerScheduler.execute(new Runnable() {
			public void run() {
				Transaction txn = Transaction.open(Transaction.CLOUD_DB);
				try {
					ConsoleProxyVO proxy = doAssignProxy(dataCenterId, vmId);
					synchronized (result) {
						result.second(proxy);
						result.notifyAll();
					}
				} catch (Throwable e) {
					s_logger.warn("Unexpected exception " + e.getMessage(), e);
				} finally {
					StackMaid.current().exitCleanup();
					txn.close();
				}
			}
		});

		synchronized (result) {
			try {
				result.wait(API_WAIT_TIMEOUT);
			} catch (InterruptedException e) {
				s_logger.info("Waiting for console proxy assignment is interrupted");
			}
		}
		return result.second();
	}

	public ConsoleProxyVO doAssignProxy(long dataCenterId, long vmId) {
		ConsoleProxyVO proxy = null;
		VMInstanceVO vm = _instanceDao.findById(vmId);
		if (vm == null) {
			s_logger.warn("VM " + vmId + " no longer exists, return a null proxy for vm:" + vmId);
			return null;
		}

		Boolean[] proxyFromStoppedPool = new Boolean[1];
		if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
			try {
				proxy = getOrAllocProxyResource(dataCenterId, vmId, proxyFromStoppedPool);
			} finally {
				_allocProxyLock.unlock();
			}
		} else {
			s_logger.error("Unable to acquire synchronization lock to get/allocate proxy resource for vm :"
				+ vmId + ". Previous console proxy allocation is taking too long");
		}

		if (proxy == null) {
			s_logger.warn("Unable to find or allocate console proxy resource");
			return null;
		}

		long proxyVmId = proxy.getId();
		GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId));
		try {
			if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
				try {
					proxy = startProxy(proxyVmId, 0);
					if (proxy == null) {
						//
						// We had a situation with multi-pod configuration, where
						// storage allocation of the console proxy VM may succeed, but later-on starting of it
						// may fail because of running out of computing resource (CPU/memory). We
						// currently don't support moving storage to another pod on the fly, to deal
						// with the situation we will destroy this proxy VM and let it the whole proxy VM
						// creation process re-start again, by hoping that new storage and computing
						// resource may be allocated and assigned in another pod
						//
						if (s_logger.isInfoEnabled())
							s_logger.info("Unable to start console proxy, proxy vm Id : " + proxyVmId + " will recycle it and restart a new one");
						destroyProxy(proxyVmId, 0);
						return null;
					} else {
						if (s_logger.isTraceEnabled())
							s_logger.trace("Console proxy " + proxy.getName() + " is started");

						// if it is a new assignment or a changed assignment, update the
						// record
						if (vm.getProxyId() == null || vm.getProxyId().longValue() != proxy.getId())
							_instanceDao.updateProxyId(vmId, proxy.getId(), DateUtil.currentGMTTime());

						proxy.setSslEnabled(_sslEnabled);
						if (_sslEnabled)
							proxy.setPort(443);
						else
							proxy.setPort(80);
						return proxy;
					}
				} finally {
					proxyLock.unlock();
				}
			} else {
				s_logger.error("Unable to acquire synchronization lock to start console proxy "
					+ proxyVmId + " for vm: " + vmId + ". It takes too long to start the proxy");
				
				return null;
			}
		} finally {
			proxyLock.releaseRef();
		}
	}

	private ConsoleProxyVO getOrAllocProxyResource(long dataCenterId,
			long vmId, Boolean[] proxyFromStoppedPool) {
		ConsoleProxyVO proxy = null;
		VMInstanceVO vm = this._instanceDao.findById(vmId);

		if (vm != null && vm.getState() != State.Running) {
			if (s_logger.isInfoEnabled())
				s_logger.info("Detected that vm : " + vmId + " is not currently at running state, we will fail the proxy assignment for it");
			return null;
		}

		if (vm != null && vm.getProxyId() != null) {
			proxy = _consoleProxyDao.findById(vm.getProxyId());

			if (proxy != null) {
				if (!isInAssignableState(proxy)) {
					if (s_logger.isInfoEnabled())
						s_logger.info("A previous assigned proxy is not assignable now, reassign console proxy for user vm : " + vmId);
					proxy = null;
				} else {
					if (_consoleProxyDao.getProxyActiveLoad(proxy.getId()) < _capacityPerProxy
							|| hasPreviousSession(proxy, vm)) {
						if (s_logger.isTraceEnabled())
							s_logger.trace("Assign previous allocated console proxy for user vm : " + vmId);

						if (proxy.getActiveSession() >= _capacityPerProxy)
							s_logger.warn("Assign overloaded proxy to user VM as previous session exists, user vm : " + vmId);
					} else {
						proxy = null;
					}
				}
			}
		}

		if (proxy == null)
			proxy = assignProxyFromRunningPool(dataCenterId);

		if (proxy == null) {
			if (s_logger.isInfoEnabled())
				s_logger.info("No running console proxy is available, check to see if we can bring up a stopped one for data center : " + dataCenterId);

			proxy = assignProxyFromStoppedPool(dataCenterId);
			if (proxy == null) {
				if (s_logger.isInfoEnabled())
					final EventVO event = new EventVO();
					s_logger.info("No stopped console proxy is available, need to allocate a new console proxy for data center : " + dataCenterId);

				proxy = startNew(dataCenterId);
			} else {
				if (s_logger.isInfoEnabled())
			s_logger.debug("proxy is not found: " + proxyId);
					s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : "
							+ proxy.getId() + ", data center : " + dataCenterId);

				proxyFromStoppedPool[0] = new Boolean(true);
			}
		}

		return proxy;
	}

	private static boolean isInAssignableState(ConsoleProxyVO proxy) {
		// console proxies that are in states of being able to serve user VM
		State state = proxy.getState();
		if (state == State.Running || state == State.Starting
				|| state == State.Creating || state == State.Migrating)
			return true;

		return false;
	}

	private boolean hasPreviousSession(ConsoleProxyVO proxy, VMInstanceVO vm) {

		ConsoleProxyStatus status = null;
		try {
			GsonBuilder gb = new GsonBuilder();
			gb.setVersion(1.3);
			Gson gson = gb.create();

			byte[] details = proxy.getSessionDetails();
			status = gson.fromJson(details != null ? new String(details,
					Charset.forName("US-ASCII")) : null,
					ConsoleProxyStatus.class);
		} catch (Throwable e) {
			s_logger.warn("Unable to parse proxy session details : "
				+ proxy.getSessionDetails());
		}

		if (status != null && status.getConnections() != null) {
			ConsoleProxyConnectionInfo[] connections = status.getConnections();
			for (int i = 0; i < connections.length; i++) {
				long taggedVmId = 0;
				if (connections[i].tag != null) {
					try {
						taggedVmId = Long.parseLong(connections[i].tag);
					} catch (NumberFormatException e) {
						s_logger.warn(
								"Unable to parse console proxy connection info passed through tag: "
										+ connections[i].tag, e);
					}
				}
				if (taggedVmId == vm.getId())
					return true;
			}

			//
			// even if we are not in the list, it may because we haven't
			// received load-update yet
			// wait until session time
			//
			if (DateUtil.currentGMTTime().getTime() - vm.getProxyAssignTime().getTime() < _proxySessionTimeoutValue)
				return true;

			return false;
		} else {
			s_logger.error("No proxy load info on an overloaded proxy ?");
			return false;
		}
	}

	@Override
	public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) {
		try {
			return start(proxyVmId, startEventId);
		} catch (StorageUnavailableException e) {
			s_logger.warn("Exception while trying to start console proxy", e);
			return null;
		} catch (InsufficientCapacityException e) {
			s_logger.warn("Exception while trying to start console proxy", e);
			return null;
		} catch (ConcurrentOperationException e) {
			s_logger.warn("Exception while trying to start console proxy", e);
			return null;
		}
	}
	
	@Override
	@DB
	public ConsoleProxyVO start(long proxyId, long startEventId)
			throws StorageUnavailableException, InsufficientCapacityException,
			ConcurrentOperationException {

		AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
		if (asyncExecutor != null) {
			AsyncJobVO job = asyncExecutor.getJob();

			if (s_logger.isInfoEnabled())
				s_logger.info("Start console proxy " + proxyId + ", update async job-" + job.getId());
			_asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyId);
		}

		ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId);
		if (proxy == null || proxy.getRemoved() != null) {
			return null;
		}
/*
 		// don't insert event here, it may be called multiple times!
		saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
				EventTypes.EVENT_PROXY_START,
				"Starting console proxy with Id: " + proxyId, startEventId);
*/				

		if (s_logger.isTraceEnabled()) {
			s_logger.trace("Starting console proxy if it is not started, proxy vm id : " + proxyId);
		}

		for (int i = 0; i < 2; i++) {

			State state = proxy.getState();

			if (state == State.Starting /* || state == State.Migrating */) {
				if (s_logger.isDebugEnabled())
					s_logger.debug("Waiting console proxy to be ready, proxy vm id : " + proxyId + " proxy VM state : " + state.toString());

				if (proxy.getPrivateIpAddress() == null || connect(proxy.getPrivateIpAddress(), _proxyCmdPort) != null) {
					if (proxy.getPrivateIpAddress() == null)
						s_logger.warn("Retruning a proxy that is being started but private IP has not been allocated yet, proxy vm id : " + proxyId);
					else
						s_logger.warn("Waiting console proxy to be ready timed out, proxy vm id : " + proxyId);

					// TODO, it is very tricky here, if the startup process
					// takes too long and it timed out here,
					// we may give back a proxy that is not fully ready for
					// functioning
				}
				return proxy;
			}

			if (state == State.Running) {
				if (s_logger.isTraceEnabled())
					s_logger.trace("Console proxy is already started: " + proxy.getName());
				return proxy;
			}

			DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId());
			HostPodVO pod = _podDao.findById(proxy.getPodId());
			List sps = _storageMgr.getStoragePoolsForVm(proxy.getId());
			StoragePoolVO sp = sps.get(0); // FIXME

			HashSet avoid = new HashSet();
			HostVO routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing,
					dc, pod, sp, _serviceOffering, _template, proxy, null,
					avoid);

			if (routingHost == null) {
				if (s_logger.isDebugEnabled()) {
					s_logger.debug("Unable to find a routing host for " + proxy.toString());
					continue;
				}
			}
			// to ensure atomic state transition to Starting state
			if (!_consoleProxyDao.updateIf(proxy, Event.StartRequested, routingHost.getId())) {
				if (s_logger.isDebugEnabled()) {
					ConsoleProxyVO temp = _consoleProxyDao.findById(proxyId);
					s_logger.debug("Unable to start console proxy " + proxy.getName() + " because it is not in a startable state : "
							+ ((temp != null) ? temp.getState().toString() : "null"));
				}
				continue;
			}

			try {
				Answer answer = null;
				int retry = _find_host_retry;

				// Console proxy VM will be running at routing hosts as routing
				// hosts have public access to outside network
				do {
					if (s_logger.isDebugEnabled()) {
						s_logger.debug("Trying to start console proxy on host " + routingHost.getName());
					}

					String privateIpAddress = allocPrivateIpAddress(
							proxy.getDataCenterId(), routingHost.getPodId(),
							proxy.getId(), proxy.getPrivateMacAddress());
					if (privateIpAddress == null && (_IpAllocator != null && !_IpAllocator.exteralIpAddressAllocatorEnabled())) {
						s_logger.debug("Not enough ip addresses in " + routingHost.getPodId());
						avoid.add(routingHost);
						continue;
					}
					
					proxy.setPrivateIpAddress(privateIpAddress);
					event.setUserId(User.UID_SYSTEM);
					String guestIpAddress = _dcDao.allocateLinkLocalPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId());
					proxy.setGuestIpAddress(guestIpAddress);

					_consoleProxyDao.updateIf(proxy, Event.OperationRetry, routingHost.getId());
					proxy = _consoleProxyDao.findById(proxy.getId());

					List vols = _storageMgr.prepare(proxy, routingHost);
					if (vols == null) {
						s_logger.debug("Unable to prepare storage for " + routingHost);
						avoid.add(routingHost);
						continue;
					}

					// _storageMgr.share(proxy, vols, null, true);

					// carry the console proxy port info over so that we don't
					// need to configure agent on this
					StartConsoleProxyCommand cmdStart = new StartConsoleProxyCommand(
							_proxyCmdPort, proxy, proxy.getName(), "", vols,
							Integer.toString(_consoleProxyPort), 
							Integer.toString(_consoleProxyUrlPort),
							_mgmt_host, _mgmt_port, _sslEnabled);

					if (s_logger.isDebugEnabled())
						s_logger.debug("Sending start command for console proxy " + proxy.getName() + " to " + routingHost.getName());
					try {
						answer = _agentMgr.send(routingHost.getId(), cmdStart);
						
						s_logger.debug("StartConsoleProxy Answer: " + (answer != null ? answer : "null"));

						if (s_logger.isDebugEnabled())
							s_logger.debug("Received answer on starting console proxy " + proxy.getName() + " on " + routingHost.getName());

						if (answer != null && answer.getResult()) {
							if (s_logger.isDebugEnabled()) {
								s_logger.debug("Console proxy " + proxy.getName() + " started on " + routingHost.getName());
							}

							if (answer instanceof StartConsoleProxyAnswer) {
								StartConsoleProxyAnswer rAnswer = (StartConsoleProxyAnswer) answer;
								if (rAnswer.getPrivateIpAddress() != null) {
									proxy.setPrivateIpAddress(rAnswer.getPrivateIpAddress());
								}
								if (rAnswer.getPrivateMacAddress() != null) {
									proxy.setPrivateMacAddress(rAnswer.getPrivateMacAddress());
								}
							}

							final EventVO event = new EventVO();
							event.setUserId(User.UID_SYSTEM);
							event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
							event.setType(EventTypes.EVENT_PROXY_START);
							event.setLevel(EventVO.LEVEL_INFO);
							event.setStartId(startEventId);
							event.setDescription("Console proxy started - " + proxy.getName());
							_eventDao.persist(event);
							break;
						}
						s_logger.debug("Unable to start " + proxy.toString() + " on host " + routingHost.toString() + " due to " + answer.getDetails());
					} catch (OperationTimedoutException e) {
						if (e.isActive()) {
							s_logger.debug("Unable to start vm " + proxy.getName() + " due to operation timed out and it is active so scheduling a restart.");
							_haMgr.scheduleRestart(proxy, true);
							return null;
						}
					} catch (AgentUnavailableException e) {
						s_logger.debug("Agent " + routingHost.toString() + " was unavailable to start VM "
							+ proxy.getName());
					}

					avoid.add(routingHost);
					proxy.setPrivateIpAddress(null);
					freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
					proxy.setGuestIpAddress(null);
					_dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId());
					_storageMgr.unshare(proxy, vols, routingHost);
				} while (--retry > 0 && (routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp,
						_serviceOffering, _template, proxy, null, avoid)) != null);
				if (routingHost == null || retry <= 0) {

					SubscriptionMgr.getInstance().notifySubscribers(
							ConsoleProxyManager.ALERT_SUBJECT,
							this, 
							new ConsoleProxyAlertEventArgs(
								ConsoleProxyAlertEventArgs.PROXY_START_FAILURE,
								proxy.getDataCenterId(), proxy.getId(), proxy,
								"Unable to find a routing host to run")
							);

					event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
					event.setType(EventTypes.EVENT_PROXY_START);
					event.setLevel(EventVO.LEVEL_ERROR);
					event.setStartId(startEventId);
					event.setDescription("Starting console proxy failed due to unable to find a host - " + proxy.getName());
					_eventDao.persist(event);
					throw new ExecutionException("Couldn't find a routingHost to run console proxy");
				}

				_consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, routingHost.getId());
				if (s_logger.isDebugEnabled()) {
					s_logger.debug("Console proxy is now started, vm id : " + proxy.getId());
				}

				// If starting the console proxy failed due to the external
				// firewall not being reachable, send an alert.
				if (answer != null && answer.getDetails() != null && answer.getDetails().equals("firewall")) {

					SubscriptionMgr.getInstance().notifySubscribers(
						ConsoleProxyManager.ALERT_SUBJECT,
						this,
						new ConsoleProxyAlertEventArgs(
							ConsoleProxyAlertEventArgs.PROXY_FIREWALL_ALERT,
							proxy.getDataCenterId(), proxy
							.getId(), proxy, null)
						);
				}

				SubscriptionMgr.getInstance().notifySubscribers(
					ConsoleProxyManager.ALERT_SUBJECT,
					this,
					new ConsoleProxyAlertEventArgs(
						ConsoleProxyAlertEventArgs.PROXY_UP, proxy.getDataCenterId(), proxy.getId(),
						proxy, null)
					);

				return proxy;
			} catch (Throwable thr) {
				s_logger.warn("Unexpected exception: ", thr);

				SubscriptionMgr.getInstance().notifySubscribers(
						ConsoleProxyManager.ALERT_SUBJECT,
						this,
						new ConsoleProxyAlertEventArgs(
							ConsoleProxyAlertEventArgs.PROXY_START_FAILURE,
							proxy.getDataCenterId(), proxy.getId(), proxy,
							"Unexpected exception: " + thr.getMessage()));

/*				
				final EventVO event = new EventVO();
				event.setUserId(User.UID_SYSTEM);
				event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
				event.setType(EventTypes.EVENT_PROXY_START);
				event.setLevel(EventVO.LEVEL_ERROR);
				event.setStartId(startEventId);
				event.setDescription("Starting console proxy failed due to unhandled exception - "
					+ proxy.getName());
				_eventDao.persist(event);
*/				

				Transaction txn = Transaction.currentTxn();
				try {
					txn.start();
					String privateIpAddress = proxy.getPrivateIpAddress();
					if (privateIpAddress != null) {
						proxy.setPrivateIpAddress(null);
						freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
					}

					_consoleProxyDao.updateIf(proxy, Event.OperationFailed, null);
					txn.commit();
				} catch (Exception e) {
					s_logger.error("Caught exception during error recovery");
				}

				if (thr instanceof StorageUnavailableException) {
					throw (StorageUnavailableException) thr;
				} else if (thr instanceof ConcurrentOperationException) {
					throw (ConcurrentOperationException) thr;
				} else if (thr instanceof ExecutionException) {
					s_logger.error("Error while starting console proxy due to " + thr.getMessage());
				} else {
					s_logger.error("Error while starting console proxy ", thr);
				}
				return null;
			}
		}

		s_logger.warn("Starting console proxy encounters non-startable situation");
		return null;
	}

	public ConsoleProxyVO assignProxyFromRunningPool(long dataCenterId) {

		if (s_logger.isTraceEnabled())
			s_logger.trace("Assign console proxy from running pool for request from data center : " + dataCenterId);


		ConsoleProxyAllocator allocator = getCurrentAllocator();
		assert (allocator != null);
		List runningList = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Running);
		if (runningList != null && runningList.size() > 0) {
			if (s_logger.isTraceEnabled()) {
				s_logger.trace("Running proxy pool size : "
						+ runningList.size());
				for (ConsoleProxyVO proxy : runningList)
					s_logger.trace("Running proxy instance : "
							+ proxy.getName());
			}

			List> l = _consoleProxyDao.getProxyLoadMatrix();
			Map loadInfo = new HashMap();
			if (l != null) {
				for (Pair p : l) {
					loadInfo.put(p.first(), p.second());

					if (s_logger.isTraceEnabled()) {
						s_logger.trace("Running proxy instance allocation load { proxy id : "
							+ p.first() + ", load : " + p.second() + "}");
					}
				}
			}
			return allocator.allocProxy(runningList, loadInfo, dataCenterId);
		} else {
			if (s_logger.isTraceEnabled())
				s_logger.trace("Empty running proxy pool for now in data center : " + dataCenterId);
		}
		return null;
	}

	public ConsoleProxyVO assignProxyFromStoppedPool(long dataCenterId) {
		List l = _consoleProxyDao.getProxyListInStates(
				dataCenterId, State.Creating, State.Starting, State.Stopped,
				State.Migrating);
		if (l != null && l.size() > 0)
			return l.get(0);

		return null;
	}

	public ConsoleProxyVO startNew(long dataCenterId) {

		if (s_logger.isDebugEnabled())
			s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId);

		Map context = createProxyInstance(dataCenterId);

		long proxyVmId = (Long) context.get("proxyVmId");
		if (proxyVmId == 0) {
			if (s_logger.isTraceEnabled())
				s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId);

			// release critical system resource on failure
			if (context.get("publicIpAddress") != null)
				freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0);

			return null;
		}

		ConsoleProxyVO proxy = allocProxyStorage(dataCenterId, proxyVmId);
		if (proxy != null) {
			SubscriptionMgr.getInstance().notifySubscribers(
					ConsoleProxyManager.ALERT_SUBJECT,
					this,
					new ConsoleProxyAlertEventArgs(
							ConsoleProxyAlertEventArgs.PROXY_CREATED,
							dataCenterId, proxy.getId(), proxy, null));
			return proxy;
		} else {
			if (s_logger.isDebugEnabled())
				s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId);

			SubscriptionMgr.getInstance().notifySubscribers(
					ConsoleProxyManager.ALERT_SUBJECT,
					this,
					new ConsoleProxyAlertEventArgs(
							ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE,
							dataCenterId, proxyVmId, null,
							"Unable to allocate storage"));

			destroyProxyDBOnly(proxyVmId);
		}
		return null;
	}

	@DB
	protected Map createProxyInstance(long dataCenterId) {

		Map context = new HashMap();
		String publicIpAddress = null;

		Transaction txn = Transaction.currentTxn();
		try {
			DataCenterVO dc = _dcDao.findById(dataCenterId);
			assert (dc != null);
			context.put("dc", dc);

			// this will basically allocate the pod based on data center id as
			// we use system user id here
			Set avoidPods = new HashSet();
			Pair pod = null;
			networkInfo publicIpAndVlan = null;
			
			// About MAC address allocation
			// MAC address used by User VM is inherited from DomR MAC address,
			// with the least 16 bits overrided. to avoid
			// potential conflicts, domP will mask bit 31
			//
			String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31));
			String privateMacAddress = macAddresses[0];
			String publicMacAddress = macAddresses[1];
			macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31));
			String guestMacAddress = macAddresses[0];
			while ((pod = _agentMgr.findPod(_template, _serviceOffering, dc,
					Account.ACCOUNT_ID_SYSTEM, avoidPods)) != null) {
				publicIpAndVlan = allocPublicIpAddress(dataCenterId, pod.first().getId(), publicMacAddress);
				if (publicIpAndVlan == null) {
					s_logger.warn("Unable to allocate public IP address for console proxy vm in data center : "
						+ dataCenterId + ", pod=" + pod.first().getId());
					avoidPods.add(pod.first().getId());
				} else {
					break;
				}
			}

			if (pod == null || publicIpAndVlan == null) {
				s_logger.warn("Unable to allocate pod for console proxy vm in data center : " + dataCenterId);

				context.put("proxyVmId", (long) 0);
				return context;
			}
			
			long id = _consoleProxyDao.getNextInSequence(Long.class, "id");

			context.put("publicIpAddress", publicIpAndVlan._ipAddr);
			context.put("pod", pod);
			if (s_logger.isDebugEnabled()) {
				s_logger.debug("Pod allocated " + pod.first().getName());
			}

			String cidrNetmask = NetUtils.getCidrNetmask(pod.first().getCidrSize());

			// Find the VLAN ID, VLAN gateway, and VLAN netmask for
			// publicIpAddress
			publicIpAddress = publicIpAndVlan._ipAddr;
			
			String vlanGateway = publicIpAndVlan._gateWay;
			String vlanNetmask = publicIpAndVlan._netMask;

			txn.start();
			ConsoleProxyVO proxy;
			String name = VirtualMachineName.getConsoleProxyName(id, _instance).intern();
			proxy = new ConsoleProxyVO(id, name, guestMacAddress, null, NetUtils.getLinkLocalNetMask(),
					privateMacAddress, null, cidrNetmask, _template.getId(),
					_template.getGuestOSId(), publicMacAddress,
					publicIpAddress, vlanNetmask, publicIpAndVlan._vlanDbId, publicIpAndVlan._vlanid, pod.first().getId(), dataCenterId,
					vlanGateway, null, dc.getDns1(), dc.getDns2(), _domain,
					_proxyRamSize, 0);
			
			proxy.setLastHostId(pod.second());
			proxy = _consoleProxyDao.persist(proxy);
			long proxyVmId = proxy.getId();

			final EventVO event = new EventVO();
			event.setUserId(User.UID_SYSTEM);
			event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
			event.setType(EventTypes.EVENT_PROXY_CREATE);
			event.setLevel(EventVO.LEVEL_INFO);
			event.setDescription("New console proxy created - "
					+ proxy.getName());
			_eventDao.persist(event);
			txn.commit();

			context.put("proxyVmId", proxyVmId);
			return context;
		} catch (Throwable e) {
			s_logger.error("Unexpected exception : ", e);

			context.put("proxyVmId", (long) 0);
			return context;
		}
	}

	@DB
	protected ConsoleProxyVO allocProxyStorage(long dataCenterId, long proxyVmId) {
		ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
		assert (proxy != null);

		DataCenterVO dc = _dcDao.findById(dataCenterId);
		HostPodVO pod = _podDao.findById(proxy.getPodId());
		final AccountVO account = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM);

		try {

			List vols = _storageMgr.create(account, proxy, _template, dc, pod, _serviceOffering, null,0);
			if (vols == null) {
				s_logger.error("Unable to alloc storage for console proxy");
				return null;
			}

			Transaction txn = Transaction.currentTxn();
			txn.start();

			// update pool id
			ConsoleProxyVO vo = _consoleProxyDao.findById(proxy.getId());
			_consoleProxyDao.update(proxy.getId(), vo);

			// kick the state machine
			_consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, null);

			txn.commit();
			return proxy;
		} catch (StorageUnavailableException e) {
			s_logger.error("Unable to alloc storage for console proxy: ", e);
			return null;
		} catch (ExecutionException e) {
			s_logger.error("Unable to alloc storage for console proxy: ", e);
			return null;
		}
	}

	private networkInfo allocPublicIpAddress(long dcId, long podId, String macAddr) {
		
		if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
			IpAddrAllocator.IpAddr ip = _IpAllocator.getPublicIpAddress(macAddr, dcId, podId);
			networkInfo net = new networkInfo(ip.ipaddr, ip.netMask, ip.gateway, null, "untagged");
			return net;
		}

		Pair ipAndVlan = _vlanDao.assignIpAddress(dcId,
				Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN,
				VlanType.VirtualNetwork, true);

		if (ipAndVlan == null) {
			s_logger.debug("Unable to get public ip address (type=Virtual) for console proxy vm for data center  : " + dcId);
			ipAndVlan = _vlanDao.assignPodDirectAttachIpAddress(dcId, podId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN);
			if (ipAndVlan == null)
				s_logger.debug("Unable to get public ip address (type=DirectAttach) for console proxy vm for data center  : " + dcId);
		}
		if (ipAndVlan != null) {
			VlanVO vlan = ipAndVlan.second();
			networkInfo net = new networkInfo(ipAndVlan.first(), vlan.getVlanNetmask(), vlan.getVlanGateway(), vlan.getId(), vlan.getVlanId());
			return net;
		}
		return null;
	}

	private String allocPrivateIpAddress(Long dcId, Long podId, Long proxyId, String macAddr) {
		if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
			return _IpAllocator.getPrivateIpAddress(macAddr, dcId, podId).ipaddr;
		} else {
			return _dcDao.allocatePrivateIpAddress(dcId, podId, proxyId);
		}
	}
	
	private void freePrivateIpAddress(String ipAddress, Long dcId, Long podId) {
		if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
			 _IpAllocator.releasePrivateIpAddress(ipAddress, dcId, podId);
		} else {
			_dcDao.releasePrivateIpAddress(ipAddress, dcId, podId);
		}
	}
	
	private void freePublicIpAddress(String ipAddress, long dcId, long podId) {
		if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
			 _IpAllocator.releasePublicIpAddress(ipAddress, dcId, podId);
		} else {
			_ipAddressDao.unassignIpAddress(ipAddress);
		}
	}

	private ConsoleProxyAllocator getCurrentAllocator() {
		// for now, only one adapter is supported
		Enumeration it = _consoleProxyAllocators.enumeration();
		if (it.hasMoreElements())
			return it.nextElement();

		return null;
	}

	protected String connect(String ipAddress, int port) {
		for (int i = 0; i <= _ssh_retry; i++) {
			SocketChannel sch = null;
			try {
				if (s_logger.isDebugEnabled()) {
					s_logger.debug("Trying to connect to " + ipAddress);
				}
				sch = SocketChannel.open();
				sch.configureBlocking(true);
				sch.socket().setSoTimeout(5000);
				InetSocketAddress addr = new InetSocketAddress(ipAddress, port);
				sch.connect(addr);
				return null;
			} catch (IOException e) {
				if (s_logger.isDebugEnabled()) {
					s_logger.debug("Could not connect to " + ipAddress);
				}
			} finally {
				if (sch != null) {
					try {
						sch.close();
					} catch (IOException e) {
					}
				}
			}
			try {
				Thread.sleep(_ssh_sleep);
			} catch (InterruptedException ex) {
			}
		}

		s_logger.debug("Unable to logon to " + ipAddress);

		return "Unable to connect";
	}

	public void onLoadAnswer(ConsoleProxyLoadAnswer answer) {
		if (answer.getDetails() == null)
			return;

		ConsoleProxyStatus status = null;
		try {
			GsonBuilder gb = new GsonBuilder();
			gb.setVersion(1.3);
			Gson gson = gb.create();
			status = gson.fromJson(answer.getDetails(), ConsoleProxyStatus.class);
		} catch (Throwable e) {
			s_logger.warn("Unable to parse load info from proxy, proxy vm id : "
					+ answer.getProxyVmId() + ", info : " + answer.getDetails());
		}

		if (status != null) {
			int count = 0;
			if (status.getConnections() != null)
				count = status.getConnections().length;

			byte[] details = null;
			if (answer.getDetails() != null)
				details = answer.getDetails().getBytes(Charset.forName("US-ASCII"));
			_consoleProxyDao.update(answer.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
		} else {
			if (s_logger.isTraceEnabled())
				s_logger.trace("Unable to get console proxy load info, id : " + answer.getProxyVmId());

			_consoleProxyDao.update(answer.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
			// TODO : something is wrong with the VM, restart it?
		}
	}

	public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
		if (cmd.getLoadInfo() == null)
			return;

		ConsoleProxyStatus status = null;
		try {
			GsonBuilder gb = new GsonBuilder();
			gb.setVersion(1.3);
			Gson gson = gb.create();
			status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class);
		} catch (Throwable e) {
			s_logger.warn("Unable to parse load info from proxy, proxy vm id : "
				+ cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo());
		}

		if (status != null) {
			int count = 0;
			if (status.getConnections() != null)
				count = status.getConnections().length;

			byte[] details = null;
			if (cmd.getLoadInfo() != null)
				details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII"));
			_consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
		} else {
			if (s_logger.isTraceEnabled())
				s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId());

			_consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
		}
	}

	public AgentControlAnswer onConsoleAccessAuthentication(
			ConsoleAccessAuthenticationCommand cmd) {
		long vmId = 0;

		if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
			if (s_logger.isTraceEnabled())
				s_logger.trace("Invalid vm id sent from proxy(happens when proxy session has terminated)");
			return new ConsoleAccessAuthenticationAnswer(cmd, false);
		}

		try {
			vmId = Long.parseLong(cmd.getVmId());
	}
		} catch (NumberFormatException e) {
			s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication", e);
			return new ConsoleAccessAuthenticationAnswer(cmd, false);
		}

		// TODO authentication channel between console proxy VM and management
		// server needs to be secured,
		// the data is now being sent through private network, but this is
		// apparently not enough
		VMInstanceVO vm = _instanceDao.findById(vmId);
		if (vm == null) {
			return new ConsoleAccessAuthenticationAnswer(cmd, false);
		}

		if (vm.getHostId() == null) {
			s_logger.warn("VM " + vmId + " lost host info, failed authentication request");
			return new ConsoleAccessAuthenticationAnswer(cmd, false);
		}

		HostVO host = _hostDao.findById(vm.getHostId());
		if (host == null) {
			s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request");
			return new ConsoleAccessAuthenticationAnswer(cmd, false);
		}

		String sid = cmd.getSid();
		if (sid == null || !sid.equals(vm.getVncPassword())) {
			s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
			return new ConsoleAccessAuthenticationAnswer(cmd, false);
		}

		return new ConsoleAccessAuthenticationAnswer(cmd, true);
	}

	private ConsoleProxyVO findConsoleProxyByHost(HostVO host) throws NumberFormatException {
		String name = host.getName();
		long proxyVmId = 0;
		ConsoleProxyVO proxy = null;
		if (name != null && name.startsWith("v-")) {
			String[] tokens = name.split("-");
			proxyVmId = Long.parseLong(tokens[1]);
			proxy = this._consoleProxyDao.findById(proxyVmId);
		}
		return proxy;
	}
	@Override
	public void onAgentConnect(HostVO host, StartupCommand cmd) {
		if (host.getType() == Type.ConsoleProxy) {
			// TODO we can use this event to mark the proxy is up and
			// functioning instead of
			// pinging the console proxy VM command port
			//
			// for now, just log a message
			if (s_logger.isInfoEnabled())
				s_logger.info("Console proxy agent is connected. proxy: " + host.getName());
			
			/* update public/private ip address */
			if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
				try {
					ConsoleProxyVO console = findConsoleProxyByHost(host);
					if (console == null) {
						s_logger.debug("Can't find console proxy ");
						return;
					}
					console.setPrivateIpAddress(cmd.getPrivateIpAddress());
					console.setPrivateNetmask(cmd.getPrivateNetmask());
					console.setPublicIpAddress(cmd.getPublicIpAddress());
					console.setPublicNetmask(cmd.getPublicNetmask());
					_consoleProxyDao.persist(console);
				} catch (NumberFormatException e) {
				}
			}
		}
	}

	@Override
	public void onAgentDisconnect(long agentId, com.cloud.host.Status state) {
		if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) {
			// be it either in alert or in disconnected state, the agent process
			// may be gone in the VM,
			// we will be reacting to stop the corresponding VM and let the scan
			// process to
			HostVO host = _hostDao.findById(agentId);
			if (host.getType() == Type.ConsoleProxy) {
				String name = host.getName();
				if (s_logger.isInfoEnabled())
					s_logger.info("Console proxy agent disconnected, proxy: " + name);
				if (name != null && name.startsWith("v-")) {
					String[] tokens = name.split("-");
					long proxyVmId = 0;
					try {
						proxyVmId = Long.parseLong(tokens[1]);
					} catch (NumberFormatException e) {
						s_logger.error("Unexpected exception " + e.getMessage(), e);
						return;
					}
					final ConsoleProxyVO proxy = this._consoleProxyDao.findById(proxyVmId);
					if (proxy != null) {
						Long hostId = proxy.getHostId();

						// Disable this feature for now, as it conflicts with
						// the case of allowing user to reboot console proxy
						// when rebooting happens, we will receive disconnect
						// here and we can't enter into stopping process,
						// as when the rebooted one comes up, it will kick off a
						// newly started one and trigger the process
						// continue on forever

						/*
						 * _capacityScanScheduler.execute(new Runnable() {
						 * public void run() { if(s_logger.isInfoEnabled())
						 * s_logger.info("Stop console proxy " + proxy.getName()
						 * +
						 * " VM because of that the agent running inside it has disconnected"
						 * ); stopProxy(proxy.getId()); } });
						 */
					} else {
						if (s_logger.isInfoEnabled())
							s_logger.info("Console proxy agent disconnected but corresponding console proxy VM no longer exists in DB, proxy: " + name);
					}
				} else {
					assert (false) : "Invalid console proxy name: " + name;
				}
			}
		}
	}

	private void checkPendingProxyVMs() {
		// drive state to change away from transient states
		List l = _consoleProxyDao.getProxyListInStates(State.Creating);
		if (l != null && l.size() > 0) {
			for (ConsoleProxyVO proxy : l) {
				if (proxy.getLastUpdateTime() == null
						|| (proxy.getLastUpdateTime() != null && System.currentTimeMillis() - proxy.getLastUpdateTime().getTime() > 60000)) {
					try {
						ConsoleProxyVO readyProxy = null;
						if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
							try {
								readyProxy = allocProxyStorage(proxy.getDataCenterId(), proxy.getId());
							} finally {
								_allocProxyLock.unlock();
							}

							if (readyProxy != null) {
								GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(readyProxy.getId()));
								try {
									if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
										try {
											readyProxy = start(readyProxy.getId(), 0);
										} finally {
											proxyLock.unlock();
										}
									} else {
										if (s_logger.isInfoEnabled())
											s_logger.info("Unable to acquire synchronization lock to start console proxy : " + readyProxy.getName());
									}
								} finally {
									proxyLock.releaseRef();
								}
							}
						} else {
							if (s_logger.isInfoEnabled())
								s_logger.info("Unable to acquire synchronization lock to allocate proxy storage, wait for next turn");
						}
					} catch (StorageUnavailableException e) {
						s_logger.warn("Storage unavailable", e);
					} catch (InsufficientCapacityException e) {
						s_logger.warn("insuffiient capacity", e);
					} catch (ConcurrentOperationException e) {
						s_logger.debug("Concurrent operation: "
								+ e.getMessage());
					}
				}
			}
		}
	}

	private Runnable getCapacityScanTask() {
		return new Runnable() {

			@Override
			public void run() {
				Transaction txn = Transaction.open(Transaction.CLOUD_DB);
				try {
					reallyRun();
				} catch (Throwable e) {
					s_logger.warn("Unexpected exception " + e.getMessage(), e);
				} finally {
					StackMaid.current().exitCleanup();
					txn.close();
				}
			}

			private void reallyRun() {
				if (s_logger.isTraceEnabled())

					s_logger.trace("Begin console proxy capacity scan");

				// config var for consoleproxy.restart check
				String restart = _configDao.getValue("consoleproxy.restart");
				if(restart != null && restart.equalsIgnoreCase("false"))
				{
					s_logger.debug("Capacity scan disabled purposefully, consoleproxy.restart = false. This happens when the primarystorage is in maintenance mode");
					return;
				}
					
				Map zoneHostInfoMap = getZoneHostInfo();
				if (isServiceReady(zoneHostInfoMap)) {
					if (s_logger.isTraceEnabled())
						s_logger.trace("Service is ready, check to see if we need to allocate standby capacity");

					if (!_capacityScanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
						if (s_logger.isTraceEnabled())
							s_logger.trace("Capacity scan lock is used by others, skip and wait for my turn");
						return;
					}

					if (s_logger.isTraceEnabled())
						s_logger.trace("*** Begining capacity scan... ***");

					try {
						checkPendingProxyVMs();

						// scan default data center first
						long defaultId = 0;

						// proxy count info by data-centers (zone-id, zone-name,
						// count)
						List l = _consoleProxyDao.getDatacenterProxyLoadMatrix();

						// running VM session count by data-centers (zone-id,
						// zone-name, count)
						List listVmCounts = _consoleProxyDao.getDatacenterSessionLoadMatrix();

						// indexing load info by data-center id
						Map mapVmCounts = new HashMap();
						if (listVmCounts != null)
							for (ConsoleProxyLoadInfo info : listVmCounts)
								mapVmCounts.put(info.getId(), info);

						for (ConsoleProxyLoadInfo info : l) {
							if (info.getName().equals(_instance)) {
								ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId());

								if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) {
									if (isZoneReady(zoneHostInfoMap, info.getId())) {
										allocCapacity(info.getId());
									} else {
										if (s_logger.isTraceEnabled())
											s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy");
									}
								}

								defaultId = info.getId();
								break;
							}
						}

						// scan rest of data-centers
						for (ConsoleProxyLoadInfo info : l) {
							if (info.getId() != defaultId) {
								ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId());

								if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) {
									if (isZoneReady(zoneHostInfoMap, info.getId())) {
										allocCapacity(info.getId());
									} else {
										if (s_logger.isTraceEnabled())
											s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy");
									}
								}
							}
						}

						if (s_logger.isTraceEnabled())
							s_logger.trace("*** Stop capacity scan ***");
					} finally {
						_capacityScanLock.unlock();
					}

				} else {
					if (s_logger.isTraceEnabled())
						s_logger.trace("Service is not ready for capacity preallocation, wait for next time");
				}

				if (s_logger.isTraceEnabled())
					s_logger.trace("End of console proxy capacity scan");
			}
		};
	}

	private boolean checkCapacity(ConsoleProxyLoadInfo proxyCountInfo,
			ConsoleProxyLoadInfo vmCountInfo) {

		if (proxyCountInfo.getCount() * _capacityPerProxy
				- vmCountInfo.getCount() <= _standbyCapacity)
			return false;

		return true;
	}

			}
	private void allocCapacity(long dataCenterId) {
		if (s_logger.isTraceEnabled())
			s_logger.trace("Allocate console proxy standby capacity for data center : " + dataCenterId);

		boolean proxyFromStoppedPool = false;
		ConsoleProxyVO proxy = assignProxyFromStoppedPool(dataCenterId);
		if (proxy == null) {
			if (s_logger.isInfoEnabled())
				s_logger.info("No stopped console proxy is available, need to allocate a new console proxy");

			if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
				try {
					proxy = startNew(dataCenterId);
				} finally {
					_allocProxyLock.unlock();
				}
			} else {
				if (s_logger.isInfoEnabled())
					s_logger.info("Unable to acquire synchronization lock to allocate proxy resource for standby capacity, wait for next scan");
				return;
			}
		} else {
			if (s_logger.isInfoEnabled())
				s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId());
			proxyFromStoppedPool = true;
		}

		if (proxy != null) {
			long proxyVmId = proxy.getId();
			GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId));
			try {
				if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
					try {
						proxy = startProxy(proxyVmId, 0);
					} finally {
						proxyLock.unlock();
					}
				} else {
					if (s_logger.isInfoEnabled())
						s_logger.info("Unable to acquire synchronization lock to start proxy for standby capacity, proxy vm id : " + proxy.getId());
					return;
				}
			} finally {
				proxyLock.releaseRef();
			}

			if (proxy == null) {
				if (s_logger.isInfoEnabled())
					s_logger.info("Unable to start console proxy for standby capacity, proxy vm Id : "
									+ proxyVmId + ", will recycle it and start a new one");

				if (proxyFromStoppedPool)
					destroyProxy(proxyVmId, 0);
			} else {
				if (s_logger.isInfoEnabled())
					s_logger.info("Console proxy " + proxy.getName() + " is started");
			}
		}
	}

	public boolean isServiceReady(Map zoneHostInfoMap) {
		for (ZoneHostInfo zoneHostInfo : zoneHostInfoMap.values()) {
			if (isZoneHostReady(zoneHostInfo)) {
				if (s_logger.isInfoEnabled())
					s_logger.info("Zone " + zoneHostInfo.getDcId() + " is ready to launch");
				return true;
			}
		}

		return false;
	}

	public boolean isZoneReady(Map zoneHostInfoMap,
			long dataCenterId) {
		ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
		if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
			VMTemplateVO template = _templateDao.findConsoleProxyTemplate();
			HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(dataCenterId);
			boolean templateReady = false;

			if (template != null && secondaryStorageHost != null) {
				VMTemplateHostVO templateHostRef = _vmTemplateHostDao.findByHostTemplate(secondaryStorageHost.getId(), template.getId());
				templateReady = (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED);
			}

			if (templateReady) {
				List> l = _consoleProxyDao.getDatacenterStoragePoolHostInfo(dataCenterId, _use_lvm);
				if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) {
					return true;
				} else {
					if (s_logger.isTraceEnabled())
						s_logger.trace("Primary storage is not ready, wait until it is ready to launch console proxy");
				}
			} else {
				if (s_logger.isTraceEnabled())
					s_logger.trace("Zone host is ready, but console proxy template is not ready");
		}
		return false;
	}

	private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) {
		int expectedFlags = 0;
		if (_use_storage_vm)
			expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK;
		else
			expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ALL_HOST_MASK;

		return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags;
	}

	private synchronized Map getZoneHostInfo() {
		Date cutTime = DateUtil.currentGMTTime();
		List l = _hostDao.getRunningHostCounts(new Date(cutTime.getTime() - ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD));

		RunningHostInfoAgregator aggregator = new RunningHostInfoAgregator();
		if (l.size() > 0)
			for (RunningHostCountInfo countInfo : l)
				aggregator.aggregate(countInfo);

		return aggregator.getZoneHostInfoMap();
	}

	@Override
	public String getName() {
		return _name;
	}

	@Override
	public boolean start() {
		if (s_logger.isInfoEnabled())
			s_logger.info("Start console proxy manager");

		return true;
	}

	@Override
	public boolean stop() {
		if (s_logger.isInfoEnabled())
			s_logger.info("Stop console proxy manager");
		_capacityScanScheduler.shutdownNow();

		try {
			_capacityScanScheduler.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT,
					TimeUnit.MILLISECONDS);
		} catch (InterruptedException e) {
		}

		_capacityScanLock.releaseRef();
		_allocProxyLock.releaseRef();
		return true;
	}

	@Override
	public boolean configure(String name, Map params)
			throws ConfigurationException {
		if (s_logger.isInfoEnabled())
			s_logger.info("Start configuring console proxy manager : " + name);

		_name = name;

		ComponentLocator locator = ComponentLocator.getCurrentLocator();
		ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
		if (configDao == null) {
			throw new ConfigurationException(
					"Unable to get the configuration dao.");
		}

		Map configs = configDao.getConfiguration(
				"management-server", params);

		_proxyRamSize = NumbersUtil.parseInt(configs
				.get("consoleproxy.ram.size"), DEFAULT_PROXY_VM_RAMSIZE);

		String value = configs.get("start.retry");
		_find_host_retry = NumbersUtil.parseInt(value,
				DEFAULT_FIND_HOST_RETRY_COUNT);

		value = configs.get("consoleproxy.cmd.port");
		_proxyCmdPort = NumbersUtil.parseInt(value, DEFAULT_PROXY_CMD_PORT);

		value = configs.get("consoleproxy.sslEnabled");
		if (value != null && value.equalsIgnoreCase("true"))
			_sslEnabled = true;

		value = configs.get("consoleproxy.capacityscan.interval");
		_capacityScanInterval = NumbersUtil.parseLong(value, DEFAULT_CAPACITY_SCAN_INTERVAL);

		_capacityPerProxy = NumbersUtil.parseInt(configs.get("consoleproxy.session.max"), DEFAULT_PROXY_CAPACITY);
		_standbyCapacity = NumbersUtil.parseInt(configs.get("consoleproxy.capacity.standby"), DEFAULT_STANDBY_CAPACITY);
		_proxySessionTimeoutValue = NumbersUtil.parseInt(configs.get("consoleproxy.session.timeout"), DEFAULT_PROXY_SESSION_TIMEOUT);

	@Override
		value = configs.get("consoleproxy.port");
		if (value != null)
			_consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT);

		value = configs.get("consoleproxy.url.port");
		if (value != null)
			_consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT);

		value = configs.get("system.vm.use.local.storage");
		if (value != null && value.equalsIgnoreCase("true"))
			_use_lvm = true;

		value = configs.get("secondary.storage.vm");
		if (value != null && value.equalsIgnoreCase("true"))
			_use_storage_vm = true;

		if (s_logger.isInfoEnabled()) {
			s_logger.info("Console proxy max session soft limit : " + _capacityPerProxy);
			s_logger.info("Console proxy standby capacity : " + _standbyCapacity);
		}

		_domain = configs.get("domain");
		if (_domain == null) {
			_domain = "foo.com";
		}

		_instance = configs.get("instance.name");
		if (_instance == null) {
			_instance = "DEFAULT";
		}

		value = (String) params.get("ssh.sleep");
		_ssh_sleep = NumbersUtil.parseInt(value, 5) * 1000;

		value = (String) params.get("ssh.retry");
		_ssh_retry = NumbersUtil.parseInt(value, 3);

		Map agentMgrConfigs = configDao.getConfiguration("AgentManager", params);
		_mgmt_host = agentMgrConfigs.get("host");
		if (_mgmt_host == null) {
			s_logger.warn("Critical warning! Please configure your management server host address right after you have started your management server and then restart it, otherwise you won't be able to do console access");
		}

		value = agentMgrConfigs.get("port");
		_mgmt_port = NumbersUtil.parseInt(value, 8250);

		_consoleProxyDao = locator.getDao(ConsoleProxyDao.class);
		if (_consoleProxyDao == null) {
			throw new ConfigurationException("Unable to get " + ConsoleProxyDao.class.getName());
		}

		_consoleProxyAllocators = locator.getAdapters(ConsoleProxyAllocator.class);
		if (_consoleProxyAllocators == null || !_consoleProxyAllocators.isSet()) {
			throw new ConfigurationException("Unable to get proxy allocators");
		}

		_dcDao = locator.getDao(DataCenterDao.class);
		if (_dcDao == null) {
			throw new ConfigurationException("Unable to get " + DataCenterDao.class.getName());
		}

		_templateDao = locator.getDao(VMTemplateDao.class);
		if (_templateDao == null) {
			throw new ConfigurationException("Unable to get " + VMTemplateDao.class.getName());
		}

		_ipAddressDao = locator.getDao(IPAddressDao.class);
		if (_ipAddressDao == null) {
			throw new ConfigurationException("Unable to get " + IPAddressDao.class.getName());
		}

		_volsDao = locator.getDao(VolumeDao.class);
		if (_volsDao == null) {
			throw new ConfigurationException("Unable to get " + VolumeDao.class.getName());
		}

		_podDao = locator.getDao(HostPodDao.class);
		if (_podDao == null) {
			throw new ConfigurationException("Unable to get " + HostPodDao.class.getName());
		}

		_hostDao = locator.getDao(HostDao.class);
		if (_hostDao == null) {
			throw new ConfigurationException("Unable to get " + HostDao.class.getName());
		}

		_eventDao = locator.getDao(EventDao.class);
		if (_eventDao == null) {
			throw new ConfigurationException("Unable to get " + EventDao.class.getName());
		}

		_storagePoolDao = locator.getDao(StoragePoolDao.class);
		if (_storagePoolDao == null) {
			throw new ConfigurationException("Unable to find " + StoragePoolDao.class);
		}
		
		_configDao = locator.getDao(ConfigurationDao.class);
		if (_configDao == null) {
			throw new ConfigurationException("Unable to find " + ConfigurationDao.class);
		}

		_vmTemplateHostDao = locator.getDao(VMTemplateHostDao.class);
		if (_vmTemplateHostDao == null) {
			throw new ConfigurationException("Unable to get " + VMTemplateHostDao.class.getName());
		}

		_instanceDao = locator.getDao(VMInstanceDao.class);
		if (_instanceDao == null)
			throw new ConfigurationException("Unable to get " + VMInstanceDao.class.getName());

		_capacityDao = locator.getDao(CapacityDao.class);
		if (_capacityDao == null) {
			throw new ConfigurationException("Unable to get " + CapacityDao.class.getName());
		}

		_haDao = locator.getDao(HighAvailabilityDao.class);
		if (_haDao == null) {
			throw new ConfigurationException("Unable to get " + HighAvailabilityDao.class.getName());
		}

		_accountDao = locator.getDao(AccountDao.class);
		if (_accountDao == null) {
			throw new ConfigurationException("Unable to get " + AccountDao.class.getName());
		}

		_vlanDao = locator.getDao(VlanDao.class);
		if (_vlanDao == null) {
			throw new ConfigurationException("Unable to get " + VlanDao.class.getName());
		}

		_agentMgr = locator.getManager(AgentManager.class);
		if (_agentMgr == null) {
			throw new ConfigurationException("Unable to get " + AgentManager.class.getName());
		}

		_networkMgr = locator.getManager(NetworkManager.class);
		if (_networkMgr == null) {
			throw new ConfigurationException("Unable to get " + NetworkManager.class.getName());
		}

		_listener = new ConsoleProxyListener(this);
		_agentMgr.registerForHostEvents(_listener, true, true, false);

		_haMgr = locator.getManager(HighAvailabilityManager.class);
		if (_haMgr == null) {
			throw new ConfigurationException("Unable to get "
					+ HighAvailabilityManager.class.getName());
		}

		_storageMgr = locator.getManager(StorageManager.class);
		if (_storageMgr == null) {
			throw new ConfigurationException("Unable to get "
					+ StorageManager.class.getName());
		}

		_asyncMgr = locator.getManager(AsyncJobManager.class);
		if (_asyncMgr == null) {
			throw new ConfigurationException("Unable to get "
					+ AsyncJobManager.class.getName());
		}
		
		Adapters ipAllocators = locator.getAdapters(IpAddrAllocator.class);
		if (ipAllocators != null && ipAllocators.isSet()) {
			Enumeration it = ipAllocators.enumeration();
			_IpAllocator = it.nextElement();
		}

		HighAvailabilityManager haMgr = locator.getManager(HighAvailabilityManager.class);
		if (haMgr != null) {
			haMgr.registerHandler(VirtualMachine.Type.ConsoleProxy, this);
		}

		boolean useLocalStorage = Boolean.parseBoolean((String) params.get(Config.SystemVMUseLocalStorage.key()));
		_serviceOffering = new ServiceOfferingVO("Fake Offering For DomP", 1,
				_proxyRamSize, 0, 0, 0, false, null, GuestIpType.Virtualized,
				useLocalStorage, true, null);
		_serviceOffering.setUniqueName("Cloud.com-ConsoleProxy");
		_serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering);
		_template = _templateDao.findConsoleProxyTemplate();
		if (_template == null) {
			throw new ConfigurationException(
					"Unable to find the template for console proxy VMs");
		}

		_capacityScanScheduler.scheduleAtFixedRate(getCapacityScanTask(),
				STARTUP_DELAY, _capacityScanInterval, TimeUnit.MILLISECONDS);

		if (s_logger.isInfoEnabled())
			s_logger.info("Console Proxy Manager is configured.");
		return true;
	}

	protected ConsoleProxyManagerImpl() {
	public Command cleanup(ConsoleProxyVO vm, String vmName) {
		if (vmName != null) {
			return new StopCommand(vm, vmName, VirtualMachineName.getVnet(vmName));
		} else if (vm != null) {
			ConsoleProxyVO vo = vm;
			return new StopCommand(vo, null);
		} else {
			throw new CloudRuntimeException("Shouldn't even be here!");
		}
	}

	@Override
	public void completeStartCommand(ConsoleProxyVO vm) {
		_consoleProxyDao.updateIf(vm, Event.AgentReportRunning, vm.getHostId());
	}

	@Override
	public void completeStopCommand(ConsoleProxyVO vm) {
		completeStopCommand(vm, Event.AgentReportStopped);
	}

	@DB
	protected void completeStopCommand(ConsoleProxyVO proxy, Event ev) {
		Transaction txn = Transaction.currentTxn();
		try {
			txn.start();
			String privateIpAddress = proxy.getPrivateIpAddress();
			if (privateIpAddress != null) {
				proxy.setPrivateIpAddress(null);
				freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
			}
			String guestIpAddress = proxy.getGuestIpAddress();
			if (guestIpAddress != null) {
				proxy.setGuestIpAddress(null);
				_dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId());
			}

			if (!_consoleProxyDao.updateIf(proxy, ev, null)) {
				s_logger.debug("Unable to update the console proxy");
				return;
			}
			txn.commit();
		} catch (Exception e) {
			s_logger.error("Unable to complete stop command due to ", e);
		}

		if (_storageMgr.unshare(proxy, null) == null) {
			s_logger.warn("Unable to set share to false for " + proxy.getId());
		}
	}

	@Override
	public ConsoleProxyVO get(long id) {
		return _consoleProxyDao.findById(id);
	}

	@Override
	public Long convertToId(String vmName) {
		if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) {
			return null;
		}
		return VirtualMachineName.getConsoleProxyId(vmName);
	}

	@Override
	public boolean stopProxy(long proxyVmId, long startEventId) {

		AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
		if (asyncExecutor != null) {
			AsyncJobVO job = asyncExecutor.getJob();

			if (s_logger.isInfoEnabled())
				s_logger.info("Stop console proxy " + proxyVmId + ", update async job-" + job.getId());
			_asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId);
		}

		ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
		if (proxy == null) {
			if (s_logger.isDebugEnabled())
				s_logger.debug("Stopping console proxy failed: console proxy " + proxyVmId + " no longer exists");
			return false;
		}
/*		
		saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
				EventTypes.EVENT_PROXY_STOP, "Stopping console proxy with Id: "
						+ proxyVmId, startEventId);
*/						
		try {
			return stop(proxy, startEventId);
		} catch (AgentUnavailableException e) {
			if (s_logger.isDebugEnabled())
				s_logger.debug("Stopping console proxy " + proxy.getName() + " failed : exception " + e.toString());
			return false;
		}
	}

	@Override
	public boolean rebootProxy(long proxyVmId, long startEventId) {
		AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
		if (asyncExecutor != null) {
			AsyncJobVO job = asyncExecutor.getJob();

			if (s_logger.isInfoEnabled())
				s_logger.info("Reboot console proxy " + proxyVmId + ", update async job-" + job.getId());
			_asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId);
		}

		final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);

		if (proxy == null || proxy.getState() == State.Destroyed) {
			return false;
		}

/*
		saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
				EventTypes.EVENT_PROXY_REBOOT,
				"Rebooting console proxy with Id: " + proxyVmId, startEventId);
*/
		if (proxy.getState() == State.Running && proxy.getHostId() != null) {
			final RebootCommand cmd = new RebootCommand(proxy.getInstanceName());
			final Answer answer = _agentMgr.easySend(proxy.getHostId(), cmd);

			if (answer != null) {
				if (s_logger.isDebugEnabled())
					s_logger.debug("Successfully reboot console proxy " + proxy.getName());

				SubscriptionMgr.getInstance().notifySubscribers(
						ConsoleProxyManager.ALERT_SUBJECT,
						this,
						new ConsoleProxyAlertEventArgs(
								ConsoleProxyAlertEventArgs.PROXY_REBOOTED,
								proxy.getDataCenterId(), proxy.getId(), proxy,
								null)
						);

				final EventVO event = new EventVO();
				event.setUserId(User.UID_SYSTEM);
				event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
				event.setType(EventTypes.EVENT_PROXY_REBOOT);
				event.setLevel(EventVO.LEVEL_INFO);
				event.setStartId(startEventId);
				event.setDescription("Console proxy rebooted - " + proxy.getName());
				_eventDao.persist(event);
				return true;
			} else {
				if (s_logger.isDebugEnabled())
					s_logger.debug("failed to reboot console proxy : " + proxy.getName());

				final EventVO event = new EventVO();
				event.setUserId(User.UID_SYSTEM);
				event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
				event.setType(EventTypes.EVENT_PROXY_REBOOT);
				event.setLevel(EventVO.LEVEL_ERROR);
				event.setStartId(startEventId);
				event.setDescription("Rebooting console proxy failed - " + proxy.getName());
				_eventDao.persist(event);
				return false;
			}
		} else {
			return startProxy(proxyVmId, 0) != null;
		}
	}

	@Override
	public boolean destroy(ConsoleProxyVO proxy) throws AgentUnavailableException {
		return destroyProxy(proxy.getId(), 0);
	}

	@Override
	@DB
	public boolean destroyProxy(long vmId, long startEventId) {
		AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
		if (asyncExecutor != null) {
			AsyncJobVO job = asyncExecutor.getJob();

			if (s_logger.isInfoEnabled())
				s_logger.info("Destroy console proxy " + vmId + ", update async job-" + job.getId());
			_asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", vmId);
		}

		ConsoleProxyVO vm = _consoleProxyDao.findById(vmId);
		if (vm == null || vm.getState() == State.Destroyed) {
			if (s_logger.isDebugEnabled()) {
				s_logger.debug("Unable to find vm or vm is destroyed: " + vmId);
			}
			return true;
		}
/*		
		saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
				EventTypes.EVENT_PROXY_DESTROY,
				"Destroying console proxy with Id: " + vmId, startEventId);
*/				
		if (s_logger.isDebugEnabled()) {
			s_logger.debug("Destroying console proxy vm " + vmId);
		} 

		if (!_consoleProxyDao.updateIf(vm, Event.DestroyRequested, null)) {
			s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vmId);
			return false;
		}
		Transaction txn = Transaction.currentTxn();
		List vols = null;
		try {
			vols = _volsDao.findByInstance(vmId);
			if (vols.size() != 0) {
				_storageMgr.destroy(vm, vols);
			}

			return true;
		} finally {
			try {
				txn.start();
				// release critical system resources used by the VM before we
				// delete them
				if (vm.getPublicIpAddress() != null)
					freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId());
				vm.setPublicIpAddress(null);

				_consoleProxyDao.remove(vm.getId());

				final EventVO event = new EventVO();
				event.setUserId(User.UID_SYSTEM);
				event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
				event.setType(EventTypes.EVENT_PROXY_DESTROY);
				event.setLevel(EventVO.LEVEL_INFO);
				event.setStartId(startEventId);
				event.setDescription("Console proxy destroyed - "
						+ vm.getName());
				_eventDao.persist(event);

				txn.commit();
			} catch (Exception e) {
				s_logger.error("Caught this error: ", e);
				txn.rollback();
				return false;
			} finally {
				s_logger.debug("console proxy vm is destroyed : "
						+ vm.getName());
			}
		}
	}

	@DB
	public boolean destroyProxyDBOnly(long vmId) {
		Transaction txn = Transaction.currentTxn();
		try {
			txn.start();
			_volsDao.deleteVolumesByInstance(vmId);

			ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId);
			if (proxy != null) {
				if (proxy.getPublicIpAddress() != null)
					freePublicIpAddress(proxy.getPublicIpAddress(), proxy.getDataCenterId(), proxy.getPodId());

				_consoleProxyDao.remove(vmId);

				final EventVO event = new EventVO();
				event.setUserId(User.UID_SYSTEM);
				event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
				event.setType(EventTypes.EVENT_PROXY_DESTROY);
				event.setLevel(EventVO.LEVEL_INFO);
				event.setDescription("Console proxy destroyed - "
						+ proxy.getName());
				_eventDao.persist(event);
			}

			txn.commit();
			return true;
		} catch (Exception e) {
			s_logger.error("Caught this error: ", e);
			txn.rollback();
			return false;
		} finally {
			s_logger.debug("console proxy vm is destroyed from DB : " + vmId);
		}
	}

	@Override
	public boolean stop(ConsoleProxyVO proxy, long startEventId)
			throws AgentUnavailableException {
		if (!_consoleProxyDao.updateIf(proxy, Event.StopRequested, proxy.getHostId())) {
			s_logger.debug("Unable to stop console proxy: " + proxy.toString());
			return false;
		}

		// IPAddressVO ip = _ipAddressDao.findById(proxy.getPublicIpAddress());
		// VlanVO vlan = _vlanDao.findById(new Long(ip.getVlanDbId()));

		GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxy.getId()));
		try {
			if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
				try {
					StopCommand cmd = new StopCommand(proxy, true, Integer.toString(_consoleProxyPort), 
							Integer.toString(_consoleProxyUrlPort), proxy.getPublicIpAddress());
					try {
						Long proxyHostId = proxy.getHostId();
						if (proxyHostId == null) {
							s_logger.debug("Unable to stop due to proxy " + proxy.getId()
								+ " as host is no longer available, proxy may already have been stopped");
							return false;
						}
						StopAnswer answer = (StopAnswer) _agentMgr.send(proxyHostId, cmd);
						if (answer == null || !answer.getResult()) {
							s_logger.debug("Unable to stop due to " + (answer == null ? "answer is null" : answer.getDetails()));

							final EventVO event = new EventVO();
							event.setUserId(User.UID_SYSTEM);
							event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
							event.setType(EventTypes.EVENT_PROXY_STOP);
							event.setLevel(EventVO.LEVEL_ERROR);
							event.setStartId(startEventId);
							event.setDescription("Stopping console proxy failed due to negative answer from agent - " + proxy.getName());
							_eventDao.persist(event);
							return false;
						}
						completeStopCommand(proxy, Event.OperationSucceeded);

						SubscriptionMgr.getInstance().notifySubscribers(
								ConsoleProxyManager.ALERT_SUBJECT,
								this,
								new ConsoleProxyAlertEventArgs(
										ConsoleProxyAlertEventArgs.PROXY_DOWN,
										proxy.getDataCenterId(), proxy.getId(),
										proxy, null));

						final EventVO event = new EventVO();
						event.setUserId(User.UID_SYSTEM);
						event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
						event.setType(EventTypes.EVENT_PROXY_STOP);
						event.setLevel(EventVO.LEVEL_INFO);
						event.setStartId(startEventId);
						event.setDescription("Console proxy stopped - " + proxy.getName());
						_eventDao.persist(event);
						return true;
					} catch (OperationTimedoutException e) {
						final EventVO event = new EventVO();
						event.setUserId(User.UID_SYSTEM);
						event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
						event.setType(EventTypes.EVENT_PROXY_STOP);
						event.setLevel(EventVO.LEVEL_ERROR);
						event.setStartId(startEventId);
						event.setDescription("Stopping console proxy failed due to operation time out - " + proxy.getName());
						_eventDao.persist(event);
						throw new AgentUnavailableException(proxy.getHostId());
					}
				} finally {
					proxyLock.unlock();
				}
			} else {
				s_logger.debug("Unable to acquire console proxy lock : " + proxy.toString());
				return false;
			}
		} finally {
			proxyLock.releaseRef();
		}
	}

	@Override
	public boolean migrate(ConsoleProxyVO proxy, HostVO host) {
		HostVO fromHost = _hostDao.findById(proxy.getId());

		if (!_consoleProxyDao.updateIf(proxy, Event.MigrationRequested, proxy.getHostId())) {
			s_logger.debug("State for " + proxy.toString() + " has changed so migration can not take place.");
			return false;
		}

		MigrateCommand cmd = new MigrateCommand(proxy.getInstanceName(), host.getPrivateIpAddress(), false);
		Answer answer = _agentMgr.easySend(fromHost.getId(), cmd);
		if (answer == null) {
			return false;
		}

		_storageMgr.unshare(proxy, fromHost);

		return true;
	}

	@Override
	public boolean completeMigration(ConsoleProxyVO proxy, HostVO host)
			throws AgentUnavailableException, OperationTimedoutException {

		CheckVirtualMachineCommand cvm = new CheckVirtualMachineCommand(proxy.getInstanceName());
		CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(host.getId(), cvm);
		if (!answer.getResult()) {
			s_logger.debug("Unable to complete migration for " + proxy.getId());
			_consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null);
			return false;
		}

		State state = answer.getState();
		if (state == State.Stopped) {
			s_logger.warn("Unable to complete migration as we can not detect it on " + host.getId());
			_consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null);
			return false;
		}

		_consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, host.getId());
		return true;
	}

	@Override
	public HostVO prepareForMigration(ConsoleProxyVO proxy)
			throws StorageUnavailableException {

		VMTemplateVO template = _templateDao.findById(proxy.getTemplateId());
		long routerId = proxy.getId();
		boolean mirroredVols = proxy.isMirroredVols();
		DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId());
		HostPodVO pod = _podDao.findById(proxy.getPodId());
		List sps = _storageMgr.getStoragePoolsForVm(proxy.getId());
		StoragePoolVO sp = sps.get(0); // FIXME

		List vols = _volsDao.findCreatedByInstance(routerId);

		String[] storageIps = new String[2];
		VolumeVO vol = vols.get(0);
		storageIps[0] = vol.getHostIp();
		if (mirroredVols && (vols.size() == 2)) {
			storageIps[1] = vols.get(1).getHostIp();
		}

		PrepareForMigrationCommand cmd = new PrepareForMigrationCommand(proxy.getName(), null, storageIps, vols, mirroredVols);

		HostVO routingHost = null;
		HashSet avoid = new HashSet();

		HostVO fromHost = _hostDao.findById(proxy.getHostId());
		if (fromHost.getClusterId() == null) {
			s_logger.debug("The host is not in a cluster");
			return null;
		}
		avoid.add(fromHost);

		while ((routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, template, proxy, fromHost, avoid)) != null) {
			avoid.add(routingHost);

			if (s_logger.isDebugEnabled()) {
				s_logger.debug("Trying to migrate router to host " + routingHost.getName());
			}

			if (!_storageMgr.share(proxy, vols, routingHost, false)) {
				s_logger.warn("Can not share " + proxy.getName());
				throw new StorageUnavailableException(vol.getPoolId());
			}

			Answer answer = _agentMgr.easySend(routingHost.getId(), cmd);
			if (answer != null && answer.getResult()) {
				return routingHost;
			}
			_storageMgr.unshare(proxy, vols, routingHost);
		}

		return null;
	}

	private String getCapacityScanLockName() {
		// to improve security, it may be better to return a unique mashed
		// name(for example MD5 hashed)
		return "consoleproxy.capacity.scan";
	}

	private String getAllocProxyLockName() {
		// to improve security, it may be better to return a unique mashed
		// name(for example MD5 hashed)
		return "consoleproxy.alloc";
	}

	private String getProxyLockName(long id) {
		return "consoleproxy." + id;
	}

	private Long saveStartedEvent(Long userId, Long accountId, String type,
			String description, long startEventId) {
		EventVO event = new EventVO();
		event.setUserId(userId);
		event.setAccountId(accountId);
		event.setType(type);
		event.setState(EventState.Started);
		event.setDescription(description);
		event.setStartId(startEventId);
		event = _eventDao.persist(event);
		if (event != null)
			return event.getId();
		return null;
	}
	
	@Override
	public boolean destroyConsoleProxy(DestroyConsoleProxyCmd cmd) throws ServerApiException{
	    Long proxyId = cmd.getId();
	    
	    // verify parameters
        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId);
        if (proxy == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a console proxy with id " + proxyId);
        }
        
        long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_DESTROY, "destroying console proxy with Id: "+proxyId);
        
        return destroyProxy(proxyId, eventId);
        
	}
=======
public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMachineManager, AgentHook {
    private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class);

    private static final int DEFAULT_FIND_HOST_RETRY_COUNT = 2;
    private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30
    // seconds
    private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1000; // 1 second

    private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3
    // seconds
    private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC = 180; // 3
    // minutes

    private static final int API_WAIT_TIMEOUT = 5000; // 5 seconds (in
    // milliseconds)
    private static final int STARTUP_DELAY = 60000; // 60 seconds

    private int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT;
    private int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT;

    private String _mgmt_host;
    private int _mgmt_port = 8250;

    private String _name;
    private Adapters _consoleProxyAllocators;

    @Inject
    private ConsoleProxyDao _consoleProxyDao;
    @Inject
    private DataCenterDao _dcDao;
    @Inject
    private VlanDao _vlanDao;
    @Inject
    private VMTemplateDao _templateDao;
    @Inject
    private IPAddressDao _ipAddressDao;
    @Inject
    private VolumeDao _volsDao;
    @Inject
    private HostPodDao _podDao;
    @Inject
    private HostDao _hostDao;
    @Inject
    private ConfigurationDao _configDao;

    @Inject
    private VMInstanceDao _instanceDao;
    @Inject
    private AccountDao _accountDao;

    @Inject
    private VMTemplateHostDao _vmTemplateHostDao;

    @Inject
    private AgentManager _agentMgr;
    @Inject
    private StorageManager _storageMgr;
    @Inject
    private HighAvailabilityManager _haMgr;
    @Inject NetworkManager _networkMgr;
    
    @Inject AccountManager _accountMgr;
    @Inject
    private EventDao _eventDao;
    @Inject
    ServiceOfferingDao _offeringDao;
    @Inject
    NetworkOfferingDao _networkOfferingDao;
    private IpAddrAllocator _IpAllocator;

    private ConsoleProxyListener _listener;

    private ServiceOfferingVO _serviceOffering;
    private int _networkRate;
    private int _multicastRate;
    private VMTemplateVO _template;
    
    NetworkOfferingVO _publicNetworkOffering;
    NetworkOfferingVO _managementNetworkOffering;
    NetworkOfferingVO _linkLocalNetworkOffering;

    @Inject
    private AsyncJobManager _asyncMgr;
    
    @Inject
    private VmManager _vmMgr;

    private final ScheduledExecutorService _capacityScanScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("CP-Scan"));
    private final ExecutorService _requestHandlerScheduler = Executors.newCachedThreadPool(new NamedThreadFactory("Request-handler"));

    private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL;
    private int _capacityPerProxy = ConsoleProxyManager.DEFAULT_PROXY_CAPACITY;
    private int _standbyCapacity = ConsoleProxyManager.DEFAULT_STANDBY_CAPACITY;

    private int _proxyRamSize;
    private int _find_host_retry = DEFAULT_FIND_HOST_RETRY_COUNT;
    private int _ssh_retry;
    private int _ssh_sleep;
    private boolean _use_lvm;
    private boolean _use_storage_vm;

    private String _domain;
    private String _instance;

    // private String _privateNetmask;
    private int _proxyCmdPort = DEFAULT_PROXY_CMD_PORT;
    private int _proxySessionTimeoutValue = DEFAULT_PROXY_SESSION_TIMEOUT;
    private boolean _sslEnabled = false;

    private final GlobalLock _capacityScanLock = GlobalLock.getInternLock(getCapacityScanLockName());
    private final GlobalLock _allocProxyLock = GlobalLock.getInternLock(getAllocProxyLockName());

    @Override
    public ConsoleProxyInfo assignProxy(final long dataCenterId, final long vmId) {

        final Pair result = new Pair(this, null);

        _requestHandlerScheduler.execute(new Runnable() {
            @Override
            public void run() {
                Transaction txn = Transaction.open(Transaction.CLOUD_DB);
                try {
                    ConsoleProxyVO proxy = doAssignProxy(dataCenterId, vmId);
                    synchronized (result) {
                        result.second(proxy);
                        result.notifyAll();
                    }
                } catch (Throwable e) {
                    s_logger.warn("Unexpected exception " + e.getMessage(), e);
                } finally {
                    StackMaid.current().exitCleanup();
                    txn.close();
                }
            }
        });

        synchronized (result) {
            try {
                result.wait(API_WAIT_TIMEOUT);
            } catch (InterruptedException e) {
                s_logger.info("Waiting for console proxy assignment is interrupted");
            }
        }
        
        ConsoleProxyVO proxy = result.second();
        if (proxy == null)
            return null;
        
        return new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), _consoleProxyPort, proxy.getPort());
    }

    public ConsoleProxyVO doAssignProxy(long dataCenterId, long vmId) {
        ConsoleProxyVO proxy = null;
        VMInstanceVO vm = _instanceDao.findById(vmId);
        if (vm == null) {
            s_logger.warn("VM " + vmId + " no longer exists, return a null proxy for vm:" + vmId);
            return null;
        }

        Boolean[] proxyFromStoppedPool = new Boolean[1];
        if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
            try {
                proxy = getOrAllocProxyResource(dataCenterId, vmId, proxyFromStoppedPool);
            } finally {
                _allocProxyLock.unlock();
            }
        } else {
            s_logger.error("Unable to acquire synchronization lock to get/allocate proxy resource for vm :" + vmId
                    + ". Previous console proxy allocation is taking too long");
        }

        if (proxy == null) {
            s_logger.warn("Unable to find or allocate console proxy resource");
            return null;
        }

        long proxyVmId = proxy.getId();
        GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId));
        try {
            if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                try {
                    proxy = startProxy(proxyVmId, 0);

                    if (proxy == null) {
                        //
                        // We had a situation with multi-pod configuration,
    }
                        // where
                        // storage allocation of the console proxy VM may
                        // succeed, but later-on starting of it
                        // may fail because of running out of computing resource
                        // (CPU/memory). We
                        // currently don't support moving storage to another pod
                        // on the fly, to deal
                        // with the situation we will destroy this proxy VM and
                        // let it the whole proxy VM
                        // creation process re-start again, by hoping that new
                        // storage and computing
                        // resource may be allocated and assigned in another pod
                        //
                        if (s_logger.isInfoEnabled())
                            s_logger.info("Unable to start console proxy, proxy vm Id : " + proxyVmId + " will recycle it and restart a new one");
                        destroyProxy(proxyVmId, 0);
                        return null;
                    } else {
                        if (s_logger.isTraceEnabled())
                            s_logger.trace("Console proxy " + proxy.getName() + " is started");

                        // if it is a new assignment or a changed assignment,
                        // update the
                        // record
                        if (vm.getProxyId() == null || vm.getProxyId().longValue() != proxy.getId())
                            _instanceDao.updateProxyId(vmId, proxy.getId(), DateUtil.currentGMTTime());

                        proxy.setSslEnabled(_sslEnabled);
                        if (_sslEnabled)
                            proxy.setPort(443);
                        else
                            proxy.setPort(80);
                        return proxy;
                    }
                } finally {
                    proxyLock.unlock();
                }
            } else {
                s_logger.error("Unable to acquire synchronization lock to start console proxy " + proxyVmId + " for vm: " + vmId
                        + ". It takes too long to start the proxy");

                return null;
            }
        } finally {
            proxyLock.releaseRef();
        }
    }

    private ConsoleProxyVO getOrAllocProxyResource(long dataCenterId, long vmId, Boolean[] proxyFromStoppedPool) {
        ConsoleProxyVO proxy = null;
        VMInstanceVO vm = this._instanceDao.findById(vmId);

        if (vm != null && vm.getState() != State.Running) {
            if (s_logger.isInfoEnabled())
                s_logger.info("Detected that vm : " + vmId + " is not currently at running state, we will fail the proxy assignment for it");
            return null;
        }

        if (vm != null && vm.getProxyId() != null) {
            proxy = _consoleProxyDao.findById(vm.getProxyId());

            if (proxy != null) {
                if (!isInAssignableState(proxy)) {
                    if (s_logger.isInfoEnabled())
                        s_logger.info("A previous assigned proxy is not assignable now, reassign console proxy for user vm : " + vmId);
                    proxy = null;
                } else {
                    if (_consoleProxyDao.getProxyActiveLoad(proxy.getId()) < _capacityPerProxy || hasPreviousSession(proxy, vm)) {
                        if (s_logger.isTraceEnabled())
                            s_logger.trace("Assign previous allocated console proxy for user vm : " + vmId);

                        if (proxy.getActiveSession() >= _capacityPerProxy)
                            s_logger.warn("Assign overloaded proxy to user VM as previous session exists, user vm : " + vmId);
                    } else {
                        proxy = null;
                    }

                }
            }
        }

        if (proxy == null)
            proxy = assignProxyFromRunningPool(dataCenterId);

        if (proxy == null) {

            if (s_logger.isInfoEnabled())
                s_logger.info("No running console proxy is available, check to see if we can bring up a stopped one for data center : "
                        + dataCenterId);

            proxy = assignProxyFromStoppedPool(dataCenterId);
            if (proxy == null) {
                if (s_logger.isInfoEnabled())
                    s_logger.info("No stopped console proxy is available, need to allocate a new console proxy for data center : " + dataCenterId);

                proxy = startNew(dataCenterId);
            } else {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId() + ", data center : "
                            + dataCenterId);

                proxyFromStoppedPool[0] = new Boolean(true);
            }
        }

        return proxy;
    }

    private static boolean isInAssignableState(ConsoleProxyVO proxy) {
        // console proxies that are in states of being able to serve user VM
        State state = proxy.getState();
        if (state == State.Running || state == State.Starting || state == State.Creating || state == State.Migrating)
            return true;

        return false;
    }

    private boolean hasPreviousSession(ConsoleProxyVO proxy, VMInstanceVO vm) {

        ConsoleProxyStatus status = null;
        try {
            GsonBuilder gb = new GsonBuilder();
            gb.setVersion(1.3);
            Gson gson = gb.create();

            byte[] details = proxy.getSessionDetails();
            status = gson.fromJson(details != null ? new String(details, Charset.forName("US-ASCII")) : null, ConsoleProxyStatus.class);
        } catch (Throwable e) {
            s_logger.warn("Unable to parse proxy session details : " + proxy.getSessionDetails());
        }

        if (status != null && status.getConnections() != null) {
            ConsoleProxyConnectionInfo[] connections = status.getConnections();
            for (int i = 0; i < connections.length; i++) {
                long taggedVmId = 0;
                if (connections[i].tag != null) {
                    try {
                        taggedVmId = Long.parseLong(connections[i].tag);
                    } catch (NumberFormatException e) {
                        s_logger.warn("Unable to parse console proxy connection info passed through tag: " + connections[i].tag, e);
                    }
                }
                if (taggedVmId == vm.getId())
                    return true;
            }

            //
            // even if we are not in the list, it may because we haven't
            // received load-update yet
            // wait until session time
            //
            if (DateUtil.currentGMTTime().getTime() - vm.getProxyAssignTime().getTime() < _proxySessionTimeoutValue)
                return true;

            return false;
        } else {
            s_logger.error("No proxy load info on an overloaded proxy ?");
            return false;
        }
    }
    
    @Override
    public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) {
        try {
            return start(proxyVmId, startEventId);
        } catch (StorageUnavailableException e) {
            s_logger.warn("Exception while trying to start console proxy", e);
            return null;
        } catch (InsufficientCapacityException e) {
            s_logger.warn("Exception while trying to start console proxy", e);
            return null;
        } catch (ConcurrentOperationException e) {
            s_logger.warn("Exception while trying to start console proxy", e);
            return null;
        }
    }


    public ConsoleProxyVO start2(long proxyVmId, long startEventId) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
        DeploymentPlan plan = new DataCenterDeployment(proxy.getDataCenterId(), 1);
        return _vmMgr.start(proxy, plan);
    }

    @Override
    @DB
    public ConsoleProxyVO start(long proxyId, long startEventId) throws StorageUnavailableException, InsufficientCapacityException,
            ConcurrentOperationException {

        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("Start console proxy " + proxyId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyId);
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId);
        if (proxy == null || proxy.getRemoved() != null) {
            s_logger.debug("proxy is not found: " + proxyId);
            return null;
        }
        /*
         * // don't insert event here, it may be called multiple times!
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: " +
         * proxyId, startEventId);
         */

        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Starting console proxy if it is not started, proxy vm id : " + proxyId);
        }

        for (int i = 0; i < 2; i++) {

            State state = proxy.getState();

            if (state == State.Starting /* || state == State.Migrating */) {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Waiting console proxy to be ready, proxy vm id : " + proxyId + " proxy VM state : " + state.toString());

                if (proxy.getPrivateIpAddress() == null || connect(proxy.getPrivateIpAddress(), _proxyCmdPort) != null) {
                    if (proxy.getPrivateIpAddress() == null)
                        s_logger.warn("Retruning a proxy that is being started but private IP has not been allocated yet, proxy vm id : " + proxyId);
                    else
                        s_logger.warn("Waiting console proxy to be ready timed out, proxy vm id : " + proxyId);

                    // TODO, it is very tricky here, if the startup process
                    // takes too long and it timed out here,
                    // we may give back a proxy that is not fully ready for
                    // functioning
                }
                return proxy;
            }

            if (state == State.Running) {
                if (s_logger.isTraceEnabled())
                    s_logger.trace("Console proxy is already started: " + proxy.getName());
                return proxy;
            }

            DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId());
            HostPodVO pod = _podDao.findById(proxy.getPodId());
            List sps = _storageMgr.getStoragePoolsForVm(proxy.getId());
            StoragePoolVO sp = sps.get(0); // FIXME

            HashSet avoid = new HashSet();
            HostVO routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, _template, proxy, null, avoid);

            if (routingHost == null) {
                if (s_logger.isDebugEnabled()) {
                    String msg = "Unable to find a routing host for " + proxy.toString() + " in pod " + pod.getId();
                    s_logger.debug(msg);
                    throw new CloudRuntimeException(msg);
                }
            }
            // to ensure atomic state transition to Starting state
            if (!_consoleProxyDao.updateIf(proxy, Event.StartRequested, routingHost.getId())) {
                if (s_logger.isDebugEnabled()) {
                    ConsoleProxyVO temp = _consoleProxyDao.findById(proxyId);
                    s_logger.debug("Unable to start console proxy " + proxy.getName() + " because it is not in a startable state : "
                            + ((temp != null) ? temp.getState().toString() : "null"));
                }
                continue;
            }

            try {
                Answer answer = null;
                int retry = _find_host_retry;

                // Console proxy VM will be running at routing hosts as routing
                // hosts have public access to outside network
                do {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Trying to start console proxy on host " + routingHost.getName());
                    }

                    String privateIpAddress = allocPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId(),
                            proxy.getPrivateMacAddress());
                    if (privateIpAddress == null && (_IpAllocator != null && !_IpAllocator.exteralIpAddressAllocatorEnabled())) {
                        String msg = "Unable to allocate private ip addresses for  " + proxy.getName() + " in pod " + pod.getId();
                        s_logger.debug(msg);
                        throw new CloudRuntimeException(msg);
                    }

                    proxy.setPrivateIpAddress(privateIpAddress);
                    String guestIpAddress = _dcDao.allocateLinkLocalPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId());
                    proxy.setGuestIpAddress(guestIpAddress);

                    _consoleProxyDao.updateIf(proxy, Event.OperationRetry, routingHost.getId());
                    proxy = _consoleProxyDao.findById(proxy.getId());

                    List vols = _storageMgr.prepare(proxy, routingHost);
                    if (vols == null || vols.size() == 0) {
                        String msg = "Unable to prepare storage for " + proxy.getName() + " in pod " + pod.getId();
                        s_logger.debug(msg);
                        throw new CloudRuntimeException(msg);
                    }

                    // _storageMgr.share(proxy, vols, null, true);

                    // carry the console proxy port info over so that we don't
                    // need to configure agent on this
                    StartConsoleProxyCommand cmdStart = new StartConsoleProxyCommand(_networkRate, _multicastRate,
                            _proxyCmdPort, proxy, proxy.getName(), "", vols, Integer.toString(_consoleProxyPort),
                            Integer.toString(_consoleProxyUrlPort), _mgmt_host, _mgmt_port, _sslEnabled);
                    if (s_logger.isDebugEnabled())
                        s_logger.debug("Sending start command for console proxy " + proxy.getName() + " to " + routingHost.getName());
                    try {
                        answer = _agentMgr.send(routingHost.getId(), cmdStart);

                        s_logger.debug("StartConsoleProxy Answer: " + (answer != null ? answer : "null"));

                        if (s_logger.isDebugEnabled())
                            s_logger.debug("Received answer on starting console proxy " + proxy.getName() + " on " + routingHost.getName());

                        if (answer != null && answer.getResult()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Console proxy " + proxy.getName() + " started on " + routingHost.getName());
                            }

                            if (answer instanceof StartConsoleProxyAnswer) {
                                StartConsoleProxyAnswer rAnswer = (StartConsoleProxyAnswer) answer;
                                if (rAnswer.getPrivateIpAddress() != null) {
                                    proxy.setPrivateIpAddress(rAnswer.getPrivateIpAddress());
                                }
                                if (rAnswer.getPrivateMacAddress() != null) {
                                    proxy.setPrivateMacAddress(rAnswer.getPrivateMacAddress());
                                }
                            }

                            final EventVO event = new EventVO();
                            event.setUserId(User.UID_SYSTEM);
                            event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                            event.setType(EventTypes.EVENT_PROXY_START);
                            event.setLevel(EventVO.LEVEL_INFO);
                            event.setStartId(startEventId);
                            event.setDescription("Console proxy started - " + proxy.getName());
                            _eventDao.persist(event);
                            break;
                        }
                        s_logger.debug("Unable to start " + proxy.toString() + " on host " + routingHost.toString() + " due to "
                                + answer.getDetails());
                    } catch (OperationTimedoutException e) {
                        if (e.isActive()) {
                            s_logger.debug("Unable to start vm " + proxy.getName()
                                    + " due to operation timed out and it is active so scheduling a restart.");
                            _haMgr.scheduleRestart(proxy, true);
                            return null;
                        }
                    } catch (AgentUnavailableException e) {
                        s_logger.debug("Agent " + routingHost.toString() + " was unavailable to start VM " + proxy.getName());
                    }

                    avoid.add(routingHost);
                    proxy.setPrivateIpAddress(null);
                    freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
                    proxy.setGuestIpAddress(null);
                    _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId());
                    _storageMgr.unshare(proxy, vols, routingHost);
                } while (--retry > 0
                        && (routingHost = (HostVO) _agentMgr
                                .findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, _template, proxy, null, avoid)) != null);
                if (routingHost == null || retry <= 0) {

                    SubscriptionMgr.getInstance().notifySubscribers(
                            ConsoleProxyManager.ALERT_SUBJECT,
                            this,
                            new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, proxy.getDataCenterId(), proxy.getId(),
                                    proxy, "Unable to find a routing host to run"));

                    final EventVO event = new EventVO();
                    event.setUserId(User.UID_SYSTEM);
                    event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                    event.setType(EventTypes.EVENT_PROXY_START);
                    event.setLevel(EventVO.LEVEL_ERROR);
                    event.setStartId(startEventId);
                    event.setDescription("Starting console proxy failed due to unable to find a host - " + proxy.getName());
                    _eventDao.persist(event);
                    throw new ExecutionException("Couldn't find a routingHost to run console proxy");
                }

                _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, routingHost.getId());
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Console proxy is now started, vm id : " + proxy.getId());
                }

                // If starting the console proxy failed due to the external
                // firewall not being reachable, send an alert.
                if (answer != null && answer.getDetails() != null && answer.getDetails().equals("firewall")) {

                    SubscriptionMgr.getInstance().notifySubscribers(
                            ConsoleProxyManager.ALERT_SUBJECT,
                            this,
                            new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_FIREWALL_ALERT, proxy.getDataCenterId(), proxy.getId(),
                                    proxy, null));
                }

                SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this,
                        new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_UP, proxy.getDataCenterId(), proxy.getId(), proxy, null));

                return proxy;
            } catch (Throwable thr) {
                s_logger.warn("Unexpected exception: ", thr);

            context.put("proxyVmId", proxyVmId);
            return context;
                SubscriptionMgr.getInstance().notifySubscribers(
                        ConsoleProxyManager.ALERT_SUBJECT,
                        this,
            return l.get(0);

        return null;
                        new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, proxy.getDataCenterId(), proxy.getId(), proxy,
                                "Unexpected exception: " + thr.getMessage()));

                /*
                 * final EventVO event = new EventVO();
                 * event.setUserId(User.UID_SYSTEM);
                 * event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                 * event.setType(EventTypes.EVENT_PROXY_START);
                 * event.setLevel(EventVO.LEVEL_ERROR);
                 * event.setStartId(startEventId); event.setDescription(
                 * "Starting console proxy failed due to unhandled exception - "
                 * + proxy.getName()); _eventDao.persist(event);
                 */

                Transaction txn = Transaction.currentTxn();
                try {
                    txn.start();
                    String privateIpAddress = proxy.getPrivateIpAddress();
                    if (privateIpAddress != null) {
                        proxy.setPrivateIpAddress(null);
                        freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
                    }

                    _consoleProxyDao.updateIf(proxy, Event.OperationFailed, null);
                    txn.commit();
                } catch (Exception e) {
                    s_logger.error("Caught exception during error recovery");
                }

                if (thr instanceof StorageUnavailableException) {
                    throw (StorageUnavailableException) thr;
                } else if (thr instanceof ConcurrentOperationException) {
                    throw (ConcurrentOperationException) thr;
                } else if (thr instanceof ExecutionException) {
                    s_logger.error("Error while starting console proxy due to " + thr.getMessage());
                } else {
                    s_logger.error("Error while starting console proxy ", thr);
                }
                return null;
            }
        }

        s_logger.warn("Starting console proxy encounters non-startable situation");
        return null;
    }

    public ConsoleProxyVO assignProxyFromRunningPool(long dataCenterId) {

        if (s_logger.isTraceEnabled())
            s_logger.trace("Assign console proxy from running pool for request from data center : " + dataCenterId);

        ConsoleProxyAllocator allocator = getCurrentAllocator();
        assert (allocator != null);
        List runningList = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Running);
        if (runningList != null && runningList.size() > 0) {
            if (s_logger.isTraceEnabled()) {
                s_logger.trace("Running proxy pool size : " + runningList.size());
                for (ConsoleProxyVO proxy : runningList)
                    s_logger.trace("Running proxy instance : " + proxy.getName());
            }

            List> l = _consoleProxyDao.getProxyLoadMatrix();
            Map loadInfo = new HashMap();
            if (l != null) {
                for (Pair p : l) {
                    loadInfo.put(p.first(), p.second());

                    if (s_logger.isTraceEnabled()) {
                        s_logger.trace("Running proxy instance allocation load { proxy id : " + p.first() + ", load : " + p.second() + "}");
                    }
                }
            }
            return allocator.allocProxy(runningList, loadInfo, dataCenterId);
        } else {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Empty running proxy pool for now in data center : " + dataCenterId);
        }
        return null;
    }

    public ConsoleProxyVO assignProxyFromStoppedPool(long dataCenterId) {
        } else {
        List l = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Creating, State.Starting, State.Stopped, State.Migrating);
        if (l != null && l.size() > 0)
    public ConsoleProxyVO startNewConsoleProxy(long dataCenterId) {
        if (s_logger.isDebugEnabled())
            s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId);

        Map context = createProxyInstance(dataCenterId);

        long proxyVmId = (Long) context.get("proxyVmId");
        if (proxyVmId == 0) {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId);

            // release critical system resource on failure
            if (context.get("publicIpAddress") != null)
                freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0);

            return null;
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); 
            //allocProxyStorage(dataCenterId, proxyVmId);
        if (proxy != null) {
            SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATED, dataCenterId, proxy.getId(), proxy, null));
            return proxy;
        } else {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId);

            SubscriptionMgr.getInstance().notifySubscribers(
                    ConsoleProxyManager.ALERT_SUBJECT,
                    this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE, dataCenterId, proxyVmId, null,
                            "Unable to allocate storage"));

            destroyProxyDBOnly(proxyVmId);
        }
        return null;
    }

    public ConsoleProxyVO startNew(long dataCenterId) {

        if (s_logger.isDebugEnabled())
            s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId);

        Map context = createProxyInstance(dataCenterId);

        long proxyVmId = (Long) context.get("proxyVmId");
        if (proxyVmId == 0) {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId);

            // release critical system resource on failure
            if (context.get("publicIpAddress") != null)
                freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0);

            return null;
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); 
            //allocProxyStorage(dataCenterId, proxyVmId);
        if (proxy != null) {
            SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATED, dataCenterId, proxy.getId(), proxy, null));
            return proxy;
        } else {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId);

            SubscriptionMgr.getInstance().notifySubscribers(
                    ConsoleProxyManager.ALERT_SUBJECT,
                    this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE, dataCenterId, proxyVmId, null,
                            "Unable to allocate storage"));

            destroyProxyDBOnly(proxyVmId);
        }
        return null;
    }

    @DB
        } catch (Throwable e) {
            return net;
    protected Map createProxyInstance(long dataCenterId) {

        Map context = new HashMap();
        String publicIpAddress = null;

        Transaction txn = Transaction.currentTxn();
        try {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            assert (dc != null);
            context.put("dc", dc);

            // this will basically allocate the pod based on data center id as
            // we use system user id here
            Set avoidPods = new HashSet();
            Pair pod = null;
            networkInfo publicIpAndVlan = null;

            // About MAC address allocation
            // MAC address used by User VM is inherited from DomR MAC address,
            // with the least 16 bits overrided. to avoid
            // potential conflicts, domP will mask bit 31
            //
            String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31));
            String privateMacAddress = macAddresses[0];
            String publicMacAddress = macAddresses[1];
            macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31));
            String guestMacAddress = macAddresses[0];
            while ((pod = _agentMgr.findPod(_template, _serviceOffering, dc, Account.ACCOUNT_ID_SYSTEM, avoidPods)) != null) {
                publicIpAndVlan = allocPublicIpAddress(dataCenterId, pod.first().getId(), publicMacAddress);
                if (publicIpAndVlan == null) {
                    s_logger.warn("Unable to allocate public IP address for console proxy vm in data center : " + dataCenterId + ", pod="
                            + pod.first().getId());
                    avoidPods.add(pod.first().getId());
                } else {
                    break;
                }
            }

            if (pod == null || publicIpAndVlan == null) {
                String msg = "Unable to allocate pod for console proxy vm in data center : " + dataCenterId;
                s_logger.warn(msg);
                throw new CloudRuntimeException(msg);
            }

            long id = _consoleProxyDao.getNextInSequence(Long.class, "id");

            context.put("publicIpAddress", publicIpAndVlan._ipAddr);
            context.put("pod", pod);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Pod allocated " + pod.first().getName());
            }

            String cidrNetmask = NetUtils.getCidrNetmask(pod.first().getCidrSize());

            // Find the VLAN ID, VLAN gateway, and VLAN netmask for
            // publicIpAddress
            publicIpAddress = publicIpAndVlan._ipAddr;

            String vlanGateway = publicIpAndVlan._gateWay;
            String vlanNetmask = publicIpAndVlan._netMask;
            
            AccountVO systemAccount = _accountMgr.getSystemAccount();

            txn.start();
            ConsoleProxyVO proxy;
            String name = VirtualMachineName.getConsoleProxyName(id, _instance).intern();
            proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, guestMacAddress, null, NetUtils.getLinkLocalNetMask(), privateMacAddress, null, cidrNetmask,
                    _template.getId(), _template.getGuestOSId(), publicMacAddress, publicIpAddress, vlanNetmask, publicIpAndVlan._vlanDbId,
                    publicIpAndVlan._vlanid, pod.first().getId(), dataCenterId, systemAccount.getDomainId(), systemAccount.getId(), vlanGateway, null, dc.getDns1(), dc.getDns2(), _domain,
                    _proxyRamSize, 0);

            proxy.setLastHostId(pod.second());
            proxy = _consoleProxyDao.persist(proxy);
            long proxyVmId = proxy.getId();

            final EventVO event = new EventVO();
            event.setUserId(User.UID_SYSTEM);
            event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
            event.setType(EventTypes.EVENT_PROXY_CREATE);
            event.setLevel(EventVO.LEVEL_INFO);
            event.setDescription("New console proxy created - " + proxy.getName());
            _eventDao.persist(event);
            txn.commit();
        }

        try {
            s_logger.error("Unexpected exception : ", e);

            context.put("proxyVmId", (long) 0);
            return context;
        }
    }
    protected Map createProxyInstance2(long dataCenterId) {

        long id = _consoleProxyDao.getNextInSequence(Long.class, "id");
        String name = VirtualMachineName.getConsoleProxyName(id, _instance);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        AccountVO systemAcct = _accountMgr.getSystemAccount();
        
        DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, 1);
        
        List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork, NetworkOfferingVO.SystemVmManagementNetwork, NetworkOfferingVO.SystemVmPublicNetwork);
        List profiles = new ArrayList(offerings.size());
        for (NetworkOfferingVO offering : offerings) {
            profiles.add(_networkMgr.setupNetworkConfiguration(_accountMgr.getSystemAccount(), offering, plan));
        }
        ConsoleProxyVO proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, _template.getId(), _template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId(), 0);
        proxy = _consoleProxyDao.persist(proxy);
        try {
            VirtualMachineProfile vmProfile = _vmMgr.allocate(proxy, _template, _serviceOffering, profiles, plan, _accountMgr.getSystemAccount());
        } catch (InsufficientCapacityException e) {
            s_logger.warn("InsufficientCapacity", e);
            throw new CloudRuntimeException("Insufficient capacity exception", e);
        } catch (StorageUnavailableException e) {
            s_logger.warn("Unable to contact storage", e);
            throw new CloudRuntimeException("Unable to contact storage", e);
        }
        
        Map context = new HashMap();
        context.put("dc", dc);
//        context.put("publicIpAddress", publicIpAndVlan._ipAddr);
        HostPodVO pod = _podDao.findById(proxy.getPodId());
        context.put("pod", pod);
        context.put("proxyVmId", proxy.getId());

        return context;
    }
    
    @DB
    protected ConsoleProxyVO allocProxyStorage(long dataCenterId, long proxyVmId) {
        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
        assert (proxy != null);

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        HostPodVO pod = _podDao.findById(proxy.getPodId());
        final AccountVO account = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM);

        try {
            List vols = _storageMgr.create(account, proxy, _template, dc, pod, _serviceOffering, null, 0);
            if (vols == null) {
                s_logger.error("Unable to alloc storage for console proxy");
                return null;
            }

            Transaction txn = Transaction.currentTxn();
            txn.start();

            // update pool id
            ConsoleProxyVO vo = _consoleProxyDao.findById(proxy.getId());
            _consoleProxyDao.update(proxy.getId(), vo);

            // kick the state machine
            _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, null);

            txn.commit();
            return proxy;
        } catch (StorageUnavailableException e) {
            s_logger.error("Unable to alloc storage for console proxy: ", e);
            return null;
        } catch (ExecutionException e) {
            s_logger.error("Unable to alloc storage for console proxy: ", e);
            return null;
        }
    }

    private networkInfo allocPublicIpAddress(long dcId, long podId, String macAddr) {

        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            IpAddrAllocator.IpAddr ip = _IpAllocator.getPublicIpAddress(macAddr, dcId, podId);
            networkInfo net = new networkInfo(ip.ipaddr, ip.netMask, ip.gateway, null, "untagged");
            GsonBuilder gb = new GsonBuilder();
        Pair ipAndVlan = _vlanDao.assignIpAddress(dcId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN, VlanType.VirtualNetwork,
                true);

        if (ipAndVlan == null) {
            s_logger.debug("Unable to get public ip address (type=Virtual) for console proxy vm for data center  : " + dcId);
            private void reallyRun() {
            ipAndVlan = _vlanDao.assignPodDirectAttachIpAddress(dcId, podId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN);
            if (ipAndVlan == null)
                s_logger.debug("Unable to get public ip address (type=DirectAttach) for console proxy vm for data center  : " + dcId);
        }
        if (ipAndVlan != null) {
            VlanVO vlan = ipAndVlan.second();
            networkInfo net = new networkInfo(ipAndVlan.first(), vlan.getVlanNetmask(), vlan.getVlanGateway(), vlan.getId(), vlan.getVlanId());
            return net;
        }
        return null;
    }

    private String allocPrivateIpAddress(Long dcId, Long podId, Long proxyId, String macAddr) {
        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            return _IpAllocator.getPrivateIpAddress(macAddr, dcId, podId).ipaddr;
        } else {
            return _dcDao.allocatePrivateIpAddress(dcId, podId, proxyId);
        }
    }

    private void freePrivateIpAddress(String ipAddress, Long dcId, Long podId) {
        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            _IpAllocator.releasePrivateIpAddress(ipAddress, dcId, podId);
        } else {
            _dcDao.releasePrivateIpAddress(ipAddress, dcId, podId);
        }
    }

    private void freePublicIpAddress(String ipAddress, long dcId, long podId) {
        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            _IpAllocator.releasePublicIpAddress(ipAddress, dcId, podId);
        } else {
            _ipAddressDao.unassignIpAddress(ipAddress);
        }
    }

    private ConsoleProxyAllocator getCurrentAllocator() {
        // for now, only one adapter is supported
        Enumeration it = _consoleProxyAllocators.enumeration();
        if (it.hasMoreElements())
            return it.nextElement();

        return null;
    }

    protected String connect(String ipAddress, int port) {
        for (int i = 0; i <= _ssh_retry; i++) {
            SocketChannel sch = null;
            try {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Trying to connect to " + ipAddress);
                }
                sch = SocketChannel.open();
                sch.configureBlocking(true);
                sch.socket().setSoTimeout(5000);

                InetSocketAddress addr = new InetSocketAddress(ipAddress, port);
                sch.connect(addr);
                return null;
            } catch (IOException e) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Could not connect to " + ipAddress);
                }
            } finally {
                if (sch != null) {
                    try {
                        sch.close();
                    } catch (IOException e) {
                    }
                }
            }
            try {
                Thread.sleep(_ssh_sleep);
            } catch (InterruptedException ex) {
            }
        }

        s_logger.debug("Unable to logon to " + ipAddress);

        return "Unable to connect";
    }

    public void onLoadAnswer(ConsoleProxyLoadAnswer answer) {
        if (answer.getDetails() == null)
            return;

        ConsoleProxyStatus status = null;

            gb.setVersion(1.3);
            Gson gson = gb.create();
            status = gson.fromJson(answer.getDetails(), ConsoleProxyStatus.class);
        } catch (Throwable e) {
            s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + answer.getProxyVmId() + ", info : " + answer.getDetails());
        }

        if (status != null) {
            int count = 0;
            if (status.getConnections() != null)
                count = status.getConnections().length;

            byte[] details = null;
            if (answer.getDetails() != null)
                details = answer.getDetails().getBytes(Charset.forName("US-ASCII"));
            _consoleProxyDao.update(answer.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
        } else {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Unable to get console proxy load info, id : " + answer.getProxyVmId());

            _consoleProxyDao.update(answer.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
            // TODO : something is wrong with the VM, restart it?
        }
    }

    @Override
    public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
        if (cmd.getLoadInfo() == null)
            return;

        ConsoleProxyStatus status = null;
        try {
            GsonBuilder gb = new GsonBuilder();
            gb.setVersion(1.3);
            Gson gson = gb.create();
            status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class);
        } catch (Throwable e) {
            s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo());
        }

        if (status != null) {
            int count = 0;
            if (status.getConnections() != null)
                count = status.getConnections().length;

            byte[] details = null;
            if (cmd.getLoadInfo() != null)
                details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII"));
            _consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
        } else {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId());

            _consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
        }
    }

    @Override
    public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) {
        long vmId = 0;

        if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Invalid vm id sent from proxy(happens when proxy session has terminated)");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        try {
            vmId = Long.parseLong(cmd.getVmId());
        } catch (NumberFormatException e) {
            s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication", e);
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        // TODO authentication channel between console proxy VM and management
        // server needs to be secured,
        // the data is now being sent through private network, but this is
        // apparently not enough
        VMInstanceVO vm = _instanceDao.findById(vmId);
        if (vm == null) {
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        if (vm.getHostId() == null) {
            s_logger.warn("VM " + vmId + " lost host info, failed authentication request");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        HostVO host = _hostDao.findById(vm.getHostId());
        if (host == null) {
            s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        String sid = cmd.getSid();
        if (sid == null || !sid.equals(vm.getVncPassword())) {
            s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        return new ConsoleAccessAuthenticationAnswer(cmd, true);
    }

    private ConsoleProxyVO findConsoleProxyByHost(HostVO host) throws NumberFormatException {
        String name = host.getName();
        long proxyVmId = 0;
        ConsoleProxyVO proxy = null;
        if (name != null && name.startsWith("v-")) {
            String[] tokens = name.split("-");
            proxyVmId = Long.parseLong(tokens[1]);
            proxy = this._consoleProxyDao.findById(proxyVmId);
        }
        return proxy;
    }

    @Override
    public void onAgentConnect(HostVO host, StartupCommand cmd) {
        if (host.getType() == Type.ConsoleProxy) {
            // TODO we can use this event to mark the proxy is up and
            // functioning instead of
            // pinging the console proxy VM command port
            //
            // for now, just log a message
            if (s_logger.isInfoEnabled())
                s_logger.info("Console proxy agent is connected. proxy: " + host.getName());

            /* update public/private ip address */
            if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
                try {
                    ConsoleProxyVO console = findConsoleProxyByHost(host);
                    if (console == null) {
                        s_logger.debug("Can't find console proxy ");
                        return;
                    }
                    console.setPrivateIpAddress(cmd.getPrivateIpAddress());
                    console.setPrivateNetmask(cmd.getPrivateNetmask());
                    console.setPublicIpAddress(cmd.getPublicIpAddress());
                    console.setPublicNetmask(cmd.getPublicNetmask());
                    _consoleProxyDao.persist(console);
                } catch (NumberFormatException e) {
                }
            }
        }
    }

    @Override
    public void onAgentDisconnect(long agentId, com.cloud.host.Status state) {
        if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) {
            // be it either in alert or in disconnected state, the agent process
            // may be gone in the VM,
            // we will be reacting to stop the corresponding VM and let the scan
            // process to
            HostVO host = _hostDao.findById(agentId);
            if (host.getType() == Type.ConsoleProxy) {
                String name = host.getName();
                if (s_logger.isInfoEnabled())
                    s_logger.info("Console proxy agent disconnected, proxy: " + name);
                if (name != null && name.startsWith("v-")) {
                    String[] tokens = name.split("-");
                    long proxyVmId = 0;
                    try {
                        proxyVmId = Long.parseLong(tokens[1]);
                    } catch (NumberFormatException e) {
                        s_logger.error("Unexpected exception " + e.getMessage(), e);
                        return;
                    }

                    final ConsoleProxyVO proxy = this._consoleProxyDao.findById(proxyVmId);
                    if (proxy != null) {
                        Long hostId = proxy.getHostId();

                        // Disable this feature for now, as it conflicts with
                        // the case of allowing user to reboot console proxy
                        // when rebooting happens, we will receive disconnect
                        // here and we can't enter into stopping process,
                        // as when the rebooted one comes up, it will kick off a
        return false;
            return new StopCommand(vo, null);
                        // newly started one and trigger the process
                        // continue on forever

                        /*
    }
                         * _capacityScanScheduler.execute(new Runnable() {
                         * public void run() { if(s_logger.isInfoEnabled())
                         * s_logger.info("Stop console proxy " + proxy.getName()
                         * +
                         * " VM because of that the agent running inside it has disconnected"
                         * ); stopProxy(proxy.getId()); } });
                         */
                    } else {
                        if (s_logger.isInfoEnabled())
                            s_logger.info("Console proxy agent disconnected but corresponding console proxy VM no longer exists in DB, proxy: "
                                    + name);
                    }
                } else {
                    assert (false) : "Invalid console proxy name: " + name;
                }
            }
        }
    }

    private void checkPendingProxyVMs() {
        // drive state to change away from transient states
        List l = _consoleProxyDao.getProxyListInStates(State.Creating);
        if (l != null && l.size() > 0) {
            for (ConsoleProxyVO proxy : l) {
                if (proxy.getLastUpdateTime() == null
                        || (proxy.getLastUpdateTime() != null && System.currentTimeMillis() - proxy.getLastUpdateTime().getTime() > 60000)) {
                    try {
                        ConsoleProxyVO readyProxy = null;
                        if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                            try {
                                readyProxy = allocProxyStorage(proxy.getDataCenterId(), proxy.getId());
                            } finally {
                                _allocProxyLock.unlock();
                            }

                            if (readyProxy != null) {
                                GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(readyProxy.getId()));
                                try {
                                    if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                                        try {
                                            readyProxy = start(readyProxy.getId(), 0);
                                        } finally {
                                            proxyLock.unlock();
                                        }
                                    } else {
                                        if (s_logger.isInfoEnabled())
                                            s_logger.info("Unable to acquire synchronization lock to start console proxy : " + readyProxy.getName());
                                    }
                                } finally {
                                    proxyLock.releaseRef();
                                }
                            }
                        } else {
                            if (s_logger.isInfoEnabled())
                                s_logger.info("Unable to acquire synchronization lock to allocate proxy storage, wait for next turn");
                        }
                    } catch (StorageUnavailableException e) {
                        s_logger.warn("Storage unavailable", e);
                    } catch (InsufficientCapacityException e) {
                        s_logger.warn("insuffiient capacity", e);
                    } catch (ConcurrentOperationException e) {
                        s_logger.debug("Concurrent operation: " + e.getMessage());
                    }
                }
            }
        }
    }

    private Runnable getCapacityScanTask() {
        return new Runnable() {

            @Override
            public void run() {
                Transaction txn = Transaction.open(Transaction.CLOUD_DB);
                try {
                    reallyRun();
                } catch (Throwable e) {
                    s_logger.warn("Unexpected exception " + e.getMessage(), e);
                } finally {
                    StackMaid.current().exitCleanup();
                    txn.close();
                }
            }


                if (s_logger.isTraceEnabled())
                    s_logger.trace("Begin console proxy capacity scan");

                // config var for consoleproxy.restart check
                String restart = _configDao.getValue("consoleproxy.restart");
                if (restart != null && restart.equalsIgnoreCase("false")) {
                    s_logger.debug("Capacity scan disabled purposefully, consoleproxy.restart = false. This happens when the primarystorage is in maintenance mode");
                    return;
                }

                Map zoneHostInfoMap = getZoneHostInfo();
                if (isServiceReady(zoneHostInfoMap)) {
                    if (s_logger.isTraceEnabled())
                        s_logger.trace("Service is ready, check to see if we need to allocate standby capacity");

                    if (!_capacityScanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
                        if (s_logger.isTraceEnabled())
                            s_logger.trace("Capacity scan lock is used by others, skip and wait for my turn");
                        return;
                    }

                    if (s_logger.isTraceEnabled())
                        s_logger.trace("*** Begining capacity scan... ***");

                    try {
                        checkPendingProxyVMs();

                        // scan default data center first
                        long defaultId = 0;

                        // proxy count info by data-centers (zone-id, zone-name,
                        // count)
                        List l = _consoleProxyDao.getDatacenterProxyLoadMatrix();

                        // running VM session count by data-centers (zone-id,
                        // zone-name, count)
                        List listVmCounts = _consoleProxyDao.getDatacenterSessionLoadMatrix();

                        // indexing load info by data-center id
                        Map mapVmCounts = new HashMap();
                        if (listVmCounts != null)
                            for (ConsoleProxyLoadInfo info : listVmCounts)
                                mapVmCounts.put(info.getId(), info);

                        for (ConsoleProxyLoadInfo info : l) {
                            if (info.getName().equals(_instance)) {
                                ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId());

                                if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) {
                                    if (isZoneReady(zoneHostInfoMap, info.getId())) {
                                        allocCapacity(info.getId());
                                    } else {
                                        if (s_logger.isTraceEnabled())
                                            s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy");
                                    }
                                }

                                defaultId = info.getId();
                                break;
                            }
                        }

                        // scan rest of data-centers
                        for (ConsoleProxyLoadInfo info : l) {
                            if (info.getId() != defaultId) {
                                ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId());

                                if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) {
                                    if (isZoneReady(zoneHostInfoMap, info.getId())) {
                                        allocCapacity(info.getId());
                                    } else {
                                        if (s_logger.isTraceEnabled())
                                            s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy");
                                    }
                                }
                            }
                        }

                        if (s_logger.isTraceEnabled())
                            s_logger.trace("*** Stop capacity scan ***");
                    } finally {
                        _capacityScanLock.unlock();
                    }

                } else {
                    if (s_logger.isTraceEnabled())
                        s_logger.trace("Service is not ready for capacity preallocation, wait for next time");
                }

                if (s_logger.isTraceEnabled())
                    s_logger.trace("End of console proxy capacity scan");
            }
        };
    }

    private boolean checkCapacity(ConsoleProxyLoadInfo proxyCountInfo, ConsoleProxyLoadInfo vmCountInfo) {

        if (proxyCountInfo.getCount() * _capacityPerProxy - vmCountInfo.getCount() <= _standbyCapacity)
            return false;

        return true;
    }

    private void allocCapacity(long dataCenterId) {
        if (s_logger.isTraceEnabled())
            s_logger.trace("Allocate console proxy standby capacity for data center : " + dataCenterId);

        boolean proxyFromStoppedPool = false;
        ConsoleProxyVO proxy = assignProxyFromStoppedPool(dataCenterId);
        if (proxy == null) {
            if (s_logger.isInfoEnabled())
                s_logger.info("No stopped console proxy is available, need to allocate a new console proxy");

            if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                try {
                    proxy = startNew(dataCenterId);
                } finally {
                    _allocProxyLock.unlock();
                }
            } else {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Unable to acquire synchronization lock to allocate proxy resource for standby capacity, wait for next scan");
                return;
            }
        } else {
            if (s_logger.isInfoEnabled())
                s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId());
            proxyFromStoppedPool = true;
        }

        if (proxy != null) {
            long proxyVmId = proxy.getId();
            GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId));
            try {
                if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                    try {
                        proxy = startProxy(proxyVmId, 0);
                    } finally {
                        proxyLock.unlock();
                    }
                } else {
                    if (s_logger.isInfoEnabled())
                        s_logger.info("Unable to acquire synchronization lock to start proxy for standby capacity, proxy vm id : " + proxy.getId());
                    return;
                }
            } finally {
                proxyLock.releaseRef();
            }

            if (proxy == null) {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Unable to start console proxy for standby capacity, proxy vm Id : " + proxyVmId
                            + ", will recycle it and start a new one");

                if (proxyFromStoppedPool)
                    destroyProxy(proxyVmId, 0);
            } else {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Console proxy " + proxy.getName() + " is started");
            }
        }
    }

    public boolean isServiceReady(Map zoneHostInfoMap) {
        for (ZoneHostInfo zoneHostInfo : zoneHostInfoMap.values()) {
            if (isZoneHostReady(zoneHostInfo)) {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Zone " + zoneHostInfo.getDcId() + " is ready to launch");
                return true;
            }
        }
    public boolean isZoneReady(Map zoneHostInfoMap, long dataCenterId) {
        ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
        if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
            VMTemplateVO template = _templateDao.findConsoleProxyTemplate();
            HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(dataCenterId);
            boolean templateReady = false;

            if (template != null && secondaryStorageHost != null) {
                VMTemplateHostVO templateHostRef = _vmTemplateHostDao.findByHostTemplate(secondaryStorageHost.getId(), template.getId());
                templateReady = (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED);
            }

            if (templateReady) {
                List> l = _consoleProxyDao.getDatacenterStoragePoolHostInfo(dataCenterId, _use_lvm);
                if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) {
                    return true;
                } else {
                    if (s_logger.isTraceEnabled())
                        s_logger.trace("Primary storage is not ready, wait until it is ready to launch console proxy");
                }
            } else {
                if (s_logger.isTraceEnabled())
                    s_logger.trace("Zone host is ready, but console proxy template is not ready");
            }
        }
        return false;
    }

    private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) {
        int expectedFlags = 0;
        if (_use_storage_vm)
            expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK;
        else
            expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ALL_HOST_MASK;

        return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags;
    }

    private synchronized Map getZoneHostInfo() {
        Date cutTime = DateUtil.currentGMTTime();
        List l = _hostDao.getRunningHostCounts(new Date(cutTime.getTime() - ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD));

        RunningHostInfoAgregator aggregator = new RunningHostInfoAgregator();
        if (l.size() > 0)
            for (RunningHostCountInfo countInfo : l)
                aggregator.aggregate(countInfo);

        return aggregator.getZoneHostInfoMap();
    }

    @Override
    public String getName() {
        return _name;
    }

    @Override
    public boolean start() {
        if (s_logger.isInfoEnabled())
            s_logger.info("Start console proxy manager");

        return true;
    }

    @Override
    public boolean stop() {
        if (s_logger.isInfoEnabled())
            s_logger.info("Stop console proxy manager");
        _capacityScanScheduler.shutdownNow();

        try {
            _capacityScanScheduler.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
        }

        _capacityScanLock.releaseRef();
        _allocProxyLock.releaseRef();
        return true;
    }

    @Override
    public Command cleanup(ConsoleProxyVO vm, String vmName) {
        if (vmName != null) {
            return new StopCommand(vm, vmName, VirtualMachineName.getVnet(vmName));
        } else if (vm != null) {
            ConsoleProxyVO vo = vm;
            throw new CloudRuntimeException("Shouldn't even be here!");
        }
    }

    @Override
    public void completeStartCommand(ConsoleProxyVO vm) {
        _consoleProxyDao.updateIf(vm, Event.AgentReportRunning, vm.getHostId());
    }

    @Override
    public void completeStopCommand(ConsoleProxyVO vm) {
        completeStopCommand(vm, Event.AgentReportStopped);
    }

    @DB
    protected void completeStopCommand(ConsoleProxyVO proxy, Event ev) {
        Transaction txn = Transaction.currentTxn();
        try {
            txn.start();
            String privateIpAddress = proxy.getPrivateIpAddress();
            if (privateIpAddress != null) {
                proxy.setPrivateIpAddress(null);
                freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
            }
            String guestIpAddress = proxy.getGuestIpAddress();
            if (guestIpAddress != null) {
                proxy.setGuestIpAddress(null);
                _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId());
            }

            if (!_consoleProxyDao.updateIf(proxy, ev, null)) {
                s_logger.debug("Unable to update the console proxy");
                return;
            }
            txn.commit();
        } catch (Exception e) {
            s_logger.error("Unable to complete stop command due to ", e);
        }

        if (_storageMgr.unshare(proxy, null) == null) {
            s_logger.warn("Unable to set share to false for " + proxy.getId());
        }
    }

    @Override
    public ConsoleProxyVO get(long id) {
        return _consoleProxyDao.findById(id);
    }

    @Override
    public Long convertToId(String vmName) {
        if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) {
            return null;
        }
        return VirtualMachineName.getConsoleProxyId(vmName);
    }

    @Override
    public boolean stopProxy(long proxyVmId, long startEventId) {

        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("Stop console proxy " + proxyVmId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId);
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
        if (proxy == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Stopping console proxy failed: console proxy " + proxyVmId + " no longer exists");
            return false;
        }
        /*
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_STOP, "Stopping console proxy with Id: " +
         * proxyVmId, startEventId);
         */
        try {
            return stop(proxy, startEventId);
        } catch (AgentUnavailableException e) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Stopping console proxy " + proxy.getName() + " faled : exception " + e.toString());
            return false;
        }
    }

    @Override
    public boolean rebootProxy(long proxyVmId, long startEventId) {
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
        _storageMgr.unshare(proxy, fromHost);
                s_logger.info("Reboot console proxy " + proxyVmId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId);
        }

        final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);

        if (proxy == null || proxy.getState() == State.Destroyed) {
            return false;
        }

        /*
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: " +
         * proxyVmId, startEventId);
         */
        if (proxy.getState() == State.Running && proxy.getHostId() != null) {
            final RebootCommand cmd = new RebootCommand(proxy.getInstanceName());
            final Answer answer = _agentMgr.easySend(proxy.getHostId(), cmd);

            if (answer != null) {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Successfully reboot console proxy " + proxy.getName());

                SubscriptionMgr.getInstance()
                        .notifySubscribers(
                                ConsoleProxyManager.ALERT_SUBJECT,
                                this,
                                new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_REBOOTED, proxy.getDataCenterId(), proxy.getId(),
                                        proxy, null));

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_REBOOT);
                event.setLevel(EventVO.LEVEL_INFO);
                event.setStartId(startEventId);
                event.setDescription("Console proxy rebooted - " + proxy.getName());
                _eventDao.persist(event);
                return true;
            } else {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("failed to reboot console proxy : " + proxy.getName());

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_REBOOT);
                event.setLevel(EventVO.LEVEL_ERROR);
                event.setStartId(startEventId);
                event.setDescription("Rebooting console proxy failed - " + proxy.getName());
                _eventDao.persist(event);
                return false;
            }
        } else {
            return startProxy(proxyVmId, 0) != null;
        }
    }

    @Override
    public boolean destroy(ConsoleProxyVO proxy) throws AgentUnavailableException {
        return destroyProxy(proxy.getId(), 0);
    }

    @Override
    @DB
    public boolean destroyProxy(long vmId, long startEventId) {
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("Destroy console proxy " + vmId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", vmId);
        }

        ConsoleProxyVO vm = _consoleProxyDao.findById(vmId);
        if (vm == null || vm.getState() == State.Destroyed) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vmId);
            }
            return true;
        }
        /*
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_DESTROY, "Destroying console proxy with Id: "
         * + vmId, startEventId);
         */
        if (s_logger.isDebugEnabled()) {

        return true;
            s_logger.debug("Destroying console proxy vm " + vmId);
        }

        if (!_consoleProxyDao.updateIf(vm, Event.DestroyRequested, null)) {
            s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vmId);
            return false;
        }

        Transaction txn = Transaction.currentTxn();
        List vols = null;
        try {
            vols = _volsDao.findByInstance(vmId);
            if (vols.size() != 0) {
                _storageMgr.destroy(vm, vols);
            }

            return true;
        } finally {
            try {
                txn.start();
                // release critical system resources used by the VM before we
                // delete them
                if (vm.getPublicIpAddress() != null)
                    freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId());
                vm.setPublicIpAddress(null);

                _consoleProxyDao.remove(vm.getId());

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_DESTROY);
                event.setLevel(EventVO.LEVEL_INFO);
                event.setStartId(startEventId);
                event.setDescription("Console proxy destroyed - " + vm.getName());
                _eventDao.persist(event);

                txn.commit();
            } catch (Exception e) {
                s_logger.error("Caught this error: ", e);
                txn.rollback();
                return false;
            } finally {
                s_logger.debug("console proxy vm is destroyed : " + vm.getName());
            }
        }
    }

    @DB
    public boolean destroyProxyDBOnly(long vmId) {
        Transaction txn = Transaction.currentTxn();
        try {
            txn.start();
            _volsDao.deleteVolumesByInstance(vmId);

            ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId);
            if (proxy != null) {
                if (proxy.getPublicIpAddress() != null)
                    freePublicIpAddress(proxy.getPublicIpAddress(), proxy.getDataCenterId(), proxy.getPodId());

                _consoleProxyDao.remove(vmId);

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_DESTROY);
                event.setLevel(EventVO.LEVEL_INFO);
                event.setDescription("Console proxy destroyed - " + proxy.getName());
                _eventDao.persist(event);
            }

            txn.commit();
            return true;
        } catch (Exception e) {
            s_logger.error("Caught this error: ", e);
            txn.rollback();
            return false;
        } finally {
            s_logger.debug("console proxy vm is destroyed from DB : " + vmId);
        }
    }

    @Override
    public boolean stop(ConsoleProxyVO proxy, long startEventId) throws AgentUnavailableException {
        if (!_consoleProxyDao.updateIf(proxy, Event.StopRequested, proxy.getHostId())) {
            s_logger.debug("Unable to stop console proxy: " + proxy.toString());
            return false;
        }

        // IPAddressVO ip = _ipAddressDao.findById(proxy.getPublicIpAddress());
        // VlanVO vlan = _vlanDao.findById(new Long(ip.getVlanDbId()));

        GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxy.getId()));
        try {

            if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                try {
                    StopCommand cmd = new StopCommand(proxy, true, Integer.toString(_consoleProxyPort), Integer.toString(_consoleProxyUrlPort),
                            proxy.getPublicIpAddress());
                    try {
                        Long proxyHostId = proxy.getHostId();
                        if (proxyHostId == null) {
                            s_logger.debug("Unable to stop due to proxy " + proxy.getId()
                                    + " as host is no longer available, proxy may already have been stopped");
                            return false;
                        }
                        StopAnswer answer = (StopAnswer) _agentMgr.send(proxyHostId, cmd);
                        if (answer == null || !answer.getResult()) {
                            s_logger.debug("Unable to stop due to " + (answer == null ? "answer is null" : answer.getDetails()));

                            final EventVO event = new EventVO();
                            event.setUserId(User.UID_SYSTEM);
                            event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                            event.setType(EventTypes.EVENT_PROXY_STOP);
                            event.setLevel(EventVO.LEVEL_ERROR);
                            event.setStartId(startEventId);
                            event.setDescription("Stopping console proxy failed due to negative answer from agent - " + proxy.getName());
                            _eventDao.persist(event);
                            return false;
                        }
                        completeStopCommand(proxy, Event.OperationSucceeded);

                        SubscriptionMgr.getInstance().notifySubscribers(
                                ConsoleProxyManager.ALERT_SUBJECT,
                                this,
                                new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_DOWN, proxy.getDataCenterId(), proxy.getId(), proxy,
                                        null));

                        final EventVO event = new EventVO();
                        event.setUserId(User.UID_SYSTEM);
                        event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                        event.setType(EventTypes.EVENT_PROXY_STOP);
                        event.setLevel(EventVO.LEVEL_INFO);
                        event.setStartId(startEventId);
                        event.setDescription("Console proxy stopped - " + proxy.getName());
                        _eventDao.persist(event);
                        return true;
                    } catch (OperationTimedoutException e) {
                        final EventVO event = new EventVO();
                        event.setUserId(User.UID_SYSTEM);
                        event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                        event.setType(EventTypes.EVENT_PROXY_STOP);
                        event.setLevel(EventVO.LEVEL_ERROR);
                        event.setStartId(startEventId);
                        event.setDescription("Stopping console proxy failed due to operation time out - " + proxy.getName());
                        _eventDao.persist(event);
                        throw new AgentUnavailableException(proxy.getHostId());
                    }
                } finally {
                    proxyLock.unlock();
                }
            } else {
                s_logger.debug("Unable to acquire console proxy lock : " + proxy.toString());
                return false;
            }
        } finally {
            proxyLock.releaseRef();
        }
    }

    @Override
    public boolean migrate(ConsoleProxyVO proxy, HostVO host) {
        HostVO fromHost = _hostDao.findById(proxy.getId());

        if (!_consoleProxyDao.updateIf(proxy, Event.MigrationRequested, proxy.getHostId())) {
            s_logger.debug("State for " + proxy.toString() + " has changed so migration can not take place.");
            return false;
        }

        MigrateCommand cmd = new MigrateCommand(proxy.getInstanceName(), host.getPrivateIpAddress(), false);
        Answer answer = _agentMgr.easySend(fromHost.getId(), cmd);
        if (answer == null) {
            return false;
        }

    }

    @Override
    public boolean completeMigration(ConsoleProxyVO proxy, HostVO host) throws AgentUnavailableException, OperationTimedoutException {

        CheckVirtualMachineCommand cvm = new CheckVirtualMachineCommand(proxy.getInstanceName());
        CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(host.getId(), cvm);
        if (!answer.getResult()) {
            s_logger.debug("Unable to complete migration for " + proxy.getId());
            _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null);
            return false;
        }

        State state = answer.getState();
        if (state == State.Stopped) {
            s_logger.warn("Unable to complete migration as we can not detect it on " + host.getId());
            _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null);
            return false;
        }

        _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, host.getId());
        return true;
    }

    @Override
    public HostVO prepareForMigration(ConsoleProxyVO proxy) throws StorageUnavailableException {

        VMTemplateVO template = _templateDao.findById(proxy.getTemplateId());
        long routerId = proxy.getId();
        boolean mirroredVols = proxy.isMirroredVols();
        DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId());
        HostPodVO pod = _podDao.findById(proxy.getPodId());
        List sps = _storageMgr.getStoragePoolsForVm(proxy.getId());
        StoragePoolVO sp = sps.get(0); // FIXME

        List vols = _volsDao.findCreatedByInstance(routerId);

        String[] storageIps = new String[2];
        VolumeVO vol = vols.get(0);
        storageIps[0] = vol.getHostIp();
        if (mirroredVols && (vols.size() == 2)) {
            storageIps[1] = vols.get(1).getHostIp();
        }

        PrepareForMigrationCommand cmd = new PrepareForMigrationCommand(proxy.getName(), null, storageIps, vols, mirroredVols);

        HostVO routingHost = null;
        HashSet avoid = new HashSet();

        HostVO fromHost = _hostDao.findById(proxy.getHostId());
        if (fromHost.getClusterId() == null) {
            s_logger.debug("The host is not in a cluster");
            return null;
        }
        avoid.add(fromHost);

        while ((routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, template, proxy, fromHost, avoid)) != null) {
            avoid.add(routingHost);

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Trying to migrate router to host " + routingHost.getName());
            }

            if (!_storageMgr.share(proxy, vols, routingHost, false)) {
                s_logger.warn("Can not share " + proxy.getName());
                throw new StorageUnavailableException(vol.getPoolId());
            }

            Answer answer = _agentMgr.easySend(routingHost.getId(), cmd);
            if (answer != null && answer.getResult()) {
                return routingHost;
            }
            _storageMgr.unshare(proxy, vols, routingHost);
        }

        return null;
    }

    private String getCapacityScanLockName() {
        // to improve security, it may be better to return a unique mashed
        // name(for example MD5 hashed)
        return "consoleproxy.capacity.scan";
    }

    private String getAllocProxyLockName() {
        // to improve security, it may be better to return a unique mashed
        // name(for example MD5 hashed)
        return "consoleproxy.alloc";
    }

    private String getProxyLockName(long id) {
        return "consoleproxy." + id;
    }
    private Long saveStartedEvent(Long userId, Long accountId, String type, String description, long startEventId) {
        EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(accountId);
        event.setType(type);
        event.setState(EventState.Started);
        event.setDescription(description);
        event.setStartId(startEventId);
        event = _eventDao.persist(event);
        if (event != null)
            return event.getId();
        return null;
    }

    @Override
    public boolean configure(String name, Map params) throws ConfigurationException {
        if (s_logger.isInfoEnabled())
            s_logger.info("Start configuring console proxy manager : " + name);

        _name = name;

        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
        if (configDao == null) {
            throw new ConfigurationException("Unable to get the configuration dao.");
        }

        Map configs = configDao.getConfiguration("management-server", params);

        _proxyRamSize = NumbersUtil.parseInt(configs.get("consoleproxy.ram.size"), DEFAULT_PROXY_VM_RAMSIZE);

        String value = configs.get("start.retry");
        _find_host_retry = NumbersUtil.parseInt(value, DEFAULT_FIND_HOST_RETRY_COUNT);

        value = configs.get("consoleproxy.cmd.port");
        _proxyCmdPort = NumbersUtil.parseInt(value, DEFAULT_PROXY_CMD_PORT);

        value = configs.get("consoleproxy.sslEnabled");
        if (value != null && value.equalsIgnoreCase("true"))
            _sslEnabled = true;

        value = configs.get("consoleproxy.capacityscan.interval");
        _capacityScanInterval = NumbersUtil.parseLong(value, DEFAULT_CAPACITY_SCAN_INTERVAL);

        _capacityPerProxy = NumbersUtil.parseInt(configs.get("consoleproxy.session.max"), DEFAULT_PROXY_CAPACITY);
        _standbyCapacity = NumbersUtil.parseInt(configs.get("consoleproxy.capacity.standby"), DEFAULT_STANDBY_CAPACITY);
        _proxySessionTimeoutValue = NumbersUtil.parseInt(configs.get("consoleproxy.session.timeout"), DEFAULT_PROXY_SESSION_TIMEOUT);

        value = configs.get("consoleproxy.port");
        if (value != null)
            _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT);

        value = configs.get("consoleproxy.url.port");
        if (value != null)
            _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT);

        value = configs.get("system.vm.use.local.storage");
        if (value != null && value.equalsIgnoreCase("true"))
            _use_lvm = true;

        value = configs.get("secondary.storage.vm");
        if (value != null && value.equalsIgnoreCase("true"))
            _use_storage_vm = true;

        if (s_logger.isInfoEnabled()) {
            s_logger.info("Console proxy max session soft limit : " + _capacityPerProxy);
            s_logger.info("Console proxy standby capacity : " + _standbyCapacity);
        }

        _domain = configs.get("domain");
        if (_domain == null) {
            _domain = "foo.com";
        }

        _instance = configs.get("instance.name");
        if (_instance == null) {
            _instance = "DEFAULT";
        }

        value = (String) params.get("ssh.sleep");
        _ssh_sleep = NumbersUtil.parseInt(value, 5) * 1000;

        value = (String) params.get("ssh.retry");
        _ssh_retry = NumbersUtil.parseInt(value, 3);

        Map agentMgrConfigs = configDao.getConfiguration("AgentManager", params);
        _mgmt_host = agentMgrConfigs.get("host");
        if (_mgmt_host == null) {
            s_logger.warn("Critical warning! Please configure your management server host address right after you have started your management server and then restart it, otherwise you won't be able to do console access");
        }

        value = agentMgrConfigs.get("port");
        _mgmt_port = NumbersUtil.parseInt(value, 8250);

        _consoleProxyAllocators = locator.getAdapters(ConsoleProxyAllocator.class);
        if (_consoleProxyAllocators == null || !_consoleProxyAllocators.isSet()) {
            throw new ConfigurationException("Unable to get proxy allocators");
        }

        _listener = new ConsoleProxyListener(this);
        _agentMgr.registerForHostEvents(_listener, true, true, false);

        Adapters ipAllocators = locator.getAdapters(IpAddrAllocator.class);
        if (ipAllocators != null && ipAllocators.isSet()) {
            Enumeration it = ipAllocators.enumeration();
            _IpAllocator = it.nextElement();
        }

        HighAvailabilityManager haMgr = locator.getManager(HighAvailabilityManager.class);
        if (haMgr != null) {
            haMgr.registerHandler(VirtualMachine.Type.ConsoleProxy, this);
        }

        boolean useLocalStorage = Boolean.parseBoolean((String) params.get(Config.SystemVMUseLocalStorage.key()));
        String networkRateStr = _configDao.getValue("network.throttling.rate");
        String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
        _networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr));
        _multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr));
        _serviceOffering = new ServiceOfferingVO("Fake Offering For DomP", 1, _proxyRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized,
                useLocalStorage, true, null);
        _serviceOffering.setUniqueName("Cloud.com-ConsoleProxy");
        _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering);
        _template = _templateDao.findConsoleProxyTemplate();
        if (_template == null) {
            throw new ConfigurationException("Unable to find the template for console proxy VMs");
        }
        
        _capacityScanScheduler.scheduleAtFixedRate(getCapacityScanTask(), STARTUP_DELAY, _capacityScanInterval, TimeUnit.MILLISECONDS);

        if (s_logger.isInfoEnabled())
            s_logger.info("Console Proxy Manager is configured.");
        return true;
    }

    protected ConsoleProxyManagerImpl() {
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
// because sooner or later, it will be driven into Running state
//
@Local(value = { ConsoleProxyManager.class })
public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMachineManager, AgentHook {
    private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class);

    private static final int DEFAULT_FIND_HOST_RETRY_COUNT = 2;
    private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30
    // seconds
    private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1000; // 1 second

    private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3
    // seconds
    private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC = 180; // 3
    // minutes

    private static final int API_WAIT_TIMEOUT = 5000; // 5 seconds (in
    // milliseconds)
    private static final int STARTUP_DELAY = 60000; // 60 seconds

    private int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT;
    private int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT;

    private String _mgmt_host;
    private int _mgmt_port = 8250;

    private String _name;
    private Adapters _consoleProxyAllocators;

    @Inject
    private ConsoleProxyDao _consoleProxyDao;
    @Inject
    private DataCenterDao _dcDao;
    @Inject
    private VlanDao _vlanDao;
    @Inject
    private VMTemplateDao _templateDao;
    @Inject
    private IPAddressDao _ipAddressDao;
    @Inject
    private VolumeDao _volsDao;
    @Inject
    private HostPodDao _podDao;
    @Inject

    private HostDao _hostDao;
    @Inject
    private ConfigurationDao _configDao;

    @Inject
    private VMInstanceDao _instanceDao;
    @Inject
    private AccountDao _accountDao;

    @Inject
    private VMTemplateHostDao _vmTemplateHostDao;

    @Inject
    private AgentManager _agentMgr;
    @Inject
    private StorageManager _storageMgr;
    @Inject
    private HighAvailabilityManager _haMgr;
    @Inject NetworkManager _networkMgr;
    
    @Inject AccountManager _accountMgr;
    @Inject
    private EventDao _eventDao;
    @Inject
    ServiceOfferingDao _offeringDao;
    @Inject
    NetworkOfferingDao _networkOfferingDao;
    private IpAddrAllocator _IpAllocator;

    private ConsoleProxyListener _listener;

    private ServiceOfferingVO _serviceOffering;
    private int _networkRate;
    private int _multicastRate;
    private VMTemplateVO _template;
    
    NetworkOfferingVO _publicNetworkOffering;
    NetworkOfferingVO _managementNetworkOffering;
    NetworkOfferingVO _linkLocalNetworkOffering;

    @Inject
    private AsyncJobManager _asyncMgr;
    
    @Inject
    private VmManager _vmMgr;

    private final ScheduledExecutorService _capacityScanScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("CP-Scan"));
    private final ExecutorService _requestHandlerScheduler = Executors.newCachedThreadPool(new NamedThreadFactory("Request-handler"));

    private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL;
    private int _capacityPerProxy = ConsoleProxyManager.DEFAULT_PROXY_CAPACITY;
    }
    private int _standbyCapacity = ConsoleProxyManager.DEFAULT_STANDBY_CAPACITY;

    private int _proxyRamSize;
    private int _find_host_retry = DEFAULT_FIND_HOST_RETRY_COUNT;
    private int _ssh_retry;
    private int _ssh_sleep;
    private boolean _use_lvm;
    private boolean _use_storage_vm;

    private String _domain;
    private String _instance;

    // private String _privateNetmask;
    private int _proxyCmdPort = DEFAULT_PROXY_CMD_PORT;
    private int _proxySessionTimeoutValue = DEFAULT_PROXY_SESSION_TIMEOUT;
    private boolean _sslEnabled = false;

    private final GlobalLock _capacityScanLock = GlobalLock.getInternLock(getCapacityScanLockName());
    private final GlobalLock _allocProxyLock = GlobalLock.getInternLock(getAllocProxyLockName());

    @Override
    public ConsoleProxyInfo assignProxy(final long dataCenterId, final long vmId) {

        final Pair result = new Pair(this, null);

        _requestHandlerScheduler.execute(new Runnable() {
            @Override
            public void run() {
                Transaction txn = Transaction.open(Transaction.CLOUD_DB);
                try {
                    ConsoleProxyVO proxy = doAssignProxy(dataCenterId, vmId);
                    synchronized (result) {
                        result.second(proxy);
                        result.notifyAll();
                    }
                } catch (Throwable e) {
                    s_logger.warn("Unexpected exception " + e.getMessage(), e);
                } finally {
                    StackMaid.current().exitCleanup();
                    txn.close();
                }
            }
        });

        synchronized (result) {
            try {
                result.wait(API_WAIT_TIMEOUT);
            } catch (InterruptedException e) {
                s_logger.info("Waiting for console proxy assignment is interrupted");
            }
        }
        
        ConsoleProxyVO proxy = result.second();
        if (proxy == null)
            return null;
        
        return new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), _consoleProxyPort, proxy.getPort());
    }

    public ConsoleProxyVO doAssignProxy(long dataCenterId, long vmId) {
        ConsoleProxyVO proxy = null;
        VMInstanceVO vm = _instanceDao.findById(vmId);
        if (vm == null) {
            s_logger.warn("VM " + vmId + " no longer exists, return a null proxy for vm:" + vmId);
            return null;
        }

        Boolean[] proxyFromStoppedPool = new Boolean[1];
        if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
            try {
                proxy = getOrAllocProxyResource(dataCenterId, vmId, proxyFromStoppedPool);
            } finally {
                _allocProxyLock.unlock();
            }
        } else {
            s_logger.error("Unable to acquire synchronization lock to get/allocate proxy resource for vm :" + vmId
                    + ". Previous console proxy allocation is taking too long");
        }

        if (proxy == null) {
            s_logger.warn("Unable to find or allocate console proxy resource");
            return null;
        }

        long proxyVmId = proxy.getId();
        GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId));
        try {
            if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                try {
                    proxy = startProxy(proxyVmId, 0);

                    if (proxy == null) {
                        //

                        // We had a situation with multi-pod configuration,
                        // where
                        // storage allocation of the console proxy VM may
                        // succeed, but later-on starting of it
                        // may fail because of running out of computing resource
                        // (CPU/memory). We
                        // currently don't support moving storage to another pod
                        // on the fly, to deal
                        // with the situation we will destroy this proxy VM and
                        // let it the whole proxy VM
                        // creation process re-start again, by hoping that new
                        // storage and computing
                        // resource may be allocated and assigned in another pod
                        //
                        if (s_logger.isInfoEnabled())
                            s_logger.info("Unable to start console proxy, proxy vm Id : " + proxyVmId + " will recycle it and restart a new one");
                        destroyProxy(proxyVmId, 0);
                        return null;
                    } else {
                        if (s_logger.isTraceEnabled())
                            s_logger.trace("Console proxy " + proxy.getName() + " is started");

                        // if it is a new assignment or a changed assignment,
                        // update the
                        // record
                        if (vm.getProxyId() == null || vm.getProxyId().longValue() != proxy.getId())
                            _instanceDao.updateProxyId(vmId, proxy.getId(), DateUtil.currentGMTTime());

                        proxy.setSslEnabled(_sslEnabled);
                        if (_sslEnabled)
                            proxy.setPort(443);
                        else
                            proxy.setPort(80);
                        return proxy;
                    }
                } finally {
                    proxyLock.unlock();
                }
            } else {
                s_logger.error("Unable to acquire synchronization lock to start console proxy " + proxyVmId + " for vm: " + vmId
                        + ". It takes too long to start the proxy");
                return null;
            }
        } finally {
            proxyLock.releaseRef();
        }
    }

    private ConsoleProxyVO getOrAllocProxyResource(long dataCenterId, long vmId, Boolean[] proxyFromStoppedPool) {
        ConsoleProxyVO proxy = null;
        VMInstanceVO vm = this._instanceDao.findById(vmId);

        if (vm != null && vm.getState() != State.Running) {
            if (s_logger.isInfoEnabled())
                s_logger.info("Detected that vm : " + vmId + " is not currently at running state, we will fail the proxy assignment for it");
            return null;
        }

        if (vm != null && vm.getProxyId() != null) {
            proxy = _consoleProxyDao.findById(vm.getProxyId());

            if (proxy != null) {
                if (!isInAssignableState(proxy)) {
                    if (s_logger.isInfoEnabled())
                        s_logger.info("A previous assigned proxy is not assignable now, reassign console proxy for user vm : " + vmId);
                    proxy = null;
                } else {
                    if (_consoleProxyDao.getProxyActiveLoad(proxy.getId()) < _capacityPerProxy || hasPreviousSession(proxy, vm)) {
                        if (s_logger.isTraceEnabled())
                            s_logger.trace("Assign previous allocated console proxy for user vm : " + vmId);

                        if (proxy.getActiveSession() >= _capacityPerProxy)
                            s_logger.warn("Assign overloaded proxy to user VM as previous session exists, user vm : " + vmId);
                    } else {
                        proxy = null;
                    }
                }
            }
        }

        if (proxy == null)
            proxy = assignProxyFromRunningPool(dataCenterId);

        if (proxy == null) {
            if (s_logger.isInfoEnabled())
                s_logger.info("No running console proxy is available, check to see if we can bring up a stopped one for data center : "
                        + dataCenterId);

            proxy = assignProxyFromStoppedPool(dataCenterId);
            if (proxy == null) {
                if (s_logger.isInfoEnabled())
                    s_logger.info("No stopped console proxy is available, need to allocate a new console proxy for data center : " + dataCenterId);

                proxy = startNew(dataCenterId);
            } else {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId() + ", data center : "
                            + dataCenterId);

                proxyFromStoppedPool[0] = new Boolean(true);
            }
        }

        return proxy;
    }

    private static boolean isInAssignableState(ConsoleProxyVO proxy) {
        // console proxies that are in states of being able to serve user VM
        State state = proxy.getState();
        if (state == State.Running || state == State.Starting || state == State.Creating || state == State.Migrating)
            return true;

        return false;
    }

    private boolean hasPreviousSession(ConsoleProxyVO proxy, VMInstanceVO vm) {

        ConsoleProxyStatus status = null;
        try {
            GsonBuilder gb = new GsonBuilder();
            gb.setVersion(1.3);
            Gson gson = gb.create();

            byte[] details = proxy.getSessionDetails();
            status = gson.fromJson(details != null ? new String(details, Charset.forName("US-ASCII")) : null, ConsoleProxyStatus.class);
        } catch (Throwable e) {
            s_logger.warn("Unable to parse proxy session details : " + proxy.getSessionDetails());
        }

        if (status != null && status.getConnections() != null) {

            ConsoleProxyConnectionInfo[] connections = status.getConnections();
            for (int i = 0; i < connections.length; i++) {
                long taggedVmId = 0;
                if (connections[i].tag != null) {
                    try {
                        taggedVmId = Long.parseLong(connections[i].tag);
                    } catch (NumberFormatException e) {
                        s_logger.warn("Unable to parse console proxy connection info passed through tag: " + connections[i].tag, e);
                    }
                }
                if (taggedVmId == vm.getId())
                    return true;
            }

            //
            // even if we are not in the list, it may because we haven't
            // received load-update yet
            // wait until session time
            //
            if (DateUtil.currentGMTTime().getTime() - vm.getProxyAssignTime().getTime() < _proxySessionTimeoutValue)
                return true;

            return false;
        } else {
            s_logger.error("No proxy load info on an overloaded proxy ?");
            return false;
        }
    }
    
    @Override
    public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) {
        try {
            return start(proxyVmId, startEventId);
        } catch (StorageUnavailableException e) {
            s_logger.warn("Exception while trying to start console proxy", e);
            return null;
        } catch (InsufficientCapacityException e) {
            s_logger.warn("Exception while trying to start console proxy", e);
            return null;
        } catch (ConcurrentOperationException e) {
            s_logger.warn("Exception while trying to start console proxy", e);
            return null;
        }
    }

    public ConsoleProxyVO start2(long proxyVmId, long startEventId) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
        DeploymentPlan plan = new DataCenterDeployment(proxy.getDataCenterId(), 1);
        return _vmMgr.start(proxy, plan);
    }

    @Override
    @DB
    public ConsoleProxyVO start(long proxyId, long startEventId) throws StorageUnavailableException, InsufficientCapacityException,
            ConcurrentOperationException {

        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("Start console proxy " + proxyId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyId);
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId);
        if (proxy == null || proxy.getRemoved() != null) {
            s_logger.debug("proxy is not found: " + proxyId);
            return null;
        }
        /*
         * // don't insert event here, it may be called multiple times!
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: " +
         * proxyId, startEventId);
         */

        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Starting console proxy if it is not started, proxy vm id : " + proxyId);
        }

        for (int i = 0; i < 2; i++) {

            State state = proxy.getState();

            if (state == State.Starting /* || state == State.Migrating */) {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Waiting console proxy to be ready, proxy vm id : " + proxyId + " proxy VM state : " + state.toString());

            byte[] details = null;
                if (proxy.getPrivateIpAddress() == null || connect(proxy.getPrivateIpAddress(), _proxyCmdPort) != null) {
                    if (proxy.getPrivateIpAddress() == null)
                        s_logger.warn("Retruning a proxy that is being started but private IP has not been allocated yet, proxy vm id : " + proxyId);
                    else
                        s_logger.warn("Waiting console proxy to be ready timed out, proxy vm id : " + proxyId);

                    // TODO, it is very tricky here, if the startup process
                    // takes too long and it timed out here,
                    // we may give back a proxy that is not fully ready for
                    // functioning
                }
                return proxy;
            }

            if (state == State.Running) {
                if (s_logger.isTraceEnabled())
                    s_logger.trace("Console proxy is already started: " + proxy.getName());
                return proxy;
            }

            DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId());
            HostPodVO pod = _podDao.findById(proxy.getPodId());
            List sps = _storageMgr.getStoragePoolsForVm(proxy.getId());
            StoragePoolVO sp = sps.get(0); // FIXME

            HashSet avoid = new HashSet();
            HostVO routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, _template, proxy, null, avoid);

            if (routingHost == null) {
                if (s_logger.isDebugEnabled()) {
                    String msg = "Unable to find a routing host for " + proxy.toString() + " in pod " + pod.getId();
                    s_logger.debug(msg);
                    throw new CloudRuntimeException(msg);
                }
            }
            // to ensure atomic state transition to Starting state
            if (!_consoleProxyDao.updateIf(proxy, Event.StartRequested, routingHost.getId())) {
                if (s_logger.isDebugEnabled()) {
            context.put("proxyVmId", (long) 0);
                    ConsoleProxyVO temp = _consoleProxyDao.findById(proxyId);
                    s_logger.debug("Unable to start console proxy " + proxy.getName() + " because it is not in a startable state : "
                            + ((temp != null) ? temp.getState().toString() : "null"));
                }
                continue;
            }

            try {
                Answer answer = null;
                int retry = _find_host_retry;

                // Console proxy VM will be running at routing hosts as routing
                // hosts have public access to outside network
                do {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Trying to start console proxy on host " + routingHost.getName());
                    }

                    String privateIpAddress = allocPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId(),
                            proxy.getPrivateMacAddress());
                    if (privateIpAddress == null && (_IpAllocator != null && !_IpAllocator.exteralIpAddressAllocatorEnabled())) {
                        String msg = "Unable to allocate private ip addresses for  " + proxy.getName() + " in pod " + pod.getId();
                        s_logger.debug(msg);
                        throw new CloudRuntimeException(msg);
                    }

                    proxy.setPrivateIpAddress(privateIpAddress);
                    String guestIpAddress = _dcDao.allocateLinkLocalPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId());
                    proxy.setGuestIpAddress(guestIpAddress);

                    _consoleProxyDao.updateIf(proxy, Event.OperationRetry, routingHost.getId());
                    proxy = _consoleProxyDao.findById(proxy.getId());

                    List vols = _storageMgr.prepare(proxy, routingHost);
                    if (vols == null || vols.size() == 0) {
                        String msg = "Unable to prepare storage for " + proxy.getName() + " in pod " + pod.getId();
                        s_logger.debug(msg);
                        throw new CloudRuntimeException(msg);
                    }

                    // _storageMgr.share(proxy, vols, null, true);
                    // carry the console proxy port info over so that we don't
                    // need to configure agent on this
                    StartConsoleProxyCommand cmdStart = new StartConsoleProxyCommand(_networkRate, _multicastRate,
                            _proxyCmdPort, proxy, proxy.getName(), "", vols, Integer.toString(_consoleProxyPort),
                            Integer.toString(_consoleProxyUrlPort), _mgmt_host, _mgmt_port, _sslEnabled);
                    if (s_logger.isDebugEnabled())
                        s_logger.debug("Sending start command for console proxy " + proxy.getName() + " to " + routingHost.getName());
                    try {
                        answer = _agentMgr.send(routingHost.getId(), cmdStart);

                        s_logger.debug("StartConsoleProxy Answer: " + (answer != null ? answer : "null"));

                        if (s_logger.isDebugEnabled())
                            s_logger.debug("Received answer on starting console proxy " + proxy.getName() + " on " + routingHost.getName());

                        if (answer != null && answer.getResult()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Console proxy " + proxy.getName() + " started on " + routingHost.getName());
                            }

                            if (answer instanceof StartConsoleProxyAnswer) {
                                StartConsoleProxyAnswer rAnswer = (StartConsoleProxyAnswer) answer;
                                if (rAnswer.getPrivateIpAddress() != null) {
                                    proxy.setPrivateIpAddress(rAnswer.getPrivateIpAddress());
                                }
                                if (rAnswer.getPrivateMacAddress() != null) {
                                    proxy.setPrivateMacAddress(rAnswer.getPrivateMacAddress());
                                }
                            }

                            final EventVO event = new EventVO();
                            event.setUserId(User.UID_SYSTEM);
                            event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                            event.setType(EventTypes.EVENT_PROXY_START);
                            event.setLevel(EventVO.LEVEL_INFO);
                            event.setStartId(startEventId);
                            event.setDescription("Console proxy started - " + proxy.getName());
                            _eventDao.persist(event);
                            break;
                        }
                        s_logger.debug("Unable to start " + proxy.toString() + " on host " + routingHost.toString() + " due to "
                                + answer.getDetails());
                    } catch (OperationTimedoutException e) {
                        if (e.isActive()) {
                            s_logger.debug("Unable to start vm " + proxy.getName()
                                    + " due to operation timed out and it is active so scheduling a restart.");
                            _haMgr.scheduleRestart(proxy, true);
                            return null;
                        }
                    } catch (AgentUnavailableException e) {
                        s_logger.debug("Agent " + routingHost.toString() + " was unavailable to start VM " + proxy.getName());
                    }

                    avoid.add(routingHost);
                    proxy.setPrivateIpAddress(null);
                    freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
                    proxy.setGuestIpAddress(null);
                    _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId());
                    _storageMgr.unshare(proxy, vols, routingHost);
                } while (--retry > 0
                        && (routingHost = (HostVO) _agentMgr
                                .findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, _template, proxy, null, avoid)) != null);
                if (routingHost == null || retry <= 0) {

                    SubscriptionMgr.getInstance().notifySubscribers(
                            ConsoleProxyManager.ALERT_SUBJECT,
                            this,
                            new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, proxy.getDataCenterId(), proxy.getId(),
                                    proxy, "Unable to find a routing host to run"));

                    final EventVO event = new EventVO();
                    event.setUserId(User.UID_SYSTEM);
                    event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                    event.setType(EventTypes.EVENT_PROXY_START);
                    event.setLevel(EventVO.LEVEL_ERROR);
                    event.setStartId(startEventId);
                    event.setDescription("Starting console proxy failed due to unable to find a host - " + proxy.getName());
                    _eventDao.persist(event);
                    throw new ExecutionException("Couldn't find a routingHost to run console proxy");
                }

                _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, routingHost.getId());
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Console proxy is now started, vm id : " + proxy.getId());
                }

                // If starting the console proxy failed due to the external
                // firewall not being reachable, send an alert.
                if (answer != null && answer.getDetails() != null && answer.getDetails().equals("firewall")) {

                    SubscriptionMgr.getInstance().notifySubscribers(
                            ConsoleProxyManager.ALERT_SUBJECT,
                            this,
                            new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_FIREWALL_ALERT, proxy.getDataCenterId(), proxy.getId(),
                                    proxy, null));
                }

                SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this,
                        new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_UP, proxy.getDataCenterId(), proxy.getId(), proxy, null));

                return proxy;
            } catch (Throwable thr) {
                s_logger.warn("Unexpected exception: ", thr);

                SubscriptionMgr.getInstance().notifySubscribers(
                        ConsoleProxyManager.ALERT_SUBJECT,
                        this,
                        new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, proxy.getDataCenterId(), proxy.getId(), proxy,
        } else {
                                "Unexpected exception: " + thr.getMessage()));

                /*
                 * final EventVO event = new EventVO();
                 * event.setUserId(User.UID_SYSTEM);
                 * event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                 * event.setType(EventTypes.EVENT_PROXY_START);
                 * event.setLevel(EventVO.LEVEL_ERROR);
                 * event.setStartId(startEventId); event.setDescription(
                 * "Starting console proxy failed due to unhandled exception - "
                 * + proxy.getName()); _eventDao.persist(event);
                 */

                Transaction txn = Transaction.currentTxn();
                try {
                    txn.start();
                    String privateIpAddress = proxy.getPrivateIpAddress();
                    if (privateIpAddress != null) {
                        proxy.setPrivateIpAddress(null);
                        freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
                    }

                    _consoleProxyDao.updateIf(proxy, Event.OperationFailed, null);
                    txn.commit();
                } catch (Exception e) {
                    s_logger.error("Caught exception during error recovery");
                }

                if (thr instanceof StorageUnavailableException) {
                    throw (StorageUnavailableException) thr;
                } else if (thr instanceof ConcurrentOperationException) {
                    throw (ConcurrentOperationException) thr;
                } else if (thr instanceof ExecutionException) {
                    s_logger.error("Error while starting console proxy due to " + thr.getMessage());
                } else {
                    s_logger.error("Error while starting console proxy ", thr);
                }
                return null;
            }
        }

        s_logger.warn("Starting console proxy encounters non-startable situation");
        return null;
    }

            if (cmd.getLoadInfo() != null)
    public ConsoleProxyVO assignProxyFromRunningPool(long dataCenterId) {

        if (s_logger.isTraceEnabled())
            s_logger.trace("Assign console proxy from running pool for request from data center : " + dataCenterId);

        ConsoleProxyAllocator allocator = getCurrentAllocator();
        assert (allocator != null);
        List runningList = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Running);
        if (runningList != null && runningList.size() > 0) {
            if (s_logger.isTraceEnabled()) {
                s_logger.trace("Running proxy pool size : " + runningList.size());
                for (ConsoleProxyVO proxy : runningList)
                    s_logger.trace("Running proxy instance : " + proxy.getName());
            }

            List> l = _consoleProxyDao.getProxyLoadMatrix();
            Map loadInfo = new HashMap();
            if (l != null) {
                for (Pair p : l) {
                    loadInfo.put(p.first(), p.second());

                    if (s_logger.isTraceEnabled()) {
                        s_logger.trace("Running proxy instance allocation load { proxy id : " + p.first() + ", load : " + p.second() + "}");
                    }
                }
            }
            return allocator.allocProxy(runningList, loadInfo, dataCenterId);
        } else {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Empty running proxy pool for now in data center : " + dataCenterId);
        }
        return null;
    }

    public ConsoleProxyVO assignProxyFromStoppedPool(long dataCenterId) {
        List l = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Creating, State.Starting, State.Stopped, State.Migrating);
        if (l != null && l.size() > 0)
            return l.get(0);

        return null;
    public ConsoleProxyVO startNewConsoleProxy(long dataCenterId) {
        if (s_logger.isDebugEnabled())
            s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId);

        Map context = createProxyInstance(dataCenterId);

        long proxyVmId = (Long) context.get("proxyVmId");
        if (proxyVmId == 0) {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId);

            // release critical system resource on failure
            if (context.get("publicIpAddress") != null)
                freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0);

            return null;
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); 
            //allocProxyStorage(dataCenterId, proxyVmId);
        if (proxy != null) {
            SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATED, dataCenterId, proxy.getId(), proxy, null));
            return proxy;
        } else {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId);

            SubscriptionMgr.getInstance().notifySubscribers(
                    ConsoleProxyManager.ALERT_SUBJECT,
                    this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE, dataCenterId, proxyVmId, null,
                            "Unable to allocate storage"));

            destroyProxyDBOnly(proxyVmId);
        }
        return null;
    }

    public ConsoleProxyVO startNew(long dataCenterId) {

        if (s_logger.isDebugEnabled())
            s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId);

        Map context = createProxyInstance(dataCenterId);

        long proxyVmId = (Long) context.get("proxyVmId");
        if (proxyVmId == 0) {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId);

            // release critical system resource on failure
            if (context.get("publicIpAddress") != null)
                freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0);

            return null;
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); 
            //allocProxyStorage(dataCenterId, proxyVmId);
        if (proxy != null) {
            SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATED, dataCenterId, proxy.getId(), proxy, null));
            return proxy;
        } else {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId);

            SubscriptionMgr.getInstance().notifySubscribers(
                    ConsoleProxyManager.ALERT_SUBJECT,
                    this,
                    new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE, dataCenterId, proxyVmId, null,
                            "Unable to allocate storage"));

            destroyProxyDBOnly(proxyVmId);
        }
        return null;
    }

    @DB
    protected Map createProxyInstance(long dataCenterId) {

        Map context = new HashMap();
        String publicIpAddress = null;

        Transaction txn = Transaction.currentTxn();
        try {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            assert (dc != null);
            context.put("dc", dc);

            // this will basically allocate the pod based on data center id as
            // we use system user id here
            Set avoidPods = new HashSet();
            Pair pod = null;
            networkInfo publicIpAndVlan = null;

            // About MAC address allocation
            // MAC address used by User VM is inherited from DomR MAC address,
            // with the least 16 bits overrided. to avoid
            // potential conflicts, domP will mask bit 31
            //
            String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31));
            String privateMacAddress = macAddresses[0];
            String publicMacAddress = macAddresses[1];
            macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31));
            String guestMacAddress = macAddresses[0];
            while ((pod = _agentMgr.findPod(_template, _serviceOffering, dc, Account.ACCOUNT_ID_SYSTEM, avoidPods)) != null) {
                publicIpAndVlan = allocPublicIpAddress(dataCenterId, pod.first().getId(), publicMacAddress);
                if (publicIpAndVlan == null) {
                    s_logger.warn("Unable to allocate public IP address for console proxy vm in data center : " + dataCenterId + ", pod="
                            + pod.first().getId());
                    avoidPods.add(pod.first().getId());
                } else {
                    break;
                }
            }

            if (pod == null || publicIpAndVlan == null) {
                String msg = "Unable to allocate pod for console proxy vm in data center : " + dataCenterId;
                s_logger.warn(msg);
                throw new CloudRuntimeException(msg);
            }

            long id = _consoleProxyDao.getNextInSequence(Long.class, "id");

            context.put("publicIpAddress", publicIpAndVlan._ipAddr);
            context.put("pod", pod);
            if (s_logger.isDebugEnabled()) {
                                try {
                s_logger.debug("Pod allocated " + pod.first().getName());
            }

            String cidrNetmask = NetUtils.getCidrNetmask(pod.first().getCidrSize());

            // Find the VLAN ID, VLAN gateway, and VLAN netmask for
            // publicIpAddress
            publicIpAddress = publicIpAndVlan._ipAddr;

            String vlanGateway = publicIpAndVlan._gateWay;
            String vlanNetmask = publicIpAndVlan._netMask;
            
            AccountVO systemAccount = _accountMgr.getSystemAccount();

            txn.start();
            ConsoleProxyVO proxy;
            String name = VirtualMachineName.getConsoleProxyName(id, _instance).intern();
            proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, guestMacAddress, null, NetUtils.getLinkLocalNetMask(), privateMacAddress, null, cidrNetmask,
                    _template.getId(), _template.getGuestOSId(), publicMacAddress, publicIpAddress, vlanNetmask, publicIpAndVlan._vlanDbId,
                    publicIpAndVlan._vlanid, pod.first().getId(), dataCenterId, systemAccount.getDomainId(), systemAccount.getId(), vlanGateway, null, dc.getDns1(), dc.getDns2(), _domain,
                    _proxyRamSize, 0);

            proxy.setLastHostId(pod.second());
            proxy = _consoleProxyDao.persist(proxy);
            long proxyVmId = proxy.getId();

            final EventVO event = new EventVO();
            event.setUserId(User.UID_SYSTEM);
            event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
            event.setType(EventTypes.EVENT_PROXY_CREATE);
            event.setLevel(EventVO.LEVEL_INFO);
            event.setDescription("New console proxy created - " + proxy.getName());
            _eventDao.persist(event);
            txn.commit();

            context.put("proxyVmId", proxyVmId);
            return context;
        } catch (Throwable e) {
            s_logger.error("Unexpected exception : ", e);

    }
            return context;
        }
    }

    protected Map createProxyInstance2(long dataCenterId) {

        long id = _consoleProxyDao.getNextInSequence(Long.class, "id");
        String name = VirtualMachineName.getConsoleProxyName(id, _instance);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        AccountVO systemAcct = _accountMgr.getSystemAccount();
        
        DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, 1);
        
        List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork, NetworkOfferingVO.SystemVmManagementNetwork, NetworkOfferingVO.SystemVmPublicNetwork);
        List profiles = new ArrayList(offerings.size());
        for (NetworkOfferingVO offering : offerings) {
            profiles.add(_networkMgr.setupNetworkConfiguration(_accountMgr.getSystemAccount(), offering, plan));
        }
        ConsoleProxyVO proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, _template.getId(), _template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId(), 0);
        proxy = _consoleProxyDao.persist(proxy);
        try {
            VirtualMachineProfile vmProfile = _vmMgr.allocate(proxy, _template, _serviceOffering, profiles, plan, _accountMgr.getSystemAccount());
        } catch (InsufficientCapacityException e) {
            s_logger.warn("InsufficientCapacity", e);
            throw new CloudRuntimeException("Insufficient capacity exception", e);
        } catch (StorageUnavailableException e) {
            s_logger.warn("Unable to contact storage", e);
            throw new CloudRuntimeException("Unable to contact storage", e);
        }
        
        Map context = new HashMap();
        context.put("dc", dc);
//        context.put("publicIpAddress", publicIpAndVlan._ipAddr);
        HostPodVO pod = _podDao.findById(proxy.getPodId());
        context.put("pod", pod);
        context.put("proxyVmId", proxy.getId());

        return context;
    }
    
    @DB
                return;
    protected ConsoleProxyVO allocProxyStorage(long dataCenterId, long proxyVmId) {
        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
        assert (proxy != null);

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        HostPodVO pod = _podDao.findById(proxy.getPodId());
        final AccountVO account = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM);

        try {
            List vols = _storageMgr.create(account, proxy, _template, dc, pod, _serviceOffering, null, 0);
            if (vols == null) {
                s_logger.error("Unable to alloc storage for console proxy");
                return null;
            }

            Transaction txn = Transaction.currentTxn();
            txn.start();

            // update pool id
            ConsoleProxyVO vo = _consoleProxyDao.findById(proxy.getId());
            _consoleProxyDao.update(proxy.getId(), vo);

            // kick the state machine
            _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, null);

            txn.commit();
            return proxy;
        } catch (StorageUnavailableException e) {
            s_logger.error("Unable to alloc storage for console proxy: ", e);
            return null;
        } catch (ExecutionException e) {
            s_logger.error("Unable to alloc storage for console proxy: ", e);
            return null;
        }
    }

    private networkInfo allocPublicIpAddress(long dcId, long podId, String macAddr) {

        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            IpAddrAllocator.IpAddr ip = _IpAllocator.getPublicIpAddress(macAddr, dcId, podId);
            networkInfo net = new networkInfo(ip.ipaddr, ip.netMask, ip.gateway, null, "untagged");
            return net;
        }

        Pair ipAndVlan = _vlanDao.assignIpAddress(dcId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN, VlanType.VirtualNetwork,
                true);

        if (ipAndVlan == null) {
            s_logger.debug("Unable to get public ip address (type=Virtual) for console proxy vm for data center  : " + dcId);
            ipAndVlan = _vlanDao.assignPodDirectAttachIpAddress(dcId, podId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN);
            if (ipAndVlan == null)
                s_logger.debug("Unable to get public ip address (type=DirectAttach) for console proxy vm for data center  : " + dcId);
        }
        if (ipAndVlan != null) {
            VlanVO vlan = ipAndVlan.second();
            networkInfo net = new networkInfo(ipAndVlan.first(), vlan.getVlanNetmask(), vlan.getVlanGateway(), vlan.getId(), vlan.getVlanId());
            return net;
        }
        return null;
    }

    private String allocPrivateIpAddress(Long dcId, Long podId, Long proxyId, String macAddr) {
        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            return _IpAllocator.getPrivateIpAddress(macAddr, dcId, podId).ipaddr;
        } else {
            return _dcDao.allocatePrivateIpAddress(dcId, podId, proxyId);
        }
    }

    private void freePrivateIpAddress(String ipAddress, Long dcId, Long podId) {
        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            _IpAllocator.releasePrivateIpAddress(ipAddress, dcId, podId);
        } else {
            _dcDao.releasePrivateIpAddress(ipAddress, dcId, podId);
        }
    }

    private void freePublicIpAddress(String ipAddress, long dcId, long podId) {
        if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
            _IpAllocator.releasePublicIpAddress(ipAddress, dcId, podId);
        } else {
            _ipAddressDao.unassignIpAddress(ipAddress);
        }
    }

    private ConsoleProxyAllocator getCurrentAllocator() {
        // for now, only one adapter is supported
            }
        Enumeration it = _consoleProxyAllocators.enumeration();
        if (it.hasMoreElements())
            return it.nextElement();

        return null;
    }

    protected String connect(String ipAddress, int port) {
        for (int i = 0; i <= _ssh_retry; i++) {
            SocketChannel sch = null;
            try {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Trying to connect to " + ipAddress);
                }
                sch = SocketChannel.open();
                sch.configureBlocking(true);
                sch.socket().setSoTimeout(5000);

                InetSocketAddress addr = new InetSocketAddress(ipAddress, port);
                sch.connect(addr);
                return null;
            } catch (IOException e) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Could not connect to " + ipAddress);
                }
            } finally {
                if (sch != null) {
                    try {
                        sch.close();
                    } catch (IOException e) {
                    }
                }
            }
            try {
                Thread.sleep(_ssh_sleep);
            } catch (InterruptedException ex) {
            }
        }

        s_logger.debug("Unable to logon to " + ipAddress);

        return "Unable to connect";
    }

    public void onLoadAnswer(ConsoleProxyLoadAnswer answer) {
        if (answer.getDetails() == null)
            return;


        ConsoleProxyStatus status = null;
        try {
            GsonBuilder gb = new GsonBuilder();
            gb.setVersion(1.3);
            Gson gson = gb.create();
            status = gson.fromJson(answer.getDetails(), ConsoleProxyStatus.class);
        } catch (Throwable e) {
            s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + answer.getProxyVmId() + ", info : " + answer.getDetails());
        }

        if (status != null) {
            int count = 0;
            if (status.getConnections() != null)
                count = status.getConnections().length;

            byte[] details = null;
            if (answer.getDetails() != null)
                details = answer.getDetails().getBytes(Charset.forName("US-ASCII"));
            _consoleProxyDao.update(answer.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
        } else {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Unable to get console proxy load info, id : " + answer.getProxyVmId());

            _consoleProxyDao.update(answer.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
            // TODO : something is wrong with the VM, restart it?
        }
    }

    @Override
    public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
        if (cmd.getLoadInfo() == null)
            return;

        ConsoleProxyStatus status = null;
        try {
            GsonBuilder gb = new GsonBuilder();
            gb.setVersion(1.3);
            Gson gson = gb.create();
            status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class);
        } catch (Throwable e) {
            s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo());
        }

        if (status != null) {
            int count = 0;
            if (status.getConnections() != null)
                count = status.getConnections().length;

                details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII"));
            _consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
        } else {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId());

            _consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
        }
    }

    @Override
    public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) {
        long vmId = 0;

        if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Invalid vm id sent from proxy(happens when proxy session has terminated)");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        try {
            vmId = Long.parseLong(cmd.getVmId());
        } catch (NumberFormatException e) {
            s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication", e);
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        // TODO authentication channel between console proxy VM and management
        // server needs to be secured,
        // the data is now being sent through private network, but this is
        // apparently not enough
        VMInstanceVO vm = _instanceDao.findById(vmId);
        if (vm == null) {
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        if (vm.getHostId() == null) {
            s_logger.warn("VM " + vmId + " lost host info, failed authentication request");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        HostVO host = _hostDao.findById(vm.getHostId());
        if (host == null) {
            s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request");
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        String sid = cmd.getSid();
        if (sid == null || !sid.equals(vm.getVncPassword())) {
            s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
            return new ConsoleAccessAuthenticationAnswer(cmd, false);
        }

        return new ConsoleAccessAuthenticationAnswer(cmd, true);
    }

    private ConsoleProxyVO findConsoleProxyByHost(HostVO host) throws NumberFormatException {
        String name = host.getName();
        long proxyVmId = 0;
        ConsoleProxyVO proxy = null;
        if (name != null && name.startsWith("v-")) {
            String[] tokens = name.split("-");
            proxyVmId = Long.parseLong(tokens[1]);
            proxy = this._consoleProxyDao.findById(proxyVmId);
        }
        return proxy;
    }

    @Override
    public void onAgentConnect(HostVO host, StartupCommand cmd) {
        if (host.getType() == Type.ConsoleProxy) {
            // TODO we can use this event to mark the proxy is up and
            // functioning instead of
            // pinging the console proxy VM command port
            //
            // for now, just log a message
            if (s_logger.isInfoEnabled())
                s_logger.info("Console proxy agent is connected. proxy: " + host.getName());

            /* update public/private ip address */
            if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
                try {
                    ConsoleProxyVO console = findConsoleProxyByHost(host);
                    if (console == null) {
                        s_logger.debug("Can't find console proxy ");
                        return;
                    }
                    console.setPrivateIpAddress(cmd.getPrivateIpAddress());
        } else {
                    console.setPrivateNetmask(cmd.getPrivateNetmask());
                    console.setPublicIpAddress(cmd.getPublicIpAddress());
                    console.setPublicNetmask(cmd.getPublicNetmask());
                    _consoleProxyDao.persist(console);
                } catch (NumberFormatException e) {
                }
            }
        }
    }

    @Override
    public void onAgentDisconnect(long agentId, com.cloud.host.Status state) {
        if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) {
            // be it either in alert or in disconnected state, the agent process
            // may be gone in the VM,
            // we will be reacting to stop the corresponding VM and let the scan
            // process to
            HostVO host = _hostDao.findById(agentId);
            if (host.getType() == Type.ConsoleProxy) {
                String name = host.getName();
                if (s_logger.isInfoEnabled())
                    s_logger.info("Console proxy agent disconnected, proxy: " + name);
                if (name != null && name.startsWith("v-")) {
                    String[] tokens = name.split("-");
                    long proxyVmId = 0;
                    try {
                        proxyVmId = Long.parseLong(tokens[1]);
                    } catch (NumberFormatException e) {
                        s_logger.error("Unexpected exception " + e.getMessage(), e);
                        return;
                    }

                    final ConsoleProxyVO proxy = this._consoleProxyDao.findById(proxyVmId);
                    if (proxy != null) {
                        Long hostId = proxy.getHostId();

                        // Disable this feature for now, as it conflicts with
                        // the case of allowing user to reboot console proxy
                        // when rebooting happens, we will receive disconnect
                        // here and we can't enter into stopping process,
                        // as when the rebooted one comes up, it will kick off a
                        // newly started one and trigger the process
                        // continue on forever

                        /*
                         * _capacityScanScheduler.execute(new Runnable() {
                         * public void run() { if(s_logger.isInfoEnabled())
                         * s_logger.info("Stop console proxy " + proxy.getName()
                         * +
                         * " VM because of that the agent running inside it has disconnected"
                         * ); stopProxy(proxy.getId()); } });
                         */
                    } else {
                        if (s_logger.isInfoEnabled())
                            s_logger.info("Console proxy agent disconnected but corresponding console proxy VM no longer exists in DB, proxy: "
                                    + name);
                    }
                } else {
                    assert (false) : "Invalid console proxy name: " + name;
                }
            }
        }
    }

    private void checkPendingProxyVMs() {
        // drive state to change away from transient states
        List l = _consoleProxyDao.getProxyListInStates(State.Creating);
        if (l != null && l.size() > 0) {
            for (ConsoleProxyVO proxy : l) {
                if (proxy.getLastUpdateTime() == null
                        || (proxy.getLastUpdateTime() != null && System.currentTimeMillis() - proxy.getLastUpdateTime().getTime() > 60000)) {
                    try {
                        ConsoleProxyVO readyProxy = null;
                        if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                            try {
                                readyProxy = allocProxyStorage(proxy.getDataCenterId(), proxy.getId());
                            } finally {
                                _allocProxyLock.unlock();
                            }

                            if (readyProxy != null) {
                                GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(readyProxy.getId()));
                                    if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                                        try {
                                            readyProxy = start(readyProxy.getId(), 0);
                                        } finally {
                                            proxyLock.unlock();
                                        }
                                    } else {
                                        if (s_logger.isInfoEnabled())
                                            s_logger.info("Unable to acquire synchronization lock to start console proxy : " + readyProxy.getName());
                                    }
                                } finally {
                                    proxyLock.releaseRef();
                                }
                            }
                        } else {
                            if (s_logger.isInfoEnabled())
                                s_logger.info("Unable to acquire synchronization lock to allocate proxy storage, wait for next turn");
                        }
                    } catch (StorageUnavailableException e) {
                        s_logger.warn("Storage unavailable", e);
                    } catch (InsufficientCapacityException e) {
                        s_logger.warn("insuffiient capacity", e);
                    } catch (ConcurrentOperationException e) {
                        s_logger.debug("Concurrent operation: " + e.getMessage());
                    }
                }
            }
        }
    }

    private Runnable getCapacityScanTask() {
        return new Runnable() {

            @Override
            public void run() {
                Transaction txn = Transaction.open(Transaction.CLOUD_DB);
                try {
                    reallyRun();
                } catch (Throwable e) {
                    s_logger.warn("Unexpected exception " + e.getMessage(), e);
                } finally {
                    StackMaid.current().exitCleanup();
                    txn.close();
                }
            }

            private void reallyRun() {
                if (s_logger.isTraceEnabled())
                    s_logger.trace("Begin console proxy capacity scan");

                // config var for consoleproxy.restart check
                String restart = _configDao.getValue("consoleproxy.restart");
                if (restart != null && restart.equalsIgnoreCase("false")) {
                    s_logger.debug("Capacity scan disabled purposefully, consoleproxy.restart = false. This happens when the primarystorage is in maintenance mode");
                    return;
                }

                Map zoneHostInfoMap = getZoneHostInfo();
                if (isServiceReady(zoneHostInfoMap)) {
                    if (s_logger.isTraceEnabled())
                        s_logger.trace("Service is ready, check to see if we need to allocate standby capacity");

                    if (!_capacityScanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
                        if (s_logger.isTraceEnabled())
                            s_logger.trace("Capacity scan lock is used by others, skip and wait for my turn");
                        return;
                    }

                    if (s_logger.isTraceEnabled())
                        s_logger.trace("*** Begining capacity scan... ***");

                    try {
                        checkPendingProxyVMs();

                        // scan default data center first
                        long defaultId = 0;

                        // proxy count info by data-centers (zone-id, zone-name,
                        // count)
                        List l = _consoleProxyDao.getDatacenterProxyLoadMatrix();

                        // running VM session count by data-centers (zone-id,
                        // zone-name, count)
                        List listVmCounts = _consoleProxyDao.getDatacenterSessionLoadMatrix();

                        // indexing load info by data-center id
                        Map mapVmCounts = new HashMap();
                        if (listVmCounts != null)
                            for (ConsoleProxyLoadInfo info : listVmCounts)
                                mapVmCounts.put(info.getId(), info);

                        for (ConsoleProxyLoadInfo info : l) {
                            if (info.getName().equals(_instance)) {
                                ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId());

                                if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) {
                                    if (isZoneReady(zoneHostInfoMap, info.getId())) {
                                        allocCapacity(info.getId());
                                    } else {
                                        if (s_logger.isTraceEnabled())
                                            s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy");
                                    }
                                }

                                defaultId = info.getId();
                                break;
                            }
                        }

                        // scan rest of data-centers
                        for (ConsoleProxyLoadInfo info : l) {
                            if (info.getId() != defaultId) {
                                ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId());

                                if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) {
                                    if (isZoneReady(zoneHostInfoMap, info.getId())) {
                                        allocCapacity(info.getId());
                                    } else {
                                        if (s_logger.isTraceEnabled())
                                            s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy");
                                    }
                                }
                            }
                        }

                        if (s_logger.isTraceEnabled())
                            s_logger.trace("*** Stop capacity scan ***");
                    } finally {
                        _capacityScanLock.unlock();
                    }

                } else {
                    if (s_logger.isTraceEnabled())
                        s_logger.trace("Service is not ready for capacity preallocation, wait for next time");
                }

                if (s_logger.isTraceEnabled())
                    s_logger.trace("End of console proxy capacity scan");
            }
        };
    }

    private boolean checkCapacity(ConsoleProxyLoadInfo proxyCountInfo, ConsoleProxyLoadInfo vmCountInfo) {

        if (proxyCountInfo.getCount() * _capacityPerProxy - vmCountInfo.getCount() <= _standbyCapacity)
            return false;

        return true;
    }

    private void allocCapacity(long dataCenterId) {
        if (s_logger.isTraceEnabled())
            s_logger.trace("Allocate console proxy standby capacity for data center : " + dataCenterId);

        boolean proxyFromStoppedPool = false;
        ConsoleProxyVO proxy = assignProxyFromStoppedPool(dataCenterId);
        if (proxy == null) {
            if (s_logger.isInfoEnabled())
                s_logger.info("No stopped console proxy is available, need to allocate a new console proxy");

            if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                try {
                    proxy = startNew(dataCenterId);
                } finally {
                    _allocProxyLock.unlock();
                }
            } else {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Unable to acquire synchronization lock to allocate proxy resource for standby capacity, wait for next scan");
            if (s_logger.isInfoEnabled())
                s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId());
            proxyFromStoppedPool = true;
        }

        if (proxy != null) {
            long proxyVmId = proxy.getId();
            GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId));
            try {
                if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                    try {
                        proxy = startProxy(proxyVmId, 0);
                    } finally {
                        proxyLock.unlock();
                    }
                } else {
                    if (s_logger.isInfoEnabled())
                        s_logger.info("Unable to acquire synchronization lock to start proxy for standby capacity, proxy vm id : " + proxy.getId());
                    return;
                }
            } finally {
                proxyLock.releaseRef();
            }

            if (proxy == null) {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Unable to start console proxy for standby capacity, proxy vm Id : " + proxyVmId
                            + ", will recycle it and start a new one");

                if (proxyFromStoppedPool)
                    destroyProxy(proxyVmId, 0);
            } else {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Console proxy " + proxy.getName() + " is started");
            }
        }
    }

    public boolean isServiceReady(Map zoneHostInfoMap) {
        for (ZoneHostInfo zoneHostInfo : zoneHostInfoMap.values()) {
            if (isZoneHostReady(zoneHostInfo)) {
                if (s_logger.isInfoEnabled())
                    s_logger.info("Zone " + zoneHostInfo.getDcId() + " is ready to launch");
                return true;
            }
        }

        return false;
    }

    public boolean isZoneReady(Map zoneHostInfoMap, long dataCenterId) {
        ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
        if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
            VMTemplateVO template = _templateDao.findConsoleProxyTemplate();
            HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(dataCenterId);
            boolean templateReady = false;

            if (template != null && secondaryStorageHost != null) {
                VMTemplateHostVO templateHostRef = _vmTemplateHostDao.findByHostTemplate(secondaryStorageHost.getId(), template.getId());
                templateReady = (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED);
            }

            if (templateReady) {
                List> l = _consoleProxyDao.getDatacenterStoragePoolHostInfo(dataCenterId, _use_lvm);
                if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) {
                    return true;
                } else {
                    if (s_logger.isTraceEnabled())
                        s_logger.trace("Primary storage is not ready, wait until it is ready to launch console proxy");
                }
            } else {
                if (s_logger.isTraceEnabled())
                    s_logger.trace("Zone host is ready, but console proxy template is not ready");
            }
        }
        return false;
    }

    private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) {
        int expectedFlags = 0;
        if (_use_storage_vm)
            expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK;
        else
            expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ALL_HOST_MASK;

        return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags;
    }


    private synchronized Map getZoneHostInfo() {
        Date cutTime = DateUtil.currentGMTTime();
        List l = _hostDao.getRunningHostCounts(new Date(cutTime.getTime() - ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD));

        RunningHostInfoAgregator aggregator = new RunningHostInfoAgregator();
        if (l.size() > 0)
            for (RunningHostCountInfo countInfo : l)
                aggregator.aggregate(countInfo);

        return aggregator.getZoneHostInfoMap();
    }

    @Override
    public String getName() {
        return _name;
    }

    @Override
    public boolean start() {
        if (s_logger.isInfoEnabled())
            s_logger.info("Start console proxy manager");

        return true;
    }

    @Override
    public boolean stop() {
        if (s_logger.isInfoEnabled())
            s_logger.info("Stop console proxy manager");
        _capacityScanScheduler.shutdownNow();

        try {
            _capacityScanScheduler.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
        }

        _capacityScanLock.releaseRef();
        _allocProxyLock.releaseRef();
        return true;
    }

    @Override
    public Command cleanup(ConsoleProxyVO vm, String vmName) {
        if (vmName != null) {
            return new StopCommand(vm, vmName, VirtualMachineName.getVnet(vmName));
        } else if (vm != null) {
            ConsoleProxyVO vo = vm;
            return new StopCommand(vo, null);
            throw new CloudRuntimeException("Shouldn't even be here!");
        }
    }

    @Override
    public void completeStartCommand(ConsoleProxyVO vm) {
        _consoleProxyDao.updateIf(vm, Event.AgentReportRunning, vm.getHostId());
    }

    @Override
    public void completeStopCommand(ConsoleProxyVO vm) {
        completeStopCommand(vm, Event.AgentReportStopped);
    }

    @DB
    protected void completeStopCommand(ConsoleProxyVO proxy, Event ev) {
        Transaction txn = Transaction.currentTxn();
        try {
            txn.start();
            String privateIpAddress = proxy.getPrivateIpAddress();
            if (privateIpAddress != null) {
                proxy.setPrivateIpAddress(null);
                freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId());
            }
            String guestIpAddress = proxy.getGuestIpAddress();
            if (guestIpAddress != null) {
                proxy.setGuestIpAddress(null);
                _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId());
            }

            if (!_consoleProxyDao.updateIf(proxy, ev, null)) {
                s_logger.debug("Unable to update the console proxy");
                return;
            }
            txn.commit();
        } catch (Exception e) {
            s_logger.error("Unable to complete stop command due to ", e);
        }

        if (_storageMgr.unshare(proxy, null) == null) {
            s_logger.warn("Unable to set share to false for " + proxy.getId());
        }
    }

    @Override
    public ConsoleProxyVO get(long id) {
        return _consoleProxyDao.findById(id);
    }

    @Override
    public Long convertToId(String vmName) {
        
        if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) {
            return null;
        }
        return VirtualMachineName.getConsoleProxyId(vmName);
    }

    @Override
    public boolean stopProxy(long proxyVmId, long startEventId) {

        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("Stop console proxy " + proxyVmId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId);
        }

        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
        if (proxy == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Stopping console proxy failed: console proxy " + proxyVmId + " no longer exists");
            return false;
        }
        /*
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_STOP, "Stopping console proxy with Id: " +
         * proxyVmId, startEventId);
         */
        try {
            return stop(proxy, startEventId);
        } catch (AgentUnavailableException e) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Stopping console proxy " + proxy.getName() + " failed : exception " + e.toString());
            return false;
        }
    }

    @Override
    public boolean rebootProxy(long proxyVmId, long startEventId) {
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("Reboot console proxy " + proxyVmId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId);
        }

        final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);

        if (proxy == null || proxy.getState() == State.Destroyed) {
            return false;
        }

        /*
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: " +
         * proxyVmId, startEventId);
         */
        if (proxy.getState() == State.Running && proxy.getHostId() != null) {
            final RebootCommand cmd = new RebootCommand(proxy.getInstanceName());
            final Answer answer = _agentMgr.easySend(proxy.getHostId(), cmd);

            if (answer != null) {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("Successfully reboot console proxy " + proxy.getName());

                SubscriptionMgr.getInstance()
                        .notifySubscribers(
                                ConsoleProxyManager.ALERT_SUBJECT,
                                this,
                                new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_REBOOTED, proxy.getDataCenterId(), proxy.getId(),
                                        proxy, null));

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_REBOOT);
                event.setLevel(EventVO.LEVEL_INFO);
                event.setStartId(startEventId);
                event.setDescription("Console proxy rebooted - " + proxy.getName());
                _eventDao.persist(event);
                return true;
            } else {
                if (s_logger.isDebugEnabled())
                    s_logger.debug("failed to reboot console proxy : " + proxy.getName());

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_REBOOT);
                event.setLevel(EventVO.LEVEL_ERROR);
                event.setStartId(startEventId);
                event.setDescription("Rebooting console proxy failed - " + proxy.getName());
                _eventDao.persist(event);
                return false;
            }
        } else {
            return startProxy(proxyVmId, 0) != null;
        }
    }

    @Override
    public boolean destroy(ConsoleProxyVO proxy) throws AgentUnavailableException {
        return destroyProxy(proxy.getId(), 0);
    }

    @Override
    @DB
    public boolean destroyProxy(long vmId, long startEventId) {
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("Destroy console proxy " + vmId + ", update async job-" + job.getId());
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", vmId);
        }

        ConsoleProxyVO vm = _consoleProxyDao.findById(vmId);
        if (vm == null || vm.getState() == State.Destroyed) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vmId);
            }
            return true;
        }
        /*
         * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
         * EventTypes.EVENT_PROXY_DESTROY, "Destroying console proxy with Id: "
         * + vmId, startEventId);
         */
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Destroying console proxy vm " + vmId);
        }

        if (!_consoleProxyDao.updateIf(vm, Event.DestroyRequested, null)) {
            s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vmId);
            return false;
        }

        Transaction txn = Transaction.currentTxn();
        List vols = null;
        try {
            vols = _volsDao.findByInstance(vmId);
            if (vols.size() != 0) {
                _storageMgr.destroy(vm, vols);
            }

            return true;
        } finally {
            try {
                txn.start();
                // release critical system resources used by the VM before we
                // delete them
                if (vm.getPublicIpAddress() != null)
                    freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId());
                vm.setPublicIpAddress(null);

                _consoleProxyDao.remove(vm.getId());

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_DESTROY);
                event.setLevel(EventVO.LEVEL_INFO);
                event.setStartId(startEventId);
                event.setDescription("Console proxy destroyed - " + vm.getName());
                _eventDao.persist(event);

                txn.commit();
            } catch (Exception e) {
                s_logger.error("Caught this error: ", e);
                txn.rollback();
                return false;
            } finally {
                s_logger.debug("console proxy vm is destroyed : " + vm.getName());
            }
        }
    }

    @DB
    public boolean destroyProxyDBOnly(long vmId) {
        Transaction txn = Transaction.currentTxn();
        try {
            txn.start();
            _volsDao.deleteVolumesByInstance(vmId);

            ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId);
            if (proxy != null) {
                if (proxy.getPublicIpAddress() != null)
                    freePublicIpAddress(proxy.getPublicIpAddress(), proxy.getDataCenterId(), proxy.getPodId());

                _consoleProxyDao.remove(vmId);

                final EventVO event = new EventVO();
                event.setUserId(User.UID_SYSTEM);
                event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                event.setType(EventTypes.EVENT_PROXY_DESTROY);
                event.setLevel(EventVO.LEVEL_INFO);
                event.setDescription("Console proxy destroyed - " + proxy.getName());
                _eventDao.persist(event);
            }

            txn.commit();
            return true;
        } catch (Exception e) {
            s_logger.error("Caught this error: ", e);
            txn.rollback();
            return false;
        } finally {
            s_logger.debug("console proxy vm is destroyed from DB : " + vmId);
        }
    }

    @Override
    public boolean stop(ConsoleProxyVO proxy, long startEventId) throws AgentUnavailableException {
        if (!_consoleProxyDao.updateIf(proxy, Event.StopRequested, proxy.getHostId())) {
            s_logger.debug("Unable to stop console proxy: " + proxy.toString());
            return false;
        }

        // IPAddressVO ip = _ipAddressDao.findById(proxy.getPublicIpAddress());
        // VlanVO vlan = _vlanDao.findById(new Long(ip.getVlanDbId()));

        GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxy.getId()));
        try {
            if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
                try {
                    StopCommand cmd = new StopCommand(proxy, true, Integer.toString(_consoleProxyPort), Integer.toString(_consoleProxyUrlPort),
                            proxy.getPublicIpAddress());
                    try {
                        Long proxyHostId = proxy.getHostId();
                        if (proxyHostId == null) {
                            s_logger.debug("Unable to stop due to proxy " + proxy.getId()
                                    + " as host is no longer available, proxy may already have been stopped");
                            return false;
                        }
                        StopAnswer answer = (StopAnswer) _agentMgr.send(proxyHostId, cmd);
                        if (answer == null || !answer.getResult()) {
                            s_logger.debug("Unable to stop due to " + (answer == null ? "answer is null" : answer.getDetails()));

                            final EventVO event = new EventVO();
                            event.setUserId(User.UID_SYSTEM);
                            event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                            event.setType(EventTypes.EVENT_PROXY_STOP);
                            event.setLevel(EventVO.LEVEL_ERROR);
                            event.setStartId(startEventId);
                            event.setDescription("Stopping console proxy failed due to negative answer from agent - " + proxy.getName());
                            _eventDao.persist(event);
                            return false;
                        }
                        completeStopCommand(proxy, Event.OperationSucceeded);

                        SubscriptionMgr.getInstance().notifySubscribers(
                                ConsoleProxyManager.ALERT_SUBJECT,
                                this,
                                new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_DOWN, proxy.getDataCenterId(), proxy.getId(), proxy,
                                        null));

                        final EventVO event = new EventVO();
                        event.setUserId(User.UID_SYSTEM);
                        event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                        event.setType(EventTypes.EVENT_PROXY_STOP);
                        event.setLevel(EventVO.LEVEL_INFO);
                        event.setStartId(startEventId);
                        event.setDescription("Console proxy stopped - " + proxy.getName());
                        _eventDao.persist(event);
                        return true;
                    } catch (OperationTimedoutException e) {
                        final EventVO event = new EventVO();
                        event.setUserId(User.UID_SYSTEM);
                        event.setAccountId(Account.ACCOUNT_ID_SYSTEM);
                        event.setType(EventTypes.EVENT_PROXY_STOP);
                        event.setLevel(EventVO.LEVEL_ERROR);
                        event.setStartId(startEventId);
                        event.setDescription("Stopping console proxy failed due to operation time out - " + proxy.getName());
                        _eventDao.persist(event);
                        throw new AgentUnavailableException(proxy.getHostId());
                    }
                } finally {
                    proxyLock.unlock();
                }
            } else {
                s_logger.debug("Unable to acquire console proxy lock : " + proxy.toString());
                return false;
            }
        } finally {
            proxyLock.releaseRef();
        }
    }

    @Override
    public boolean migrate(ConsoleProxyVO proxy, HostVO host) {
        HostVO fromHost = _hostDao.findById(proxy.getId());

        if (!_consoleProxyDao.updateIf(proxy, Event.MigrationRequested, proxy.getHostId())) {
            s_logger.debug("State for " + proxy.toString() + " has changed so migration can not take place.");
            return false;
        }

        MigrateCommand cmd = new MigrateCommand(proxy.getInstanceName(), host.getPrivateIpAddress(), false);
        Answer answer = _agentMgr.easySend(fromHost.getId(), cmd);
        if (answer == null) {
            return false;
        }

        _storageMgr.unshare(proxy, fromHost);

        return true;
    }

    @Override
    public boolean completeMigration(ConsoleProxyVO proxy, HostVO host) throws AgentUnavailableException, OperationTimedoutException {

        CheckVirtualMachineCommand cvm = new CheckVirtualMachineCommand(proxy.getInstanceName());
        CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(host.getId(), cvm);
        if (!answer.getResult()) {
            s_logger.debug("Unable to complete migration for " + proxy.getId());
            _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null);
            return false;
        }

        State state = answer.getState();
        if (state == State.Stopped) {
            s_logger.warn("Unable to complete migration as we can not detect it on " + host.getId());
            _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null);
            return false;
        }

        _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, host.getId());
        return true;
    }

    @Override
    public HostVO prepareForMigration(ConsoleProxyVO proxy) throws StorageUnavailableException {

        VMTemplateVO template = _templateDao.findById(proxy.getTemplateId());
        long routerId = proxy.getId();
        boolean mirroredVols = proxy.isMirroredVols();
        DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId());
        HostPodVO pod = _podDao.findById(proxy.getPodId());
        List sps = _storageMgr.getStoragePoolsForVm(proxy.getId());
        StoragePoolVO sp = sps.get(0); // FIXME

        List vols = _volsDao.findCreatedByInstance(routerId);

        String[] storageIps = new String[2];
        VolumeVO vol = vols.get(0);
        storageIps[0] = vol.getHostIp();
        if (mirroredVols && (vols.size() == 2)) {
            storageIps[1] = vols.get(1).getHostIp();
        }
        PrepareForMigrationCommand cmd = new PrepareForMigrationCommand(proxy.getName(), null, storageIps, vols, mirroredVols);

        HostVO routingHost = null;
        HashSet avoid = new HashSet();

        HostVO fromHost = _hostDao.findById(proxy.getHostId());
        if (fromHost.getClusterId() == null) {
            s_logger.debug("The host is not in a cluster");
            return null;
        }
        avoid.add(fromHost);

        while ((routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, template, proxy, fromHost, avoid)) != null) {
            avoid.add(routingHost);

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Trying to migrate router to host " + routingHost.getName());
            }

            if (!_storageMgr.share(proxy, vols, routingHost, false)) {
                s_logger.warn("Can not share " + proxy.getName());
                throw new StorageUnavailableException(vol.getPoolId());
            }

            Answer answer = _agentMgr.easySend(routingHost.getId(), cmd);
            if (answer != null && answer.getResult()) {
                return routingHost;
            }
            _storageMgr.unshare(proxy, vols, routingHost);
        }

        return null;
    }

    private String getCapacityScanLockName() {
        // to improve security, it may be better to return a unique mashed
        // name(for example MD5 hashed)
        return "consoleproxy.capacity.scan";
    }

    private String getAllocProxyLockName() {
        // to improve security, it may be better to return a unique mashed
        // name(for example MD5 hashed)
        return "consoleproxy.alloc";
    private String getProxyLockName(long id) {
        return "consoleproxy." + id;
    }

    private Long saveStartedEvent(Long userId, Long accountId, String type, String description, long startEventId) {
        EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(accountId);
        event.setType(type);
        event.setState(EventState.Started);
        event.setDescription(description);
        event.setStartId(startEventId);
        event = _eventDao.persist(event);
        if (event != null)
            return event.getId();
        return null;
    }

    @Override
    public boolean configure(String name, Map params) throws ConfigurationException {
        if (s_logger.isInfoEnabled())
            s_logger.info("Start configuring console proxy manager : " + name);

        _name = name;

        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
        if (configDao == null) {
            throw new ConfigurationException("Unable to get the configuration dao.");
        }

        Map configs = configDao.getConfiguration("management-server", params);

        _proxyRamSize = NumbersUtil.parseInt(configs.get("consoleproxy.ram.size"), DEFAULT_PROXY_VM_RAMSIZE);

        String value = configs.get("start.retry");
        _find_host_retry = NumbersUtil.parseInt(value, DEFAULT_FIND_HOST_RETRY_COUNT);

        value = configs.get("consoleproxy.cmd.port");
        _proxyCmdPort = NumbersUtil.parseInt(value, DEFAULT_PROXY_CMD_PORT);

        value = configs.get("consoleproxy.sslEnabled");
        if (value != null && value.equalsIgnoreCase("true"))
            _sslEnabled = true;

        value = configs.get("consoleproxy.capacityscan.interval");
        _capacityScanInterval = NumbersUtil.parseLong(value, DEFAULT_CAPACITY_SCAN_INTERVAL);

        _capacityPerProxy = NumbersUtil.parseInt(configs.get("consoleproxy.session.max"), DEFAULT_PROXY_CAPACITY);
        _standbyCapacity = NumbersUtil.parseInt(configs.get("consoleproxy.capacity.standby"), DEFAULT_STANDBY_CAPACITY);
        _proxySessionTimeoutValue = NumbersUtil.parseInt(configs.get("consoleproxy.session.timeout"), DEFAULT_PROXY_SESSION_TIMEOUT);

        value = configs.get("consoleproxy.port");
        if (value != null)
            _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT);

        value = configs.get("consoleproxy.url.port");
        if (value != null)
            _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT);

        value = configs.get("system.vm.use.local.storage");
        if (value != null && value.equalsIgnoreCase("true"))
            _use_lvm = true;

        value = configs.get("secondary.storage.vm");
        if (value != null && value.equalsIgnoreCase("true"))
            _use_storage_vm = true;

        if (s_logger.isInfoEnabled()) {
            s_logger.info("Console proxy max session soft limit : " + _capacityPerProxy);
            s_logger.info("Console proxy standby capacity : " + _standbyCapacity);
        }

        _domain = configs.get("domain");
        if (_domain == null) {
            _domain = "foo.com";
        }

        _instance = configs.get("instance.name");
        if (_instance == null) {
            _instance = "DEFAULT";
        }

        value = (String) params.get("ssh.sleep");
        _ssh_sleep = NumbersUtil.parseInt(value, 5) * 1000;

        value = (String) params.get("ssh.retry");
        _ssh_retry = NumbersUtil.parseInt(value, 3);

        Map agentMgrConfigs = configDao.getConfiguration("AgentManager", params);
        _mgmt_host = agentMgrConfigs.get("host");
        if (_mgmt_host == null) {
            s_logger.warn("Critical warning! Please configure your management server host address right after you have started your management server and then restart it, otherwise you won't be able to do console access");
        }

        value = agentMgrConfigs.get("port");
        _mgmt_port = NumbersUtil.parseInt(value, 8250);

        _consoleProxyAllocators = locator.getAdapters(ConsoleProxyAllocator.class);
        if (_consoleProxyAllocators == null || !_consoleProxyAllocators.isSet()) {
            throw new ConfigurationException("Unable to get proxy allocators");
        }

        _listener = new ConsoleProxyListener(this);
        _agentMgr.registerForHostEvents(_listener, true, true, false);

        Adapters ipAllocators = locator.getAdapters(IpAddrAllocator.class);
        if (ipAllocators != null && ipAllocators.isSet()) {
            Enumeration it = ipAllocators.enumeration();
            _IpAllocator = it.nextElement();
        }

        HighAvailabilityManager haMgr = locator.getManager(HighAvailabilityManager.class);
        if (haMgr != null) {
            haMgr.registerHandler(VirtualMachine.Type.ConsoleProxy, this);
        }

        boolean useLocalStorage = Boolean.parseBoolean((String) params.get(Config.SystemVMUseLocalStorage.key()));
        String networkRateStr = _configDao.getValue("network.throttling.rate");
        String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
        _networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr));
        _multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr));
        _serviceOffering = new ServiceOfferingVO("Fake Offering For DomP", 1, _proxyRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized,
                useLocalStorage, true, null);
        _serviceOffering.setUniqueName("Cloud.com-ConsoleProxy");
        _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering);
        _template = _templateDao.findConsoleProxyTemplate();
        if (_template == null) {
            throw new ConfigurationException("Unable to find the template for console proxy VMs");
        }
        _capacityScanScheduler.scheduleAtFixedRate(getCapacityScanTask(), STARTUP_DELAY, _capacityScanInterval, TimeUnit.MILLISECONDS);

        if (s_logger.isInfoEnabled())
            s_logger.info("Console Proxy Manager is configured.");
        return true;
    }

    @Override
    public boolean destroyConsoleProxy(DestroyConsoleProxyCmd cmd) throws ServerApiException{
        Long proxyId = cmd.getId();
        
        // verify parameters
        ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId);
        if (proxy == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a console proxy with id " + proxyId);
        }
        
        long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_DESTROY, "destroying console proxy with Id: "+proxyId);
        
        return destroyProxy(proxyId, eventId);
        
    }

    protected ConsoleProxyManagerImpl() {
    }
}
File
ConsoleProxyManagerImpl.java
Developer's decision
Combination
Kind of conflict
Annotation
Attribute
Class signature
Comment
Method declaration
Method invocation
Chunk
Conflicting content
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.host.Host.Type;
<<<<<<< HEAD
import com.cloud.host.HostVO;
=======
import com.cloud.info.ConsoleProxyInfo;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.vm.ConsoleProxyVO;
Solution content
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.vm.ConsoleProxyVO;
File
StaticConsoleProxyManager.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.migration.DiskOffering21VO.Type;
<<<<<<< HEAD
import com.cloud.offering.ServiceOffering.GuestIpType;
=======
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VolumeVO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.Volume.VolumeType;
Solution content
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.migration.DiskOffering21VO.Type;
import com.cloud.offering.NetworkOffering;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.Volume.VolumeType;
File
Db20to21MigrationUtil.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.api.commands.DisassociateIPAddrCmd;
import java.util.List;
import java.util.Map;

<<<<<<< HEAD
import com.cloud.api.commands.AssignToLoadBalancerRuleCmd;
import com.cloud.api.commands.AssociateIPAddrCmd;
import com.cloud.api.commands.CreateIPForwardingRuleCmd;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.api.commands.DeleteIPForwardingRuleCmd;
import com.cloud.api.commands.DeleteLoadBalancerRuleCmd;
import com.cloud.api.commands.DeletePortForwardingServiceRuleCmd;
import com.cloud.api.commands.StopRouterCmd;
import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.api.commands.RebootRouterCmd;
import com.cloud.api.commands.RemoveFromLoadBalancerRuleCmd;
import com.cloud.api.commands.StartRouterCmd;
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
=======
import com.cloud.agent.api.to.NicTO;
import com.cloud.async.executor.AssignToLoadBalancerExecutor;
import com.cloud.async.executor.LoadBalancerParam;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.VlanVO;
Solution content
import java.util.List;
import java.util.Map;

import com.cloud.agent.api.to.NicTO;
import com.cloud.api.commands.AssignToLoadBalancerRuleCmd;
import com.cloud.api.commands.AssociateIPAddrCmd;
import com.cloud.api.commands.CreateIPForwardingRuleCmd;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.api.commands.DeleteIPForwardingRuleCmd;
import com.cloud.api.commands.DeleteLoadBalancerRuleCmd;
import com.cloud.api.commands.DeletePortForwardingServiceRuleCmd;
import com.cloud.api.commands.DisassociateIPAddrCmd;
import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.api.commands.RebootRouterCmd;
import com.cloud.api.commands.RemoveFromLoadBalancerRuleCmd;
import com.cloud.api.commands.StartRouterCmd;
import com.cloud.api.commands.StopRouterCmd;
import com.cloud.api.commands.UpdateLoadBalancerRuleCmd;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.VlanVO;
File
NetworkManager.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
<<<<<<< HEAD
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
=======
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.exception.ResourceAllocationException;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.service.ServiceOfferingVO;
Solution content
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.service.ServiceOfferingVO;
File
NetworkManager.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
     * @param sourceNat - (optional) true if the IP address should be a source NAT address
     * @return - list of IP addresses
     */
<<<<<<< HEAD
    List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat);	
    
    public boolean deleteNetworkRuleConfig(DeletePortForwardingServiceRuleCmd cmd) throws PermissionDeniedException;
	
    public boolean disassociateIpAddress(DisassociateIPAddrCmd cmd) throws PermissionDeniedException;
    
    public boolean deleteIpForwardingRule(DeleteIPForwardingRuleCmd cmd) throws PermissionDeniedException, InvalidParameterValueException;

=======
    List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat);
    
    NetworkConfigurationVO setupNetworkConfiguration(AccountVO owner, NetworkOfferingVO offering, DeploymentPlan plan);
    NetworkConfigurationVO setupNetworkConfiguration(AccountVO owner, NetworkOfferingVO offering, NetworkConfiguration predefined, DeploymentPlan plan);
    List setupNetworkConfigurations(AccountVO owner, List offerings, DeploymentPlan plan);
    
    List getSystemAccountNetworkOfferings(String... offeringNames);
    
    List allocate(VirtualMachineProfile vm, List> networks) throws InsufficientCapacityException;

    NicTO[] prepare(VirtualMachineProfile profile, DeployDestination dest) throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapcityException;
    
     void create(K vm);
    
     List getNics(K vm);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
     * @param sourceNat - (optional) true if the IP address should be a source NAT address
     * @return - list of IP addresses
     */
    List listPublicIpAddressesInVirtualNetwork(long accountId, long dcId, Boolean sourceNat);	
    
    public boolean deleteNetworkRuleConfig(DeletePortForwardingServiceRuleCmd cmd) throws PermissionDeniedException;
	
    public boolean disassociateIpAddress(DisassociateIPAddrCmd cmd) throws PermissionDeniedException;
    
    public boolean deleteIpForwardingRule(DeleteIPForwardingRuleCmd cmd) throws PermissionDeniedException, InvalidParameterValueException;

    NetworkConfigurationVO setupNetworkConfiguration(AccountVO owner, NetworkOfferingVO offering, DeploymentPlan plan);
    NetworkConfigurationVO setupNetworkConfiguration(AccountVO owner, NetworkOfferingVO offering, NetworkConfiguration predefined, DeploymentPlan plan);
    List setupNetworkConfigurations(AccountVO owner, List offerings, DeploymentPlan plan);
    
    List getSystemAccountNetworkOfferings(String... offeringNames);
    
    List allocate(VirtualMachineProfile vm, List> networks) throws InsufficientCapacityException;

    NicTO[] prepare(VirtualMachineProfile profile, DeployDestination dest) throws InsufficientAddressCapacityException, InsufficientVirtualNetworkCapcityException;
    
     void create(K vm);
    
     List getNics(K vm);
}
File
NetworkManager.java
Developer's decision
Combination
Kind of conflict
Method interface
Chunk
Conflicting content
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetFirewallRuleCommand;
import com.cloud.agent.api.routing.VmDataCommand;
<<<<<<< HEAD
import com.cloud.agent.manager.AgentManager;
=======
import com.cloud.agent.api.to.NicTO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.alert.AlertManager;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
Solution content
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetFirewallRuleCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
File
NetworkManagerImpl.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
<<<<<<< HEAD
import com.cloud.dc.dao.AccountVlanMapDao;
=======
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
Solution content
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
File
NetworkManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.network.dao.SecurityGroupDao;
=======
import com.cloud.network.dao.NetworkConfigurationDao;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
<<<<<<< HEAD
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.offering.NetworkOffering;
Solution content
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkConfigurationDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.offering.NetworkOffering;
File
NetworkManagerImpl.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
=======
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineName;
<<<<<<< HEAD
import com.cloud.vm.VirtualMachineProfile;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
Solution content
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineName;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
File
NetworkManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
    @Inject StoragePoolDao _storagePoolDao = null;
    @Inject SecurityGroupDao _securityGroupDao = null;
    @Inject ServiceOfferingDao _serviceOfferingDao = null;
<<<<<<< HEAD
    @Inject UserStatisticsDao _statsDao;
    @Inject UserVmDao _userVmDao;
    @Inject FirewallRulesDao _firewallRulesDao;
    @Inject NetworkRuleConfigDao _networkRuleConfigDao;
    @Inject AccountVlanMapDao _accountVlanMapDao;
=======
    @Inject UserStatisticsDao _statsDao = null;
    @Inject NetworkOfferingDao _networkOfferingDao = null;
    @Inject NetworkConfigurationDao _networkProfileDao = null;
    @Inject NicDao _nicDao;
    
    @Inject(adapter=NetworkGuru.class)
    Adapters _networkGurus;
    @Inject(adapter=NetworkElement.class)
    Adapters _networkElements;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    long _routerTemplateId = -1;
    int _routerRamSize;
    // String _privateNetmask;
Solution content
    @Inject StoragePoolDao _storagePoolDao = null;
    @Inject SecurityGroupDao _securityGroupDao = null;
    @Inject ServiceOfferingDao _serviceOfferingDao = null;
    @Inject UserVmDao _userVmDao;
    @Inject FirewallRulesDao _firewallRulesDao;
    @Inject NetworkRuleConfigDao _networkRuleConfigDao;
    @Inject AccountVlanMapDao _accountVlanMapDao;
    @Inject UserStatisticsDao _statsDao = null;
    @Inject NetworkOfferingDao _networkOfferingDao = null;
    @Inject NetworkConfigurationDao _networkProfileDao = null;
    @Inject NicDao _nicDao;
    
    @Inject(adapter=NetworkGuru.class)
    Adapters _networkGurus;
    @Inject(adapter=NetworkElement.class)
    Adapters _networkElements;

    long _routerTemplateId = -1;
    int _routerRamSize;
    // String _privateNetmask;
File
NetworkManagerImpl.java
Developer's decision
Combination
Kind of conflict
Annotation
Attribute
Chunk
Conflicting content
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
<<<<<<< HEAD
import com.cloud.agent.manager.AgentManager;
=======
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.alert.AlertManager;
import com.cloud.alert.AlertVO;
import com.cloud.alert.dao.AlertDao;
Solution content
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.alert.AlertVO;
import com.cloud.alert.dao.AlertDao;
File
ManagementServerImpl.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeleteUserCmd;
import com.cloud.api.commands.DeployVMCmd;
<<<<<<< HEAD
import com.cloud.api.commands.EnableAccountCmd;
import com.cloud.api.commands.EnableUserCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapacityCmd;
import com.cloud.api.commands.ListCfgsByCmd;
import com.cloud.api.commands.ListClustersCmd;
import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListIsosCmd;
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPortForwardingServiceRulesCmd;
import com.cloud.api.commands.ListPortForwardingServicesByVmCmd;
import com.cloud.api.commands.ListPortForwardingServicesCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListStoragePoolsAndHostsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.LockAccountCmd;
import com.cloud.api.commands.LockUserCmd;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.RemovePortForwardingServiceCmd;
=======
import com.cloud.api.commands.ExtractIsoCmd;
import com.cloud.api.commands.ExtractTemplateCmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.PrepareForMaintenanceCmd;
import com.cloud.api.commands.PreparePrimaryStorageForMaintenanceCmd;
import com.cloud.api.commands.ReconnectHostCmd;
import com.cloud.api.commands.StartRouterCmd;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateAccountCmd;
Solution content
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeleteUserCmd;
import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.EnableAccountCmd;
import com.cloud.api.commands.EnableUserCmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapabilitiesCmd;
import com.cloud.api.commands.ListCapacityCmd;
import com.cloud.api.commands.ListCfgsByCmd;
import com.cloud.api.commands.ListClustersCmd;
import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListIsosCmd;
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPortForwardingServiceRulesCmd;
import com.cloud.api.commands.ListPortForwardingServicesByVmCmd;
import com.cloud.api.commands.ListPortForwardingServicesCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListStoragePoolsAndHostsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMGroupsCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.LockAccountCmd;
import com.cloud.api.commands.LockUserCmd;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.RemovePortForwardingServiceCmd;
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateAccountCmd;
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
<<<<<<< HEAD
=======
import com.cloud.async.executor.AssociateIpAddressParam;
import com.cloud.async.executor.AttachISOParam;
import com.cloud.async.executor.CopyTemplateParam;
import com.cloud.async.executor.CreateOrUpdateRuleParam;
import com.cloud.async.executor.CreatePrivateTemplateParam;
import com.cloud.async.executor.DeleteDomainParam;
import com.cloud.async.executor.DeleteRuleParam;
import com.cloud.async.executor.DeleteTemplateParam;
import com.cloud.async.executor.DeployVMParam;
import com.cloud.async.executor.DisassociateIpAddressParam;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.async.executor.ExtractTemplateParam;
import com.cloud.async.executor.LoadBalancerParam;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.async.executor.NetworkGroupIngressParam;
import com.cloud.async.executor.SecurityGroupParam;
import com.cloud.async.executor.VMOperationParam;
Solution content

        try {
        return true;
    }

    @Override
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.network.FirewallRuleVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVMMapVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkRuleConfigVO;
import com.cloud.network.SecurityGroupVMMapVO;
import com.cloud.network.SecurityGroupVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.security.NetworkGroupManager;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.network.security.dao.NetworkGroupDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.DiskTemplateVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Snapshot.SnapshotType;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.DiskTemplateDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.LaunchPermissionDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVMMapVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.InstanceGroupVMMapDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

public class ManagementServerImpl implements ManagementServer {	
    public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());

    private final AccountManager _accountMgr;
    private final AgentManager _agentMgr;
    private final ConfigurationManager _configMgr;
    private final FirewallRulesDao _firewallRulesDao;
    private final SecurityGroupDao _securityGroupDao;
	private final NetworkGroupDao _networkSecurityGroupDao;
    private final LoadBalancerDao _loadBalancerDao;
    private final NetworkRuleConfigDao _networkRuleConfigDao;
    private final SecurityGroupVMMapDao _securityGroupVMMapDao;
    private final IPAddressDao _publicIpAddressDao;
    private final DataCenterIpAddressDaoImpl _privateIpAddressDao;
    private final LoadBalancerVMMapDao _loadBalancerVMMapDao;
    private final DomainRouterDao _routerDao;
    private final ConsoleProxyDao _consoleProxyDao;
    private final ClusterDao _clusterDao;
    private final SecondaryStorageVmDao _secStorageVmDao;
    private final EventDao _eventDao;
    private final DataCenterDao _dcDao;
    private final VlanDao _vlanDao;
    private final AccountVlanMapDao _accountVlanMapDao;
    private final PodVlanMapDao _podVlanMapDao;
    private final HostDao _hostDao;
    private final UserDao _userDao;
    private final UserVmDao _userVmDao;
    private final ConfigurationDao _configDao;
    private final NetworkManager _networkMgr;
    private final UserVmManager _vmMgr;
    private final ConsoleProxyManager _consoleProxyMgr;
    private final SecondaryStorageVmManager _secStorageVmMgr;
    private final ServiceOfferingDao _offeringsDao;
    private final DiskOfferingDao _diskOfferingDao;
    private final VMTemplateDao _templateDao;
    private final LaunchPermissionDao _launchPermissionDao;
    private final DomainDao _domainDao;
    private final AccountDao _accountDao;
    private final ResourceLimitDao _resourceLimitDao;
    private final UserAccountDao _userAccountDao;
    private final AlertDao _alertDao;
    private final CapacityDao _capacityDao;
    private final SnapshotDao _snapshotDao;
    private final SnapshotPolicyDao _snapshotPolicyDao;
    private final GuestOSDao _guestOSDao;
    private final GuestOSCategoryDao _guestOSCategoryDao;
    private final StoragePoolDao _poolDao;
    private final StoragePoolHostDao _poolHostDao;
    private final StorageManager _storageMgr;
    private final UserVmDao _vmDao;

    private final Adapters _userAuthenticators;
    private final HostPodDao _hostPodDao;
    private final UserStatisticsDao _userStatsDao;
    private final VMInstanceDao _vmInstanceDao;
    private final VolumeDao _volumeDao;
    private final DiskTemplateDao _diskTemplateDao;
    private final AlertManager _alertMgr;
    private final AsyncJobDao _jobDao;
    private final AsyncJobManager _asyncMgr;
    private final TemplateManager _tmpltMgr;
    private final SnapshotManager _snapMgr;
    private final NetworkGroupManager _networkGroupMgr;
    private final int _purgeDelay;
    private final boolean _directAttachNetworkExternalIpAllocator;
    private final PreallocatedLunDao _lunDao;
    private final InstanceGroupDao _vmGroupDao;
    private final InstanceGroupVMMapDao _groupVMMapDao;
    private final UploadMonitor _uploadMonitor;
    private final UploadDao _uploadDao;

    private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
    private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));

    private final StatsCollector _statsCollector;

    private final Map _configs;

    private String _domain;

    private final int _routerRamSize;
    private final int _proxyRamSize;
    private final int _ssRamSize;

    private final Map _availableIdsMap;

	private boolean _networkGroupsEnabled = false;

        _domain = _configs.get("domain");
    private boolean _isHypervisorSnapshotCapable = false;

    protected ManagementServerImpl() {
        ComponentLocator locator = ComponentLocator.getLocator(Name);
        _lunDao = locator.getDao(PreallocatedLunDao.class);
        _configDao = locator.getDao(ConfigurationDao.class);
        _routerDao = locator.getDao(DomainRouterDao.class);
        _eventDao = locator.getDao(EventDao.class);
        _dcDao = locator.getDao(DataCenterDao.class);
        _vlanDao = locator.getDao(VlanDao.class);
        _accountVlanMapDao = locator.getDao(AccountVlanMapDao.class);
        _podVlanMapDao = locator.getDao(PodVlanMapDao.class);
        _hostDao = locator.getDao(HostDao.class);
        _hostPodDao = locator.getDao(HostPodDao.class);
        _jobDao = locator.getDao(AsyncJobDao.class);
        _clusterDao = locator.getDao(ClusterDao.class);

        _accountMgr = locator.getManager(AccountManager.class);
        _agentMgr = locator.getManager(AgentManager.class);
        _configMgr = locator.getManager(ConfigurationManager.class);
        _networkMgr = locator.getManager(NetworkManager.class);
        _vmMgr = locator.getManager(UserVmManager.class);
        _consoleProxyMgr = locator.getManager(ConsoleProxyManager.class);
        _secStorageVmMgr = locator.getManager(SecondaryStorageVmManager.class);
        _storageMgr = locator.getManager(StorageManager.class);
        _firewallRulesDao = locator.getDao(FirewallRulesDao.class);
        _securityGroupDao = locator.getDao(SecurityGroupDao.class);
        _networkSecurityGroupDao  = locator.getDao(NetworkGroupDao.class);
        _loadBalancerDao = locator.getDao(LoadBalancerDao.class);
        _networkRuleConfigDao = locator.getDao(NetworkRuleConfigDao.class);
        _securityGroupVMMapDao = locator.getDao(SecurityGroupVMMapDao.class);
        _publicIpAddressDao = locator.getDao(IPAddressDao.class);
        _privateIpAddressDao = locator.getDao(DataCenterIpAddressDaoImpl.class);
        _loadBalancerVMMapDao = locator.getDao(LoadBalancerVMMapDao.class);
        _consoleProxyDao = locator.getDao(ConsoleProxyDao.class);
        _secStorageVmDao = locator.getDao(SecondaryStorageVmDao.class);
        _userDao = locator.getDao(UserDao.class);
        _userVmDao = locator.getDao(UserVmDao.class);
        _offeringsDao = locator.getDao(ServiceOfferingDao.class);
        _diskOfferingDao = locator.getDao(DiskOfferingDao.class);
        _templateDao = locator.getDao(VMTemplateDao.class);
        _launchPermissionDao = locator.getDao(LaunchPermissionDao.class);
        _domainDao = locator.getDao(DomainDao.class);
        _accountDao = locator.getDao(AccountDao.class);
        _resourceLimitDao = locator.getDao(ResourceLimitDao.class);
        _userAccountDao = locator.getDao(UserAccountDao.class);
        _alertDao = locator.getDao(AlertDao.class);
        _capacityDao = locator.getDao(CapacityDao.class);
        _snapshotDao = locator.getDao(SnapshotDao.class);
        _snapshotPolicyDao = locator.getDao(SnapshotPolicyDao.class);
        _guestOSDao = locator.getDao(GuestOSDao.class);
        _guestOSCategoryDao = locator.getDao(GuestOSCategoryDao.class);
        _poolDao = locator.getDao(StoragePoolDao.class);
        _poolHostDao = locator.getDao(StoragePoolHostDao.class);
        _vmDao = locator.getDao(UserVmDao.class);
        _vmGroupDao = locator.getDao(InstanceGroupDao.class);
        _groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class);
        _uploadDao = locator.getDao(UploadDao.class);

        _configs = _configDao.getConfiguration();
        _userStatsDao = locator.getDao(UserStatisticsDao.class);
        _vmInstanceDao = locator.getDao(VMInstanceDao.class);
        _volumeDao = locator.getDao(VolumeDao.class);
        _diskTemplateDao = locator.getDao(DiskTemplateDao.class);
        _alertMgr = locator.getManager(AlertManager.class);
        _asyncMgr = locator.getManager(AsyncJobManager.class);
        _tmpltMgr = locator.getManager(TemplateManager.class);
        _snapMgr = locator.getManager(SnapshotManager.class);
        _networkGroupMgr = locator.getManager(NetworkGroupManager.class);
        _uploadMonitor = locator.getManager(UploadMonitor.class);                
        
        _userAuthenticators = locator.getAdapters(UserAuthenticator.class);
        if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
            s_logger.error("Unable to find an user authenticator.");
        }

            }
        if (_domain == null) {
            _domain = ".myvm.com";
        }
        if (!_domain.startsWith(".")) {
            _domain = "." + _domain;
        }

        String value = _configs.get("account.cleanup.interval");
        int cleanup = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour.

        // Parse the max number of UserVMs and public IPs from server-setup.xml,
        // and set them in the right places
        _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
        _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
        _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);

        _directAttachNetworkExternalIpAllocator =
        										Boolean.parseBoolean(_configs.get("direct.attach.network.externalIpAllocator.enabled"));
        
        _statsCollector = StatsCollector.getInstance(_configs);
        _executor.scheduleAtFixedRate(new AccountCleanupTask(), cleanup, cleanup, TimeUnit.SECONDS);

        _purgeDelay = NumbersUtil.parseInt(_configs.get("event.purge.delay"), 0);
        if(_purgeDelay != 0){
            _eventExecutor.scheduleAtFixedRate(new EventPurgeTask(), cleanup, cleanup, TimeUnit.SECONDS);
        }
        
        String[] availableIds = TimeZone.getAvailableIDs();
        _availableIdsMap = new HashMap(availableIds.length);
        for (String id: availableIds) {
            _availableIdsMap.put(id, true);
        }
        String enabled =_configDao.getValue("direct.attach.network.groups.enabled");
		if ("true".equalsIgnoreCase(enabled)) {
			_networkGroupsEnabled = true;
		}
 		
		String hypervisorType = _configDao.getValue("hypervisor.type");
        _isHypervisorSnapshotCapable  = hypervisorType.equals(Hypervisor.Type.XenServer.name());
    }

    protected Map getConfigs() {
        return _configs;
    }

    @Override
    public StorageStats getStorageStatistics(long hostId) {
        return _statsCollector.getStorageStats(hostId);
    }
    
    @Override
    public PreallocatedLunVO registerPreallocatedLun(RegisterPreallocatedLunCmd cmd) {
        Long zoneId = cmd.getZoneId();
        String portal = cmd.getPortal();
        String targetIqn = cmd.getTargetIqn();
        Integer lun = cmd.getLun();
        Long size = cmd.getDiskSize();
        String t = cmd.getTags();

        String[] tags = null;
        if (t != null) {
            tags = t.split(",");
            for (int i = 0; i < tags.length; i++) {
                tags[i] = tags[i].trim();
            }
        } else {
            tags = new String[0];
        }
        
        PreallocatedLunVO vo = new PreallocatedLunVO(zoneId, portal, targetIqn, lun, size);
        return _lunDao.persist(vo, tags);
    }
    
    @Override
    public boolean unregisterPreallocatedLun(DeletePreallocatedLunCmd cmd) throws IllegalArgumentException {
        Long id = cmd.getId();
    	PreallocatedLunVO lun = null;
    	if ((lun = _lunDao.findById(id)) == null) {
    		throw new IllegalArgumentException("Unable to find a LUN with ID " + id);
    	}
    	
    	if (lun.getTaken() != null) {
    		throw new IllegalArgumentException("The LUN is currently in use and cannot be deleted.");
    	}
    	
        return _lunDao.delete(id);
    }

    @Override
    public VolumeStats[] getVolumeStatistics(long[] volIds) {
        return _statsCollector.getVolumeStats(volIds);
    }

    @Override
    public UserAccount createUser(CreateUserCmd cmd) {
        Long accountId = null;
        String username = cmd.getUsername();
        String password = cmd.getPassword();
        String firstName = cmd.getFirstname();
        String lastName = cmd.getLastname();
        Long domainId = cmd.getDomainId();
        String email = cmd.getEmail();
        String timezone = cmd.getTimezone();
        String accountName = cmd.getAccountName();
        short userType = cmd.getAccountType().shortValue();
        try {
            if (accountName == null) {
                accountName = username;
            }
            if (domainId == null) {
                domainId = DomainVO.ROOT_DOMAIN;
            }

            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account != null) {
                if (account.getType() != userType) {
                    throw new CloudRuntimeException("Account " + accountName + " is not the correct account type for user " + username);
                }
                accountId = account.getId();
            }

            if (!_userAccountDao.validateUsernameInDomain(username, domainId)) {
                throw new CloudRuntimeException("The user " + username + " already exists in domain " + domainId);
            }

            if (accountId == null) {
                if ((userType < Account.ACCOUNT_TYPE_NORMAL) || (userType > Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given; unable to create user");
                }

                // create a new account for the user
                AccountVO newAccount = new AccountVO();
                if (domainId == null) {
                    // root domain is default
                    domainId = DomainVO.ROOT_DOMAIN;
                }

                if ((domainId != DomainVO.ROOT_DOMAIN) && (userType == Account.ACCOUNT_TYPE_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given for an account in domain " + domainId + "; unable to create user.");
                }

                newAccount.setAccountName(accountName);
                newAccount.setDomainId(domainId);
                newAccount.setType(userType);
                newAccount.setState("enabled");
                newAccount = _accountDao.persist(newAccount);
                accountId = newAccount.getId();
            }

            if (accountId == null) {
                throw new CloudRuntimeException("Failed to create account for user: " + username + "; unable to create user");
            }

            UserVO user = new UserVO();
            user.setUsername(username);
            user.setPassword(password);
            user.setState("enabled");
            user.setFirstname(firstName);
            user.setLastname(lastName);
            user.setAccountId(accountId.longValue());
            user.setEmail(email);
            user.setTimezone(timezone);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Creating user: " + username + ", account: " + accountName + " (id:" + accountId + "), domain: " + domainId + " timezone:"+ timezone);
            }

            UserVO dbUser = _userDao.persist(user);
            
            _networkGroupMgr.createDefaultNetworkGroup(accountId);

            if (!user.getPassword().equals(dbUser.getPassword())) {
                throw new CloudRuntimeException("The user " + username + " being creating is using a password that is different than what's in the db");
            }

            EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_CREATE, "User, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId + " was created.");
            return _userAccountDao.findById(dbUser.getId());
        } catch (Exception e) {
        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
        return dcs;
        	EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_CREATE, "Error creating user, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId);
            if (e instanceof CloudRuntimeException) {
                s_logger.info("unable to create user: " + e);
            } else {
                s_logger.warn("unknown exception creating user", e);
            }
            throw new CloudRuntimeException(e.getMessage());
        }
    }

    @Override
    public String updateAdminPassword(long userId, String oldPassword, String newPassword) {
        // String old = StringToMD5(oldPassword);
        // User user = getUser(userId);
        // if (old.equals(user.getPassword())) {
        UserVO userVO = _userDao.createForUpdate(userId);
        userVO.setPassword(StringToMD5(newPassword));
        _userDao.update(userId, userVO);
        return newPassword;
        // } else {
        // return null;
        // }
    }

    private String StringToMD5(String string) {
        MessageDigest md5;

        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new CloudRuntimeException("Error", e);
        }

        md5.reset();
        BigInteger pwInt = new BigInteger(1, md5.digest(string.getBytes()));

        // make sure our MD5 hash value is 32 digits long...
        StringBuffer sb = new StringBuffer();
        String pwStr = pwInt.toString(16);
        int padding = 32 - pwStr.length();
        for (int i = 0; i < padding; i++) {
            sb.append('0');
        }
        sb.append(pwStr);
        return sb.toString();
    }

    @Override
    public User getUser(long userId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId);
        }

        UserVO user = _userDao.getUser(userId);
        if (user == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with id " + userId);
            }
            return null;
        }

        return user;
    }

    @Override
    public User getUser(long userId, boolean active) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId + " and active = " + active);
        }

        if (active) {
            return _userDao.getUser(userId);
        } else {
            return _userDao.findById(userId);
        }
    }

    @Override
    public UserAccount getUserAccount(String username, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user: " + username + " in domain " + domainId);
        }

        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        return userAccount;
    }

    private UserAccount getUserAccount(String username, String password, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
        }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        if (!userAccount.getState().equals("enabled") || !userAccount.getAccountState().equals("enabled")) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("user " + username + " in domain " + domainId + " is disabled/locked (or account is disabled/locked), returning null");
            }
            return null;
        }

        // We only use the first adapter even if multiple have been
        // configured
        Enumeration en = _userAuthenticators.enumeration();
        UserAuthenticator authenticator = en.nextElement();
        boolean authenticated = authenticator.authenticate(username, password, domainId);

        if (authenticated) {
        	return userAccount;
        } else {
        	return null;
        }
    }

    private boolean deleteUserInternal(long userId) {
        UserAccount userAccount = null;
        Long accountId = null;
        String username = null;
        try {
            UserVO user = _userDao.findById(userId);
            if (user == null || user.getRemoved() != null) {
                return true;
            }
            username = user.getUsername();
            boolean result = _userDao.remove(userId);
            if (!result) {
                s_logger.error("Unable to remove the user with id: " + userId + "; username: " + user.getUsername());
                return false;
            }
    }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("User is removed, id: " + userId + "; username: " + user.getUsername());
            }

            accountId = user.getAccountId();
            userAccount = _userAccountDao.findById(userId);

            List users = _userDao.listByAccount(accountId);
            if (users.size() != 0) {
                s_logger.debug("User (" + userId + "/" + user.getUsername() + ") is deleted but there's still other users in the account so not deleting account.");
                return true;
            }

            result = _accountDao.remove(accountId);
            if (!result) {
                s_logger.error("Unable to delete account " + accountId);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Remove account " + accountId);
            }

            AccountVO account = _accountDao.findById(accountId);
            deleteAccount(account);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "User " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + userAccount.getDomainId() + " was deleted.");
            return true;
        } catch (Exception e) {
            s_logger.error("exception deleting user: " + userId, e);
            long domainId = 0L;
            if (userAccount != null)
                domainId = userAccount.getDomainId();
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "Error deleting user " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + domainId);
            return false;
        }
    }

    public boolean deleteAccount(AccountVO account) {
        long accountId = account.getId();
        long userId = 1L; // only admins can delete users, pass in userId 1 XXX: Shouldn't it be userId 2.
        boolean accountCleanupNeeded = false;
        
        try {
        	//delete all vm groups belonging to accont
        	List groups = _vmGroupDao.listByAccountId(accountId);
            for (InstanceGroupVO group : groups) {
            
                if (!_vmMgr.deleteVmGroup(group.getId())) {
                    s_logger.error("Unable to delete group: " + group.getId());
                    accountCleanupNeeded = true;
                } 
            }
        	
            // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
            boolean success = _snapMgr.deleteSnapshotDirsForAccount(accountId);
            if (success) {
                s_logger.debug("Successfully deleted snapshots directories for all volumes under account " + accountId + " across all zones");
            }
            // else, there are no snapshots, hence no directory to delete.
            
            // Destroy the account's VMs
            List vms = _userVmDao.listByAccountId(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of vms (accountId=" + accountId + "): " + vms.size());
            }

            for (UserVmVO vm : vms) {
                if (!_vmMgr.destroyVirtualMachine(userId, vm.getId())) {
                    s_logger.error("Unable to destroy vm: " + vm.getId());
                    accountCleanupNeeded = true;
                } 
            }
            
            // Mark the account's volumes as destroyed
            List volumes = _volumeDao.findDetachedByAccount(accountId);
            for (VolumeVO volume : volumes) {
            	if(volume.getPoolId()==null){
            		accountCleanupNeeded = true;
            	}
            	_storageMgr.destroyVolume(volume);
            }

            // Destroy the account's routers
            List routers = _routerDao.listBy(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of routers (accountId=" + accountId + "): " + routers.size());
            }

            boolean routersCleanedUp = true;
            for (DomainRouterVO router : routers) {
                if (!_networkMgr.destroyRouter(router.getId())) {
                    s_logger.error("Unable to destroy router: " + router.getId());
                    routersCleanedUp = false;
                }
            }

            if (routersCleanedUp) {
            	List ips = _publicIpAddressDao.listByAccount(accountId);
            	
                if (s_logger.isDebugEnabled()) {
            		s_logger.debug("Found " + ips.size() + " public IP addresses for account with ID " + accountId);
                }

            	for (IPAddressVO ip : ips) {
            		Long podId = getPodIdForVlan(ip.getVlanDbId());
            		if (podId != null) {
            			continue;//bug 5561 do not release direct attach pod ips until vm is destroyed
            		}
            		if (!_networkMgr.releasePublicIpAddress(User.UID_SYSTEM, ip.getAddress())) {
            			s_logger.error("Unable to release IP: " + ip.getAddress());
                        accountCleanupNeeded = true;
                    } else {
                    	_accountMgr.decrementResourceCount(accountId, ResourceType.public_ip);
                    }
                }
            } else {
            	accountCleanupNeeded = true;
            }
            
            List securityGroups = _securityGroupDao.listByAccountId(accountId);
            if (securityGroups != null) {
                for (SecurityGroupVO securityGroup : securityGroups) {
                    // All vm instances have been destroyed, delete the security group -> instance_id mappings
                    SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();
                    sc.addAnd("securityGroupId", SearchCriteria.Op.EQ, securityGroup.getId());
                    _securityGroupVMMapDao.expunge(sc);

                    // now clean the network rules and security groups themselves
                    _networkRuleConfigDao.deleteBySecurityGroup(securityGroup.getId());
                    _securityGroupDao.remove(securityGroup.getId());
                }
            }
            // Delete the account's VLANs
            List accountVlans = _vlanDao.listVlansForAccountByType(null, accountId, VlanType.DirectAttached);
            boolean allVlansDeleted = true;
            for (VlanVO vlan : accountVlans) {
            	try {
            		allVlansDeleted = _configMgr.deleteVlanAndPublicIpRange(User.UID_SYSTEM, vlan.getId());
            	} catch (InvalidParameterValueException e) {
            		allVlansDeleted = false;
            	}
            }

            if (!allVlansDeleted) {
            	accountCleanupNeeded = true;
            }
            
            // clean up templates
            List userTemplates = _templateDao.listByAccountId(accountId);
            boolean allTemplatesDeleted = true;
            for (VMTemplateVO template : userTemplates) {
            	try {
            		allTemplatesDeleted = _tmpltMgr.delete(userId, template.getId(), null);
            	} catch (InternalErrorException e) {
            		s_logger.warn("Failed to delete template while removing account: " + template.getName() + " due to: " + e.getMessage());
            		allTemplatesDeleted = false;
            	}
            }
            
            if (!allTemplatesDeleted) {
            	accountCleanupNeeded = true;
            }

            return true;
        } finally {
            s_logger.info("Cleanup for account " + account.getId() + (accountCleanupNeeded ? " is needed." : " is not needed."));
            
            if (accountCleanupNeeded) {
            	_accountDao.markForCleanup(accountId);
            }
        }
    }

    public boolean disableUser(long userId) {
        if (userId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableUser -- invalid user id: " + userId);
            }
            return false;
        }

        return doSetUserStatus(userId, Account.ACCOUNT_STATE_DISABLED);
    }

    @Override
    public boolean enableUser(EnableUserCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long userId = cmd.getId();
    	Account adminAccount = (Account)UserContext.current().getAccountObject();
        boolean success = false;
        
        //Check if user exists in the system
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);
        
        // If the user is a System user, return an error
        Account account = findAccountById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed");
        }

        if ((adminAccount != null) && !isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
        	throw new PermissionDeniedException("Failed to enable user " + userId + ", permission denied.");
        }
        
        success = doSetUserStatus(userId, Account.ACCOUNT_STATE_ENABLED);

        // make sure the account is enabled too
        success = (success && enableAccount(user.getAccountId()));
        
        return success;
    }

    @Override
    public boolean lockUser(LockUserCmd cmd) {
        boolean success = false;
        
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long id = cmd.getId();

        // Check if user with id exists in the system
        User user = _userDao.findById(id);
        if (user == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        } else if (user.getRemoved() != null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        }

        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is a system user, locking is not allowed");
        }

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock user " + id + ", permission denied.");
        }

        // make sure the account is enabled too
        // if the user is either locked already or disabled already, don't change state...only lock currently enabled users
        if (user.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
            // already locked...no-op
            return true;
        } else if (user.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
            success = doSetUserStatus(user.getId(), Account.ACCOUNT_STATE_LOCKED);

            boolean lockAccount = true;
            List allUsersByAccount = _userDao.listByAccount(user.getAccountId());
            for (UserVO oneUser : allUsersByAccount) {
                if (oneUser.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                    lockAccount = false;
                    break;
                }
            }

            if (lockAccount) {
                success = (success && lockAccountInternal(user.getAccountId()));
            }
        } else {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Attempting to lock a non-enabled user, current state is " + user.getState() + " (userId: " + user.getId() + "), locking failed.");
            }
        }
        return success;
    }

    private boolean doSetUserStatus(long userId, String state) {
        UserVO userForUpdate = _userDao.createForUpdate();
        userForUpdate.setState(state);
        return _userDao.update(Long.valueOf(userId), userForUpdate);
    }

    @Override
    public boolean disableAccount(long accountId) {
        boolean success = false;
        if (accountId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableAccount -- invalid account id: " + accountId);
            }
            return false;
        }

        AccountVO account = _accountDao.findById(accountId);
        if ((account == null) || account.getState().equals(Account.ACCOUNT_STATE_DISABLED)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setState(Account.ACCOUNT_STATE_DISABLED);
            success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);

            success = (success && doDisableAccount(accountId));
        }
        return success;
    }

    @Override
    public boolean updateAccount(UpdateAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getDomainId();
    	String accountName = cmd.getAccountName();
    	String newAccountName = cmd.getNewName();
    	
    	if (newAccountName == null) {
    		newAccountName = accountName;
    	}
    	
        boolean success = false;
        Account account = _accountDao.findAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
                AccountVO acctForUpdate = _accountDao.createForUpdate();
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        if (account.getAccountName().equals(accountName)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setAccountName(newAccountName);
            success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate);
        }
        return success;
    }

    private boolean doDisableAccount(long accountId) {
        List vms = _userVmDao.listByAccountId(accountId);
        boolean success = true;
        for (UserVmVO vm : vms) {
            try {
                success = (success && _vmMgr.stop(vm, 0));
            } catch (AgentUnavailableException aue) {
                s_logger.warn("Agent running on host " + vm.getHostId() + " is unavailable, unable to stop vm " + vm.getName());
                success = false;
            }
        }

        List routers = _routerDao.listBy(accountId);
        for (DomainRouterVO router : routers) {
        if (podId != null && zoneId != null)
            success = (success && _networkMgr.stopRouter(router.getId(), 0));
        }

        return success;
    }

    public boolean enableAccount(long accountId) {
        boolean success = false;
        AccountVO acctForUpdate = _accountDao.createForUpdate();
        acctForUpdate.setState(Account.ACCOUNT_STATE_ENABLED);
        success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
        return success;
    }
    	
    
    @Override
    public boolean enableAccount(EnableAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String accountName = cmd.getAccountName();
    	Long domainId = cmd.getDomainId();
        boolean success = false;
        Account account = _accountDao.findActiveAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        success = enableAccount(account.getId());
        return success;
    }

    private boolean lockAccountInternal(long accountId) {
        boolean success = false;
        Account account = _accountDao.findById(accountId);
        if (account != null) {
            if (account.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
                return true; // already locked, no-op
            } else if (account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                acctForUpdate.setState(Account.ACCOUNT_STATE_LOCKED);
                success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
            } else {
                if (s_logger.isInfoEnabled()) {
                    s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
                }
            }
        } else {
            s_logger.warn("Failed to lock account " + accountId + ", account not found.");
        }
        return success;
    }

    @Override
    public boolean updateUser(UpdateUserCmd cmd) throws InvalidParameterValueException {
        Long id = cmd.getId();
        String apiKey = cmd.getApiKey();
        String firstName = cmd.getFirstname();
    	String email = cmd.getEmail();
    	String lastName = cmd.getLastname();
    	String password = cmd.getPassword();
    	String secretKey = cmd.getSecretKey();
    	String timeZone = cmd.getTimezone();
    	String userName = cmd.getUsername();
    	
        //Input validation
    	UserVO user = _userDao.getUser(id);
    	
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user by id");
        }

        if((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide an api key/secret key pair");
        }
        
        // If the account is an admin type, return an error.  We do not allow this
        Account account = (Account)UserContext.current().getAccountObject();
        
        if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is system account, update is not allowed");
        }

        if (firstName == null) { 
        	firstName = user.getFirstname();
        }
        if (lastName == null) { 
        	lastName = user.getLastname(); 
        }
        if (userName == null) { 
        	userName = user.getUsername();  
        }
        if (password == null) { 
        	password = user.getPassword();
        }
        if (email == null) {
        	email = user.getEmail();
        }
        if (timeZone == null) {
        	timeZone = user.getTimezone();
        }
        if (apiKey == null) {
        	apiKey = user.getApiKey();
        }
        if (secretKey == null) {
        	secretKey = user.getSecretKey();
        }

        Long accountId = user.getAccountId();

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("updating user with id: " + id);
        }
        UserAccount userAccount = _userAccountDao.findById(id);
        try {
        	//check if the apiKey and secretKey are globally unique
        	if (apiKey != null && secretKey != null) {
        		Pair apiKeyOwner = findUserByApiKey(apiKey);

        		if(apiKeyOwner != null) {
        			User usr = apiKeyOwner.first();
        			if (usr.getId() != id) {
            			throw new InvalidParameterValueException("The api key:"+apiKey+" exists in the system for user id:"+id+" ,please provide a unique key");
        			} else {
        				//allow the updation to take place
        			}
        		}
        	}

            _userDao.update(id, userName, password, firstName, lastName, email, accountId, timeZone, apiKey, secretKey);
            EventUtils.saveEvent(new Long(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_UPDATE, "User, " + userName + " for accountId = "
                    + accountId + " domainId = " + userAccount.getDomainId() + " and timezone = "+timeZone + " was updated.");
        } catch (Throwable th) {
            s_logger.error("error updating user", th);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_UPDATE, "Error updating user, " + userName
                    + " for accountId = " + accountId + " and domainId = " + userAccount.getDomainId());
            return false;
        }
        return true;
    }
    
    @Override
    public Pair findUserByApiKey(String apiKey) {
        return _accountDao.findUserAccountByApiKey(apiKey);
    }

    @Override
    public Account getAccount(long accountId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving account with id: " + accountId);
        }

        AccountVO account = _accountDao.findById(Long.valueOf(accountId));
        if (account == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find account with id " + accountId);
            }
            return null;
        }

        return account;
    }
    
    @Override
    public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
    	Long userId = cmd.getId();
    	User user = _userDao.findById(userId);

    	if (user == null) {
           throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find user for id : " + userId);
    	}


    	// generate both an api key and a secret key, update the user table with the keys, return the keys to the user
    	String[] keys = new String[2];
    	keys[0] = createApiKey(userId);
    	keys[1] = createSecretKey(userId);

    	return keys;
    }

    private String createApiKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            Pair userAcct = null;
            int retryLimit = 10;
            do {
                // FIXME: what algorithm should we use for API keys?
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userAcct = _accountDao.findUserAccountByApiKey(encodedKey);
                retryLimit--;
            } while ((userAcct != null) && (retryLimit >= 0));

            if (userAcct != null) {
                return null;
            }
            updatedUser.setApiKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    private String createSecretKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            int retryLimit = 10;
            UserVO userBySecretKey = null;
            do {
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userBySecretKey = _userDao.findUserBySecretKey(encodedKey);
                retryLimit--;
            } while ((userBySecretKey != null) && (retryLimit >= 0));

        }
            if (userBySecretKey != null) {
                return null;
            }

            updatedUser.setSecretKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }

    @Override
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
        SearchCriteria sc = _publicIpAddressDao.createSearchCriteria();

        if (accountId != null)
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        if (zoneId != null)
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        if (vlanDbId != null)
            sc.addAnd("vlanDbId", SearchCriteria.Op.EQ, vlanDbId);
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

        return _publicIpAddressDao.search(sc, null);
    }

    @Override
    public List listPrivateIpAddressesBy(Long podId, Long zoneId) {
            return _privateIpAddressDao.listByPodIdDcId(podId.longValue(), zoneId.longValue());
        else
            return new ArrayList();
    }

    @Override
    public String generateRandomPassword() {
    	return PasswordGenerator.generateRandomPassword();
    }

    @Override
    public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
    	UserVmVO vm = _userVmDao.findById(vmId);
    	VMTemplateVO iso = _templateDao.findById(isoId);
    	if(attach){
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_ATTACH, "Attaching ISO: "+isoId+" to Vm: "+vmId, startEventId);
    	} else {
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_DETACH, "Detaching ISO: "+isoId+" from Vm: "+vmId, startEventId);
    	}
        boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach);

        if (success) {
            if (attach) {
                vm.setIsoId(iso.getId().longValue());
            } else {
                vm.setIsoId(null);
            }
            _userVmDao.update(vmId, vm);

            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_ATTACH, "Successfully attached ISO: " + iso.getName() + " to VM with ID: " + vmId,
                        null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_DETACH, "Successfully detached ISO from VM with ID: " + vmId, null, startEventId);
            }
        } else {
            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_ATTACH, "Failed to attach ISO: " + iso.getName() + " to VM with ID: " + vmId, null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_DETACH, "Failed to detach ISO from VM with ID: " + vmId, null, startEventId);
            }
        }
        return success;
    }

    private boolean validPassword(String password) {
        for (int i = 0; i < password.length(); i++) {
            if (password.charAt(i) == ' ') {
                return false;
            }
    private UserVm deployVirtualMachineImpl(long userId, long accountId, long dataCenterId, long serviceOfferingId, long templateId, Long diskOfferingId,
            String domain, String password, String displayName, String group, String userData, String [] networkGroups, long startEventId, long size) throws ResourceAllocationException, InvalidParameterValueException, InternalErrorException,
            InsufficientStorageCapacityException, PermissionDeniedException, ExecutionException, StorageUnavailableException, ConcurrentOperationException {

    	EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "Deploying Vm", startEventId);
        
        AccountVO account = _accountDao.findById(accountId);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        VMTemplateVO template = _templateDao.findById(templateId);

        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }
        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
			
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        
        // TODO: Checks such as is the user allowed to use the template and purchase the service offering id.
        if (domain == null) {
            domain = "v" + Long.toHexString(accountId) + _domain;
        }

        // Check that the password was passed in and is valid
        if (!template.getEnablePassword()) {
            password = "saved_password";
        }

        if (password == null || password.equals("") || (!validPassword(password))) {
            throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
        }
        List networkGroupVOs = new ArrayList();
        if (networkGroups != null) {
        	for (String groupName: networkGroups) {
        		NetworkGroupVO networkGroupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
        		if (networkGroupVO == null) {
        			throw new InvalidParameterValueException("Network Group " + groupName + " does not exist");
        		}
        		networkGroupVOs.add(networkGroupVO);
        	}
        }
        
        UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dataCenterId);
        if (stats == null) {
            stats = new UserStatisticsVO(account.getId(), dataCenterId);
            _userStatsDao.persist(stats);
        }
        
    	Long vmId = _vmDao.getNextInSequence(Long.class, "id");
    	
        // check if we are within context of async-execution
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("DeployVM acquired a new instance " + vmId + ", update async job-" + job.getId() + " progress status");

            _asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", vmId);
            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, vmId);
        }

        HashMap avoids = new HashMap();

        // Pod allocator now allocate VM based on a reservation style allocation, disable retry here for now
        for (int retry = 0; retry < 1; retry++) {
            String externalIp = null;
            UserVmVO created = null;

            ArrayList a = new ArrayList(avoids.values());
            if (_directAttachNetworkExternalIpAllocator) {
            	try {
            		created = _vmMgr.createDirectlyAttachedVMExternal(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            	} catch (ResourceAllocationException rae) {
            		throw rae;
            	}
            } else {
            	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
            		try {
            			externalIp = _networkMgr.assignSourceNatIpAddress(account, dc, domain, offering, startEventId);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}

            		if (externalIp == null) {
            			throw new InternalErrorException("Unable to allocate a source nat ip address");
            		}

            		if (s_logger.isDebugEnabled()) {
            			s_logger.debug("Source Nat acquired: " + externalIp);
            		}

            		try {
            			created = _vmMgr.createVirtualMachine(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	} else {
            		try {
            			created = _vmMgr.createDirectlyAttachedVM(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	}
            }
            //assign vm to the group
            try{
            	if (group != null) {
            	boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
            	if (!addToGroup) {
            		throw new InternalErrorException("Unable to assing Vm to the group " + group);
            	}
                }
            } catch (Exception ex) {
            	throw new InternalErrorException("Unable to assing Vm to the group " + group);
            }
            
            
            if (created == null) {
                throw new InternalErrorException("Unable to create VM for account (" + accountId + "): " + account.getAccountName());
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM created: " + created.getId() + "-" + created.getName());
            }
            boolean executionExceptionFlag = false;
            boolean storageUnavailableExceptionFlag = false;
            boolean concurrentOperationExceptionFlag = false;
            String executionExceptionMsg= "";
            String storageUnavailableExceptionMsg = "";
            String concurrentOperationExceptionMsg = "";
            UserVmVO started = null;
            if (isIso) {
                String isoPath = _storageMgr.getAbsoluteIsoPath(templateId, dataCenterId);
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, isoPath, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }
            } else {
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, null, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();

                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }

            }

            if (started == null) {
                List> disks = _storageMgr.isStoredOn(created);
                // NOTE: We now destroy a VM if the deploy process fails at any step. We now
                // have a lazy delete so there is still some time to figure out what's wrong.
                _vmMgr.destroyVirtualMachine(userId, created.getId());

                boolean retryCreate = true;
                for (Pair disk : disks) {
                    if (disk.second().isLocal()) {
                        avoids.put(disk.second().getId(), disk.second());
                    } else {
                        retryCreate = false;
                    }
                }

                if (retryCreate) {
                    continue;
                } else if(executionExceptionFlag){
                    throw new ExecutionException(executionExceptionMsg);
                } else if (storageUnavailableExceptionFlag){
                	throw new StorageUnavailableException(storageUnavailableExceptionMsg);
                }else if (concurrentOperationExceptionFlag){
                	throw new ConcurrentOperationException(concurrentOperationExceptionMsg);
                }
                else{
                    throw new InternalErrorException("Unable to start the VM " + created.getId() + "-" + created.getName());
                }
                
            } else {
                if (isIso) {
                    started.setIsoId(templateId);
                    _userVmDao.update(started.getId(), started);
                    started = _userVmDao.findById(started.getId());
                }

                try {
					_configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null);															
				} catch (InsufficientAddressCapacityException e) {
					s_logger.debug("Unable to assign public IP address pool: " +e.getMessage());					
				}
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM started: " + started.getId() + "-" + started.getName());
            }
            return started;
        }

        return null;
    }

    @Override
    public UserVm deployVirtualMachine(DeployVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException,
                                                               InternalErrorException, InsufficientStorageCapacityException, ExecutionException,
                                                               StorageUnavailableException, ConcurrentOperationException {
        Account ctxAccount = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        long dataCenterId = cmd.getZoneId();
        long serviceOfferingId = cmd.getServiceOfferingId();
        long templateId = cmd.getTemplateId();
        Long diskOfferingId = cmd.getDiskOfferingId();
        String domain = null; // FIXME:  this was hardcoded to null in DeployVMCmd in the old framework, do we need it?
        String password = generateRandomPassword();
        String displayName = cmd.getDisplayName();
        String group = cmd.getGroup();
        String userData = cmd.getUserData();
        String[] networkGroups = null;
        Long sizeObj = cmd.getSize();
        long size = (sizeObj == null) ? 0 : sizeObj;

        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {

                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }

        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for deploying a virtual machine.");
        }

        List netGrpList = cmd.getNetworkGroupList();
        if ((netGrpList != null) && !netGrpList.isEmpty()) {
            networkGroups = netGrpList.toArray(new String[netGrpList.size()]);
        }

    	AccountVO account = _accountDao.findById(accountId);
        if (account == null) {
            throw new InvalidParameterValueException("Unable to find account: " + accountId);
        }

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        if (dc == null) {
            throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
        }

        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        if (offering == null) {
            throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
        }

        VMTemplateVO template = _templateDao.findById(templateId);
        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        
        if (isIso && !template.isBootable()) {
        	throw new InvalidParameterValueException("Please specify a bootable ISO.");
        }

        // If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
        // Else, a disk offering is optional, and if present will be used to create the data disk
        DiskOfferingVO diskOffering = null;

        if (diskOfferingId != null) {
        	diskOffering = _diskOfferingDao.findById(diskOfferingId);
        }

        if (isIso && diskOffering == null) {
        	throw new InvalidParameterValueException("Please specify a valid disk offering ID.");
        }

        // validate that the template is usable by the account
        if (!template.isPublicTemplate()) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType()) && ((templateOwner == null) || (templateOwner.longValue() != accountId))) {
                // since the current account is not the owner of the template, check the launch permissions table to see if the
                // account can launch a VM from this template
                LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(templateId, account.getId());
                if (permission == null) {
                    throw new PermissionDeniedException("Account " + account.getAccountName() + " does not have permission to launch instances from template " + template.getName());
                }
            }
        }

        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	if (decodedUserData.length < 1) {
        		throw new InvalidParameterValueException("User data is too short");
        	}
			
        }
        if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized) {
        	_networkGroupMgr.createDefaultNetworkGroup(accountId);
    	}
        
        if (networkGroups != null) {
        	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
        		throw new InvalidParameterValueException("Network groups are not compatible with service offering " + offering.getName());
        	}
        	Set nameSet = new HashSet(); //handle duplicate names -- allowed
        	nameSet.addAll(Arrays.asList(networkGroups));
        	nameSet.add(NetworkGroupManager.DEFAULT_GROUP_NAME);
        	networkGroups = nameSet.toArray(new String[nameSet.size()]);
        	List networkGroupVOs = _networkSecurityGroupDao.findByAccountAndNames(accountId, networkGroups);
        	if (networkGroupVOs.size() != nameSet.size()) {
        		throw new InvalidParameterValueException("Some network group names do not exist");
        	}
        } else { //create a default group if necessary
        	if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized && _networkGroupsEnabled) {
        		networkGroups = new String[]{NetworkGroupManager.DEFAULT_GROUP_NAME};
        	}
        }

        // FIXME:  this really needs to be invoked when the job is scheduled by the framework, so commands need a callback for
        //         specifying event details that they are tracking...
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "deploying Vm");
            return deployVirtualMachineImpl(userId, accountId, dataCenterId, serviceOfferingId, templateId, diskOfferingId, domain, password, displayName, group, userData, networkGroups, eventId, size);
        } catch (ResourceAllocationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (ExecutionException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_HOST_LICENSE_EXPIRED", null, eventId);
            throw e;
        } catch (InvalidParameterValueException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INVALID_PARAM_ERROR", null, eventId);
            throw e;
        } catch (InternalErrorException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch (InsufficientStorageCapacityException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (PermissionDeniedException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: ACCOUNT_ERROR", null, eventId);
            throw e;
        } catch (ConcurrentOperationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch(Exception e) {
        List validateSGList = null;
            s_logger.warn("Unable to deploy VM : " + e.getMessage(), e);
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw new CloudRuntimeException("Unable to deploy VM : " + e.getMessage());
        }
    }

    @Override
    public DomainRouterVO findDomainRouterBy(long accountId, long dataCenterId) {
        return _routerDao.findBy(accountId, dataCenterId);
    }

    @Override
    public DomainRouterVO findDomainRouterById(long domainRouterId) {
        return _routerDao.findById(domainRouterId);
    }

    @Override
    public List listDataCenters(ListZonesByCmd cmd) {
        List dcs = _dcDao.listAll();

        Account account = (Account)UserContext.current().getAccountObject();
        Boolean available = cmd.isAvailable();
        if (account != null) {
            if ((available != null) && Boolean.FALSE.equals(available)) {
                List routers = _routerDao.listBy(account.getId());
                for (Iterator iter = dcs.iterator(); iter.hasNext();) {
                    DataCenterVO dc = iter.next();
                    boolean found = false;
                    for (DomainRouterVO router : routers) {
                        if (dc.getId() == router.getDataCenterId()) {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        iter.remove();
                }
            }
        }

    @Override
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }

    @Override
    public long getId() {
        return MacAddress.getMacAddress().toLong();
    }

    protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {

        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("publicPort is an invalid value");
        }
        if (!NetUtils.isValidPort(privatePort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");
        }

//        s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
//        if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//            throw new InvalidParameterValueException("Invalid private ip address");
//        }
        if (!NetUtils.isValidProto(proto)) {
            throw new InvalidParameterValueException("Invalid protocol");
        }
    }

    @Override
    @DB
    public void assignSecurityGroup(AssignPortForwardingServiceCmd cmd) throws PermissionDeniedException,
            NetworkRuleConflictException, InvalidParameterValueException, InternalErrorException {
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	Long securityGroupId = cmd.getId();
    	List sgIdList = cmd.getIds();
    	String publicIp = cmd.getPublicIp();
    	Long vmId = cmd.getVirtualMachineId();
    	
    	//Verify input parameters
        if ((securityGroupId == null) && (sgIdList == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }


        if (userId == null) {
            userId = Long.valueOf(1);
        }

        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = findAccountById(validatedAccountId);
                if (!isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }
    	
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            s_logger.warn("Unable to find virtual machine with id " + vmId);
            throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
        }
        long startEventId = EventUtils.saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "applying port forwarding service for Vm with Id: "+vmId);
    	
        boolean locked = false;
        Transaction txn = Transaction.currentTxn();
        try {
            EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "Applying port forwarding service for Vm with Id: "+vmId, startEventId);
            State vmState = userVm.getState();
            switch (vmState) {
            case Destroyed:
            case Error:
            case Expunging:
            case Unknown:
                throw new InvalidParameterValueException("Unable to assign port forwarding service(s) '"
                        + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "' to virtual machine " + vmId
                        + " due to virtual machine being in an invalid state for assigning a port forwarding service (" + vmState + ")");
            }

            // sanity check that the vm can be applied to the load balancer
            ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
            if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                }

                throw new InvalidParameterValueException("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }
            
            DomainRouterVO router = null;
            if (userVm.getDomainRouterId() != null)
            	router = _routerDao.findById(userVm.getDomainRouterId());
            if (router == null) {
                s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine " + userVm.toString());
                throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + vmId);
            }

            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;

            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User does not own supplied address");
            }

                }
            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new InvalidParameterValueException("Invalid IP address " + publicIp + " for applying port forwarding services, the IP address is not in a 'virtual network' vlan.");
            }

            txn.start();

            if (securityGroupId == null) {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on list passed in
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                {
                    // Save and create the event
                    String description;
                    String type = EventTypes.EVENT_NET_RULE_DELETE;
                    String level = EventVO.LEVEL_INFO;

                    for (FirewallRuleVO fwRule : fwRulesToRemove) {
                        fwRule.setEnabled(false); // disable rule for sending to the agent
                        _firewallRulesDao.remove(fwRule.getId()); // remove the rule from the database

                        description = "deleted ip forwarding rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                                + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                        EventUtils.saveEvent(userId, userVm.getAccountId(), level, type, description);
                    }
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);
                if ((updatedRules != null) && (updatedRules.size() != fwRulesToRemove.size())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to clean up all port forwarding service rules for public IP " + publicIp + " and guest vm " + userVm.getName()
    @Override
                                + " while applying port forwarding service(s) '" + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "'"
                                + " -- intended to remove " + fwRulesToRemove.size() + " rules, removd " + ((updatedRules == null) ? "null" : updatedRules.size()) + " rules.");
                    }
                }

                List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    boolean success = _securityGroupVMMapDao.remove(sgVmMapping.getId());

                    SecurityGroupVO securityGroup = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());

                    // save off an event for removing the security group
                    EventVO event = new EventVO();
                    event.setUserId(userId);
                    event.setAccountId(userVm.getAccountId());
                    event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
                    String sgRemoveLevel = EventVO.LEVEL_INFO;
                    String sgRemoveDesc = "Successfully removed ";
                    if (!success) {
                        sgRemoveLevel = EventVO.LEVEL_ERROR;
                        sgRemoveDesc = "Failed to remove ";
                    }
                    String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
                    event.setParameters(params);
                    event.setDescription(sgRemoveDesc + "port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
                    event.setLevel(sgRemoveLevel);
                    _eventDao.persist(event);
                }
            } else {
                List existingVMMaps = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId.longValue());
                if ((existingVMMaps != null) && !existingVMMaps.isEmpty()) {
                    for (SecurityGroupVMMapVO existingVMMap : existingVMMaps) {
                        if (existingVMMap.getInstanceId() == userVm.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("port forwarding service " + securityGroupId + " is already applied to virtual machine " + userVm.toString() + ", skipping assignment.");
                            }
                            return;
                        }
                    }
            List finalSecurityGroupIdList = new ArrayList();
            if (securityGroupId != null) {
                finalSecurityGroupIdList.add(securityGroupId);
            } else {
                finalSecurityGroupIdList.addAll(sgIdList);
            }

            for (Long sgId : finalSecurityGroupIdList) {
                if (sgId.longValue() == 0) {
                    // group id of 0 means to remove all groups, which we just did above
                    break;
                }

                SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(sgId));
                if (securityGroup == null) {
                    s_logger.warn("Unable to find port forwarding service with id " + sgId);
                    throw new InvalidParameterValueException("Unable to find port forwarding service with id " + sgId);
                }

                if (!_domainDao.isChildDomain(securityGroup.getDomainId(), userVm.getDomainId())) {
                    s_logger.warn("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                    throw new InvalidParameterValueException("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(publicIp);
                Map> mappedPublicPorts = new HashMap>();

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
                    }
                }

                List loadBalancers = _loadBalancerDao.listByIpAddress(publicIp);
                if (loadBalancers != null) {
                    for (LoadBalancerVO loadBalancer : loadBalancers) {
                        // load balancers don't have to be applied to an
                        // instance for there to be a conflict on the load
                        // balancers ip/port, so just
                        // map the public port to a pair of empty strings
                        mappedPublicPorts.put(loadBalancer.getPublicPort(), new Pair("", ""));
                    }
                }

                List firewallRulesToApply = new ArrayList();
                List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgId);
                for (NetworkRuleConfigVO netRule : netRules) {
                    Pair privateIpPort = mappedPublicPorts.get(netRule.getPublicPort());
                    if (privateIpPort != null) {
                        if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(netRule.getPrivatePort())) {
                            continue; // already mapped
                        } else {
                            throw new NetworkRuleConflictException("An existing service rule for " + publicIp + ":" + netRule.getPublicPort()
                                    + " already exists, found while trying to apply service rule " + netRule.getId() + " from port forwarding service " + securityGroup.getName() + ".");
                        }
                    }

                    FirewallRuleVO newFwRule = new FirewallRuleVO();
                    newFwRule.setEnabled(true);
                    newFwRule.setForwarding(true);
                    newFwRule.setPrivatePort(netRule.getPrivatePort());
                    newFwRule.setProtocol(netRule.getProtocol());
                    newFwRule.setPublicPort(netRule.getPublicPort());
                    newFwRule.setPublicIpAddress(publicIp);
                    newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                    newFwRule.setGroupId(netRule.getSecurityGroupId());

                    firewallRulesToApply.add(newFwRule);
                    _firewallRulesDao.persist(newFwRule);

                    String description = "created new ip forwarding rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                            + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
                }

                // now that individual rules have been created from the security group, save the security group mapping for this ip/vm instance
                SecurityGroupVMMapVO sgVmMap = new SecurityGroupVMMapVO(sgId, publicIp, vmId);
                _securityGroupVMMapDao.persist(sgVmMap);

                // Save off information for the event that the security group was applied
                EventVO event = new EventVO();
                event.setUserId(userId);
                event.setAccountId(userVm.getAccountId());
                event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY);
                event.setStartId(startEventId);
                event.setDescription("Successfully applied port forwarding service " + securityGroup.getName() + " to virtual machine " + userVm.getName());
                String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId+"\nnumRules="+firewallRulesToApply.size()+"\ndcId="+userVm.getDataCenterId();
                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
                _eventDao.persist(event);

                _networkMgr.updateFirewallRules(publicIp, firewallRulesToApply, router);
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
    @DB
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public void removeSecurityGroup(RemovePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	
    	Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long securityGroupId = cmd.getId();
        String publicIp = cmd.getPublicIp();
        Long vmId = cmd.getVirtualMachineId();
        
        //verify input parameters
        SecurityGroupVO securityG = _securityGroupDao.findById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
            }
        }
        
        UserVmVO vmInstance = findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
            txn.start();

                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing port forwarding services for Vm with Id: "+vmId);

        /*TODO : ASK KRIS AS TO WHAT DO WE DO WITH THIS PART IN THE EXECUTOR CODE
        UserVmVO userVm = userVmDao.findById(param.getInstanceId());
        if(userVm == null)
        	return null;
        
        if (userVm.getDomainRouterId() == null) {
        	return null;
        } else
        	return routerDao.findById(userVm.getDomainRouterId());
	    */
        removeSecurityGroup(userId, securityGroupId, publicIp, vmId, eventId);
    }
    
    @Override
    public void removeSecurityGroup(long userId, long securityGroupId, String publicIp, long vmId, long startEventId) throws InvalidParameterValueException, PermissionDeniedException {
        // This gets complicated with overlapping rules. As an example:
        // security group 1 has the following port mappings: 22->22 on TCP,
        // 23->23 on TCP, 80->8080 on TCP
        // security group 2 has the following port mappings: 22->22 on TCP,
        // 7891->7891 on TCP
        // User assigns group 1 & 2 on 192.168.10.120 to vm 1
        // Later, user removed group 1 from 192.168.10.120 and vm 1
        // Final valid port mappings should be 22->22 and 7891->7891 which both
        // come from security group 2. The mapping
        // for port 22 should not be removed.
        boolean locked = false;
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Unable to find vm: " + vmId);
        }
        EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "Removing port forwarding services for Vm with Id: "+vmId, startEventId);
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
            throw new InvalidParameterValueException("Unable to find port forwarding service: " + securityGroupId);
        }

        DomainRouterVO router = null;
        if (userVm.getDomainRouterId() != null)
        	router = _routerDao.findById(userVm.getDomainRouterId());
        if (router == null) {
            throw new InvalidParameterValueException("Unable to find router for ip address: " + publicIp);
        }

        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe
                // for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }

            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User/account does not own supplied address");
            }

            // get the account for writing events
            Account account = _accountDao.findById(userVm.getAccountId());
            {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on existing SG mappings
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                for (FirewallRuleVO fwRule : fwRulesToRemove) {
                    fwRule.setEnabled(false);
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "ip forwarding";
                String level = EventVO.LEVEL_INFO;

                for (FirewallRuleVO fwRule : updatedRules) {
                    _firewallRulesDao.remove(fwRule.getId());

                    description = "deleted " + ruleName + " rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                            + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), level, type, description);
                }
            }

            // since we know these groups all pass muster, just keep track
            // of the public ports we are mapping on this public IP and
            // don't duplicate
            List alreadyMappedPorts = new ArrayList();
            List fwRulesToAdd = new ArrayList();
            List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                if (sgVmMapping.getSecurityGroupId() == securityGroupId) {
                    _securityGroupVMMapDao.remove(sgVmMapping.getId());
                } else {
                    List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgVmMapping.getSecurityGroupId());
                    for (NetworkRuleConfigVO netRule : netRules) {
                        if (!alreadyMappedPorts.contains(netRule.getPublicPort())) {
                            FirewallRuleVO newFwRule = new FirewallRuleVO();
                            newFwRule.setEnabled(true);
                            newFwRule.setForwarding(true);
                            newFwRule.setPrivatePort(netRule.getPrivatePort());
                            newFwRule.setProtocol(netRule.getProtocol());
                            newFwRule.setPublicPort(netRule.getPublicPort());
                            newFwRule.setPublicIpAddress(publicIp);
                            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                            newFwRule.setGroupId(netRule.getSecurityGroupId());

                            fwRulesToAdd.add(newFwRule);

                            alreadyMappedPorts.add(netRule.getPublicPort());
                        }
                    }
                }
            }

            for (FirewallRuleVO addedRule : fwRulesToAdd) {
                _firewallRulesDao.persist(addedRule);

                String description = "created new ip forwarding rule [" + addedRule.getPublicIpAddress() + ":" + addedRule.getPublicPort() + "]->["
                        + addedRule.getPrivateIpAddress() + ":" + addedRule.getPrivatePort() + "]" + " " + addedRule.getProtocol();

                EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
            }

            // save off an event for removing the security group
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(userVm.getAccountId());
            event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
            event.setDescription("Successfully removed port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
            event.setLevel(EventVO.LEVEL_INFO);
            String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
            event.setParameters(params);
            _eventDao.persist(event);

            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
            } else {
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "

                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }
        if (domainId != null) {
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object accountName = cmd.getAccountName();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            }
        } else if (domainId != null) {
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object name = cmd.getServiceOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object name = cmd.getClusterName();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (state != null) {
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _hostPodDao.search(sc, searchFilter);
    }

    @Override
    public List searchForZones(Criteria c) {
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        if (accountName != null && domainId != null) {
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
        if (isPublic != null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

        return _vlanDao.search(sc, searchFilter);
    }
    
    @Override
    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);


    @Override
        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        }
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding

            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        } else {
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
        return _launchPermissionDao.listPermittedTemplates(accountId);
    }

    @Override
    public List listPods(long dataCenterId) {
        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

                    }
        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {
        return _vmInstanceDao.findById(vmId);
    }

    @Override
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    @Override
    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();

    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }
        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                }
            } else {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

                }
        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {

    @Override
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	else
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
        	{
    }
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        }
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system

    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
    @Override
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
            }
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
        return _securityGroupDao.persist(group);
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?

            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
        return _asyncMgr.getAsyncJob(jobId);
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
		
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
                if (ipAddrAcctId == null) {
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
    @Override
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
    }
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
        Calendar calMax = Calendar.getInstance();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
    	}
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
        calMin.add(Calendar.SECOND, -entryTime);
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.async.executor.SecurityGroupParam;
import com.cloud.async.executor.VMOperationParam;
import com.cloud.async.executor.VMOperationParam.VmOp;
<<<<<<< HEAD
=======
import com.cloud.async.executor.VolumeOperationParam;
import com.cloud.async.executor.VolumeOperationParam.VolumeOp;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
Solution content
 * 
/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */
package com.cloud.server;

import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.alert.AlertVO;
import com.cloud.alert.dao.AlertDao;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AssignPortForwardingServiceCmd;
import com.cloud.api.commands.CreateDomainCmd;
import com.cloud.api.commands.CreatePortForwardingServiceCmd;
import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd;
import com.cloud.api.commands.CreateUserCmd;
import com.cloud.api.commands.DeleteDomainCmd;
import com.cloud.api.commands.DeletePortForwardingServiceCmd;
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeleteUserCmd;
import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.EnableAccountCmd;
import com.cloud.api.commands.EnableUserCmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapabilitiesCmd;
import com.cloud.api.commands.ListCapacityCmd;
import com.cloud.api.commands.ListCfgsByCmd;
import com.cloud.api.commands.ListClustersCmd;
import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListIsosCmd;
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPortForwardingServiceRulesCmd;
import com.cloud.api.commands.ListPortForwardingServicesByVmCmd;
import com.cloud.api.commands.ListPortForwardingServicesCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListStoragePoolsAndHostsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMGroupsCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.LockAccountCmd;
import com.cloud.api.commands.LockUserCmd;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.RemovePortForwardingServiceCmd;
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateAccountCmd;
import com.cloud.api.commands.UpdateDomainCmd;
import com.cloud.api.commands.UpdateIPForwardingRuleCmd;
import com.cloud.api.commands.UpdateIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplatePermissionsCmd;
import com.cloud.api.commands.UpdateUserCmd;
import com.cloud.api.commands.UpdateVMGroupCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
<<<<<<< HEAD
=======
import com.cloud.storage.Storage.FileSystem;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
Solution content
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
<<<<<<< HEAD
import com.cloud.storage.VMTemplateVO;
=======
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
Solution content
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
File
ManagementServerImpl.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
<<<<<<< HEAD
=======
import com.cloud.storage.dao.VMTemplateHostDao;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
Solution content
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
<<<<<<< HEAD
=======
import com.cloud.storage.snapshot.SnapshotScheduler;
import com.cloud.storage.upload.UploadMonitor;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
Solution content
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
File
ManagementServerImpl.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
    private final int _proxyRamSize;
    private final int _ssRamSize;

<<<<<<< HEAD
=======
    private final long _maxVolumeSizeInGb;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    private final Map _availableIdsMap;

	private boolean _networkGroupsEnabled = false;
Solution content
    private final int _proxyRamSize;
    private final int _ssRamSize;

    private final Map _availableIdsMap;

	private boolean _networkGroupsEnabled = false;
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Attribute
Chunk
Conflicting content
        // Parse the max number of UserVMs and public IPs from server-setup.xml,
        // and set them in the right places
<<<<<<< HEAD
        
=======

        String maxVolumeSizeInTbString = _configs.get("max.volume.size.gb");
        long maxVolumeSizeGBytes = NumbersUtil.parseLong(maxVolumeSizeInTbString, new Long("2000"));

        _maxVolumeSizeInGb = maxVolumeSizeGBytes;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
        _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
        _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);
Solution content
        // Parse the max number of UserVMs and public IPs from server-setup.xml,
        // and set them in the right places
        _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
        _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
        _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Attribute
Method invocation
Variable
Chunk
Conflicting content
    }
    
    /*
        event.setState(EventState.Scheduled);
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user by id");
        }

<<<<<<< HEAD
        if((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null))
        {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide an api key/secret key pair");
        }
        
        // If the account is an admin type, return an error.  We do not allow this
        Account account = (Account)UserContext.current().getAccountObject();
        
        if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is system account, update is not allowed");
        }

        if (firstName == null) { 
        	firstName = user.getFirstname();
        }
        if (lastName == null) { 
        	lastName = user.getLastname(); 
        }
        if (userName == null) { 
        	userName = user.getUsername();  
        }
        if (password == null) { 
        	password = user.getPassword();
        }
        if (email == null) {
        	email = user.getEmail();
        }
        if (timeZone == null) {
        	timeZone = user.getTimezone();
        }
        if (apiKey == null) {
        	apiKey = user.getApiKey();
        }
        if (secretKey == null) {
        	secretKey = user.getSecretKey();
        }
=======
    private Long saveEvent(Long userId, Long accountId, String type, String description) {
        EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(accountId);
        event.setType(type);
        event.setDescription(description);
        event = _eventDao.persist(event);
        return event.getId();
    }
    
    /*
     * Save event after scheduling an async job
     */
    private Long saveScheduledEvent(Long userId, Long accountId, String type, String description) {
        EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(accountId);
        event.setType(type);
        event.setDescription("Scheduled async job for "+description);
        event = _eventDao.persist(event);
        return event.getId();
     * Save event after starting execution of an async job
     */
    @Override
    public Long saveStartedEvent(Long userId, Long accountId, String type, String description, long startEventId) {
        EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(accountId);
        event.setType(type);
        event.setState(EventState.Started);
        event.setDescription(description);
        event.setStartId(startEventId);
        event = _eventDao.persist(event);
    	return event.getId();
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        Long accountId = user.getAccountId();
Solution content
        }

            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user by id");
        }

        if((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide an api key/secret key pair");
        }
        
        // If the account is an admin type, return an error.  We do not allow this
        Account account = (Account)UserContext.current().getAccountObject();
        
        if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is system account, update is not allowed");
        }

        if (firstName == null) { 
        	firstName = user.getFirstname();
        }
        if (lastName == null) { 
        	lastName = user.getLastname(); 
        }
        if (userName == null) { 
        	userName = user.getUsername();  
        }
        if (password == null) { 
        	password = user.getPassword();
        }
        if (email == null) {
        	email = user.getEmail();
        }
        if (timeZone == null) {
        	timeZone = user.getTimezone();
        }
        if (apiKey == null) {
        	apiKey = user.getApiKey();
        }
        if (secretKey == null) {
        	secretKey = user.getSecretKey();
        Long accountId = user.getAccountId();
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Variable
Chunk
Conflicting content
        return null;
    }

<<<<<<< HEAD
    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }
=======
    @DB
    public void associateIpAddressListToAccount(long userId, long accountId, long zoneId, Long vlanId) throws InsufficientAddressCapacityException,
    		InvalidParameterValueException, InternalErrorException {
    	
        Transaction txn = Transaction.currentTxn();
        AccountVO account = null;
        
        try {
            //Acquire Lock                    
            account = _accountDao.acquire(accountId);
            if (account == null) {
                s_logger.warn("Unable to lock account: " + accountId);
                throw new InternalErrorException("Unable to acquire account lock");
            }            
            s_logger.debug("Associate IP address lock acquired");
            
            //Get Router
            DomainRouterVO router = _routerDao.findBy(accountId, zoneId);
            if (router == null) {
                s_logger.debug("No router found for account: " + account.getAccountName() + ".");
                return;
            }
            
            if (router.getState() == State.Running) {
	            //Get Vlans associated with the account
            	List vlansForAccount = new ArrayList();
            	if (vlanId == null){
            		vlansForAccount.addAll(_vlanDao.listVlansForAccountByType(zoneId, account.getId(), VlanType.VirtualNetwork));
            		s_logger.debug("vlansForAccount "+ vlansForAccount);
            	}else{
            		vlansForAccount.add(_vlanDao.findById(vlanId));
            	}
		         
	            // Creating a list of all the ips that can be assigned to this account
		        txn.start();
		        List ipAddrsList = new ArrayList();
		     	for (VlanVO vlan : vlansForAccount){
		     		ipAddrsList.addAll(_publicIpAddressDao.assignAcccountSpecificIps(accountId, account.getDomainId(), vlan.getId(), false));
		     				     		
		     		long size = ipAddrsList.size();
		     		_accountMgr.incrementResourceCount(accountId, ResourceType.public_ip, size);
		     		s_logger.debug("Assigning new ip addresses " +ipAddrsList);		     		
		     	}
		     	if(ipAddrsList.isEmpty())
		     		return;
		     	
		     	// Associate the IP's to DomR
		     	boolean success = true;
		     	String params = "\nsourceNat=" + false + "\ndcId=" + zoneId;
		     	ArrayList dummyipAddrList = new ArrayList();
		     	success = _networkMgr.associateIP(router,ipAddrsList, true, 0);
		     	String errorMsg = "Unable to assign public IP address pool";
            	if (!success) {
            		s_logger.debug(errorMsg);
            		 for(String ip : ipAddrsList){
            			 saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_NET_IP_ASSIGN, "Unable to assign public IP " +ip, params);
                     }
            		throw new InternalErrorException(errorMsg);
            	}
                txn.commit();
                for(String ip : ipAddrsList){
                	saveEvent(userId, accountId, EventVO.LEVEL_INFO, EventTypes.EVENT_NET_IP_ASSIGN, "Successfully assigned account IP " +ip, params);
                }
            }
            } catch (InternalErrorException iee) {
                s_logger.error("Associate IP threw an InternalErrorException.", iee);
                throw iee;
            } catch (Throwable t) {
                s_logger.error("Associate IP address threw an exception.", t);
                throw new InternalErrorException("Associate IP address exception");
            } finally {
                if (account != null) {
                    _accountDao.release(accountId);
                    s_logger.debug("Associate IP address lock released");
                }
            }
    
    }
    
    @Override
    @DB
    public String associateIpAddress(long userId, long accountId, long domainId, long zoneId, long vmId) throws ResourceAllocationException, InsufficientAddressCapacityException,
            InvalidParameterValueException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        AccountVO account = null;
        try {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Associate IP address called for user " + userId + " account " + accountId);
            }
            account = _accountDao.acquire(accountId);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

    @Override
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
Solution content
        return null;
    }

    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }

    @Override
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
If statement
Method declaration
Method invocation
Method signature
Try statement
Variable
Chunk
Conflicting content
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

<<<<<<< HEAD
=======
            // Check that the maximum number of public IPs for the given
            // accountId will not be exceeded
            if (_accountMgr.resourceLimitExceeded(account, ResourceType.public_ip)) {
                ResourceAllocationException rae = new ResourceAllocationException("Maximum number of public IP addresses for account: " + account.getAccountName()
                        + " has been exceeded.");
                rae.setResourceType("ip");
                throw rae;
            }

            DomainRouterVO router = _routerDao.findBy(accountId, zoneId);
            if (router == null) {
                throw new InvalidParameterValueException("No router found for account: " + account.getAccountName() + ".");
            }

            txn.start();

            String ipAddress = null;
            Pair ipAndVlan = _vlanDao.assignIpAddress(zoneId, accountId, domainId, VlanType.VirtualNetwork, false);
            
            if (ipAndVlan == null) {
                throw new InsufficientAddressCapacityException("Unable to find available public IP addresses");
            } else {
            	ipAddress = ipAndVlan.first();
            	_accountMgr.incrementResourceCount(accountId, ResourceType.public_ip);
            }

            if(vmId!=0){
            	VMInstanceVO vm = _vmInstanceDao.findById(vmId);
            	
            	if(vm == null){
            		throw new InvalidParameterValueException("Invalid vm instance id:"+vmId+" specified");
            	}
            }
            
            boolean success = true;
            String errorMsg = "";

            List ipAddrs = new ArrayList();
            ipAddrs.add(ipAddress);

            if (router.getState() == State.Running) {
                success = _networkMgr.associateIP(router, ipAddrs, true, vmId);
                if (!success) {
                    errorMsg = "Unable to assign public IP address.";
                }
            }

            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(accountId);
            event.setType(EventTypes.EVENT_NET_IP_ASSIGN);
            event.setParameters("address=" + ipAddress + "\nsourceNat=" + false + "\ndcId=" + zoneId);

            if (!success) {
                _publicIpAddressDao.unassignIpAddress(ipAddress);
                ipAddress = null;
                _accountMgr.decrementResourceCount(accountId, ResourceType.public_ip);

                event.setLevel(EventVO.LEVEL_ERROR);
                event.setDescription(errorMsg);
                _eventDao.persist(event);
                txn.commit();

                throw new InternalErrorException(errorMsg);
            } else {
                event.setDescription("Assigned a public IP address: " + ipAddress);
                _eventDao.persist(event);
            }

            txn.commit();
            return ipAddress;

        } catch (ResourceAllocationException rae) {
            s_logger.error("Associate IP threw a ResourceAllocationException.", rae);
            throw rae;
        } catch (InsufficientAddressCapacityException iace) {
            s_logger.error("Associate IP threw an InsufficientAddressCapacityException.", iace);
            throw iace;
        } catch (InvalidParameterValueException ipve) {
            s_logger.error("Associate IP threw an InvalidParameterValueException.", ipve);
            throw ipve;
        } catch (InternalErrorException iee) {
            s_logger.error("Associate IP threw an InternalErrorException.", iee);
            throw iee;
        } catch (Throwable t) {
            s_logger.error("Associate IP address threw an exception.", t);
            throw new InternalErrorException("Associate IP address exception");
        } finally {
            if (account != null) {
                _accountDao.release(accountId);
                s_logger.debug("Associate IP address lock released");
            }
        }
    }

    @Override
    public long associateIpAddressAsync(long userId, long accountId, long domainId, long zoneId) {
        AssociateIpAddressParam param = new AssociateIpAddressParam(userId, accountId, domainId, zoneId);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
        job.setUserId(UserContext.current().getUserId());
        job.setAccountId(accountId);
        job.setCmd("AssociateIpAddress");
        job.setCmdInfo(gson.toJson(param));
        job.setCmdOriginator(AssociateIPAddrCmd.getResultObjectName());
        
        return _asyncMgr.submitAsyncJob(job, true);
    }

    @Override
    @DB
    public boolean disassociateIpAddress(long userId, long accountId, String publicIPAddress) throws PermissionDeniedException, IllegalArgumentException {
        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.findById(publicIPAddress);
            if (ipVO == null) {
                return false;
            }

            if (ipVO.getAllocated() == null) {
                return true;
            }

            AccountVO accountVO = _accountDao.findById(accountId);
            if (accountVO == null) {
                return false;
            }
          
            if ((ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != accountId)) {
                // FIXME: is the user visible in the admin account's domain????
                if (!BaseCmd.isAdmin(accountVO.getType())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("permission denied disassociating IP address " + publicIPAddress + "; acct: " + accountId + "; ip (acct / dc / dom / alloc): "
		}
        param.setName(name);
                                + ipVO.getAccountId() + " / " + ipVO.getDataCenterId() + " / " + ipVO.getDomainId() + " / " + ipVO.getAllocated());
                    }
                    throw new PermissionDeniedException("User/account does not own supplied address");
                }
            }

            if (ipVO.getAllocated() == null) {
                return true;
            }

            if (ipVO.isSourceNat()) {
                throw new IllegalArgumentException("ip address is used for source nat purposes and can not be disassociated.");
            }
            
            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!vlan.getVlanType().equals(VlanType.VirtualNetwork)) {
            	throw new IllegalArgumentException("only ip addresses that belong to a virtual network may be disassociated.");
            }
			
			//Check for account wide pool. It will have an entry for account_vlan_map. 
            if (_accountVlanMapDao.findAccountVlanMap(accountId,ipVO.getVlanDbId()) != null){
            	throw new PermissionDeniedException(publicIPAddress + " belongs to Account wide IP pool and cannot be disassociated");
            }
			
            txn.start();
            boolean success = _networkMgr.releasePublicIpAddress(userId, publicIPAddress);
            if (success)
            	_accountMgr.decrementResourceCount(accountId, ResourceType.public_ip);
            txn.commit();
            return success;

        } catch (PermissionDeniedException pde) {
            throw pde;
        } catch (IllegalArgumentException iae) {
            throw iae;
        } catch (Throwable t) {
            s_logger.error("Disassociate IP address threw an exception.");
            throw new IllegalArgumentException("Disassociate IP address threw an exception");
        }
    }

    @Override
    public long disassociateIpAddressAsync(long userId, long accountId, String ipAddress) {
        DisassociateIpAddressParam param = new DisassociateIpAddressParam(userId, accountId, ipAddress);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
        job.setUserId(UserContext.current().getUserId());
        job.setAccountId(accountId);
        job.setCmd("DisassociateIpAddress");
        job.setCmdInfo(gson.toJson(param));
        
        return _asyncMgr.submitAsyncJob(job, true);
    }

    @DB
    @Override
    public VlanVO createVlanAndPublicIpRange(long userId, VlanType vlanType, Long zoneId, Long accountId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) throws Exception{
    	          
		if(accountId != null && vlanType == VlanType.VirtualNetwork){
			long ipResourceLimit = _accountMgr.findCorrectResourceLimit( _accountDao.findById(accountId), ResourceType.public_ip);
			long accountIpRange  = NetUtils.ip2Long(endIP) - NetUtils.ip2Long(startIP) + 1 ;
			s_logger.debug(" IPResourceLimit " +ipResourceLimit + " accountIpRange " + accountIpRange);
			if (ipResourceLimit != -1 && accountIpRange > ipResourceLimit){ // -1 means infinite
				throw new InvalidParameterValueException(" Public IP Resource Limit is set to " + ipResourceLimit + " which is less than the IP range of " + accountIpRange + " provided");
			}
			String params = "\nsourceNat=" + false + "\ndcId=" + zoneId;
			Transaction txn = Transaction.currentTxn();
			try{
				txn.start();
				VlanVO vlan = _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
				associateIpAddressListToAccount(userId, accountId, zoneId, vlan.getId());
				txn.commit();
				return vlan;
			}catch(Exception e){
				txn.rollback();
		    	long startIPLong = NetUtils.ip2Long(startIP);
		    	long endIPLong = NetUtils.ip2Long(endIP);		    	
		        while (startIPLong <= endIPLong) {
		        	saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_NET_IP_ASSIGN, "Unable to assign public IP " +NetUtils.long2Ip(startIPLong), params);
		        	startIPLong += 1;
		        }
				throw new Exception(e.getMessage());
			}
		return _configMgr.createVlanAndPublicIpRange(userId, vlanType, zoneId, accountId, podId, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
    }

    @Override
    public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId) throws InvalidParameterValueException {
        return _configMgr.deleteVlanAndPublicIpRange(userId, vlanDbId);
    }

    @Override
    public VolumeVO createVolume(long userId, long accountId, String name, long zoneId, long diskOfferingId, long startEventId, long size) throws InternalErrorException {
        saveStartedEvent(userId, accountId, EventTypes.EVENT_VOLUME_CREATE, "Creating volume", startEventId);
        DataCenterVO zone = _dcDao.findById(zoneId);
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        VolumeVO createdVolume = _storageMgr.createVolume(accountId, userId, name, zone, diskOffering, startEventId,size);

        if (createdVolume != null)
            return createdVolume;
        else
            throw new InternalErrorException("Failed to create volume.");
    }

    @Override
    public long createVolumeAsync(long userId, long accountId, String name, long zoneId, long diskOfferingId, long size) throws InvalidParameterValueException, InternalErrorException, ResourceAllocationException {
        // Check that the account is valid
    	AccountVO account = _accountDao.findById(accountId);
    	if (account == null) {
    		throw new InvalidParameterValueException("Please specify a valid account.");
    	}
    	
    	// Check that the zone is valid
        DataCenterVO zone = _dcDao.findById(zoneId);
        if (zone == null) {
            throw new InvalidParameterValueException("Please specify a valid zone.");
        }
        
        // Check that the the disk offering is specified
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        if ((diskOffering == null) || !DiskOfferingVO.Type.Disk.equals(diskOffering.getType())) {
            throw new InvalidParameterValueException("Please specify a valid disk offering.");
        }
            
        // Check that there is a shared primary storage pool in the specified zone
        List storagePools = _poolDao.listByDataCenterId(zoneId);
        
        boolean sharedPoolExists = false;
        boolean readyPoolExists = false;
        for (StoragePoolVO storagePool : storagePools) {
        	if (storagePool.isShared()) {
        		sharedPoolExists = true;
        	}
            //check if there are any pools in the UP state
            //if not, throw an error
        	if(storagePool.getStatus().equals(Status.Up)){
        		readyPoolExists = true;
        	}
        }
        
        if(!readyPoolExists){
        	throw new InternalErrorException("There are no ready pools for volume creation");
        }
        
        // Check that there is at least one host in the specified zone
        List hosts = _hostDao.listByDataCenter(zoneId);
        if (hosts.isEmpty()) {
        	throw new InvalidParameterValueException("Please add a host in the specified zone before creating a new volume.");
        }
        
        if (!sharedPoolExists) {
        	throw new InvalidParameterValueException("Please specify a zone that has at least one shared primary storage pool.");
        }
        
        // Check that the resource limit for volumes won't be exceeded
        if (_accountMgr.resourceLimitExceeded(account, ResourceType.volume)) {
        	ResourceAllocationException rae = new ResourceAllocationException("Maximum number of volumes for account: " + account.getAccountName() + " has been exceeded.");
        	rae.setResourceType("volume");
        	throw rae;
        }

        long eventId = saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_CREATE, "creating volume");
        
        VolumeOperationParam param = new VolumeOperationParam();
        param.setOp(VolumeOp.Create);
        param.setAccountId(accountId);
        param.setUserId(UserContext.current().getUserId());
        param.setZoneId(zoneId);
        param.setDiskOfferingId(diskOfferingId);
        param.setEventId(eventId);
        param.setSize(size);
        
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
        job.setUserId(UserContext.current().getUserId());
        job.setAccountId(accountId);
        job.setCmd("VolumeOperation");
        job.setCmdInfo(gson.toJson(param));
        job.setCmdOriginator(CreateVolumeCmd.getResultObjectName());
        
        return _asyncMgr.submitAsyncJob(job);
    }

    @Override
    public long createVolumeFromSnapshotAsync(long userId, long accountId, long snapshotId, String volumeName) throws InternalErrorException, ResourceAllocationException {
        SnapshotVO snapshot = _snapshotDao.findById(snapshotId);
        AccountVO account = _accountDao.findById(snapshot.getAccountId());
        
        // Check that the resource limit for volumes won't be exceeded
        if (_accountMgr.resourceLimitExceeded(account, ResourceType.volume)) {
            ResourceAllocationException rae = new ResourceAllocationException("Maximum number of volumes for account: " + account.getAccountName() + " has been exceeded.");
            rae.setResourceType("volume");
            throw rae;
        }
        
        return _snapMgr.createVolumeFromSnapshotAsync(userId, accountId, snapshotId, volumeName);
    }

    

    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }
    
    @Override
    public void destroyVolume(long volumeId) throws InvalidParameterValueException {
        // Check that the volume is valid
        VolumeVO volume = _volumeDao.findById(volumeId);
        if (volume == null) {
            throw new InvalidParameterValueException("Please specify a valid volume ID.");
        }

        // Check that the volume is stored on shared storage
        if (!_storageMgr.volumeOnSharedStoragePool(volume)) {
            throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
        }

        // Check that the volume is not currently attached to any VM
        if (volume.getInstanceId() != null) {
            throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
        }
           
        // Check that the volume is not already destroyed
        if (volume.getDestroyed()) {
            throw new InvalidParameterValueException("Please specify a volume that is not already destroyed.");
        }
        
        // Destroy the volume
        _storageMgr.destroyVolume(volume);
    }

    @Override
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
        SearchCriteria sc = _publicIpAddressDao.createSearchCriteria();

        if (accountId != null)
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        if (zoneId != null)
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        if (vlanDbId != null)
            sc.addAnd("vlanDbId", SearchCriteria.Op.EQ, vlanDbId);
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        return _publicIpAddressDao.search(sc, null);
    }
Solution content
    }
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

        return _publicIpAddressDao.search(sc, null);
    }

    @Override
    public List listPrivateIpAddressesBy(Long podId, Long zoneId) {
        if (podId != null && zoneId != null)
            return _privateIpAddressDao.listByPodIdDcId(podId.longValue(), zoneId.longValue());
        else
            return new ArrayList();
    }

    @Override
    public String generateRandomPassword() {
    	return PasswordGenerator.generateRandomPassword();
    }

    @Override
    public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
    	UserVmVO vm = _userVmDao.findById(vmId);
    	VMTemplateVO iso = _templateDao.findById(isoId);
    	if(attach){
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_ATTACH, "Attaching ISO: "+isoId+" to Vm: "+vmId, startEventId);
    	} else {
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_DETACH, "Detaching ISO: "+isoId+" from Vm: "+vmId, startEventId);
    	}
        boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach);

        if (success) {
            if (attach) {
                vm.setIsoId(iso.getId().longValue());
            } else {
                vm.setIsoId(null);
            }
            _userVmDao.update(vmId, vm);

		return null;
            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_ATTACH, "Successfully attached ISO: " + iso.getName() + " to VM with ID: " + vmId,
                        null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_DETACH, "Successfully detached ISO from VM with ID: " + vmId, null, startEventId);
            }
        } else {
            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_ATTACH, "Failed to attach ISO: " + iso.getName() + " to VM with ID: " + vmId, null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_DETACH, "Failed to detach ISO from VM with ID: " + vmId, null, startEventId);
            }
        }
        return success;
    }

    private boolean validPassword(String password) {
        for (int i = 0; i < password.length(); i++) {
            if (password.charAt(i) == ' ') {
                return false;
            }
        }
        return true;
    }

    private UserVm deployVirtualMachineImpl(long userId, long accountId, long dataCenterId, long serviceOfferingId, long templateId, Long diskOfferingId,
            String domain, String password, String displayName, String group, String userData, String [] networkGroups, long startEventId, long size) throws ResourceAllocationException, InvalidParameterValueException, InternalErrorException,
            InsufficientStorageCapacityException, PermissionDeniedException, ExecutionException, StorageUnavailableException, ConcurrentOperationException {

    	EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "Deploying Vm", startEventId);
        
        AccountVO account = _accountDao.findById(accountId);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        VMTemplateVO template = _templateDao.findById(templateId);

        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }
        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
			
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        
        // TODO: Checks such as is the user allowed to use the template and purchase the service offering id.

        if (domain == null) {
            domain = "v" + Long.toHexString(accountId) + _domain;
        }

        // Check that the password was passed in and is valid
        if (!template.getEnablePassword()) {
            password = "saved_password";
        }

        if (password == null || password.equals("") || (!validPassword(password))) {
            throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
        }
        List networkGroupVOs = new ArrayList();
        if (networkGroups != null) {
        	for (String groupName: networkGroups) {
        		NetworkGroupVO networkGroupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
        		if (networkGroupVO == null) {
        			throw new InvalidParameterValueException("Network Group " + groupName + " does not exist");
        		}
        		networkGroupVOs.add(networkGroupVO);
        	}
        }
        
        UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dataCenterId);
        if (stats == null) {
            stats = new UserStatisticsVO(account.getId(), dataCenterId);
            _userStatsDao.persist(stats);
        }
        
    	Long vmId = _vmDao.getNextInSequence(Long.class, "id");
    	
        // check if we are within context of async-execution
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("DeployVM acquired a new instance " + vmId + ", update async job-" + job.getId() + " progress status");

            _asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", vmId);
            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, vmId);
        }

        HashMap avoids = new HashMap();

        // Pod allocator now allocate VM based on a reservation style allocation, disable retry here for now
        for (int retry = 0; retry < 1; retry++) {
            String externalIp = null;
            UserVmVO created = null;

            ArrayList a = new ArrayList(avoids.values());
            if (_directAttachNetworkExternalIpAllocator) {
            	try {
            		created = _vmMgr.createDirectlyAttachedVMExternal(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            	} catch (ResourceAllocationException rae) {
            		throw rae;
            	}
            } else {
            	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
            		try {
            			externalIp = _networkMgr.assignSourceNatIpAddress(account, dc, domain, offering, startEventId);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}

            		if (externalIp == null) {
            			throw new InternalErrorException("Unable to allocate a source nat ip address");
            		}

            		if (s_logger.isDebugEnabled()) {
            			s_logger.debug("Source Nat acquired: " + externalIp);
            		}

            		try {
            			created = _vmMgr.createVirtualMachine(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	} else {
            		try {
            			created = _vmMgr.createDirectlyAttachedVM(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	}
            }

            //assign vm to the group
            try{
            	if (group != null) {
            	boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
            	if (!addToGroup) {
            		throw new InternalErrorException("Unable to assing Vm to the group " + group);
            	}
                }
            } catch (Exception ex) {
            	throw new InternalErrorException("Unable to assing Vm to the group " + group);
            }
            
            
            if (created == null) {
                throw new InternalErrorException("Unable to create VM for account (" + accountId + "): " + account.getAccountName());
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM created: " + created.getId() + "-" + created.getName());
            }
            boolean executionExceptionFlag = false;
            boolean storageUnavailableExceptionFlag = false;
            boolean concurrentOperationExceptionFlag = false;
            String executionExceptionMsg= "";
            String storageUnavailableExceptionMsg = "";
            String concurrentOperationExceptionMsg = "";
            UserVmVO started = null;
            if (isIso) {
                String isoPath = _storageMgr.getAbsoluteIsoPath(templateId, dataCenterId);
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, isoPath, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }
            } else {
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, null, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }

            }

            if (started == null) {
                List> disks = _storageMgr.isStoredOn(created);
                // NOTE: We now destroy a VM if the deploy process fails at any step. We now
                // have a lazy delete so there is still some time to figure out what's wrong.
                _vmMgr.destroyVirtualMachine(userId, created.getId());

                boolean retryCreate = true;
                for (Pair disk : disks) {
                    if (disk.second().isLocal()) {
                        avoids.put(disk.second().getId(), disk.second());
                    } else {
                        retryCreate = false;
                    }
                }

                if (retryCreate) {
                    continue;
                } else if(executionExceptionFlag){
                    throw new ExecutionException(executionExceptionMsg);
                } else if (storageUnavailableExceptionFlag){
                	throw new StorageUnavailableException(storageUnavailableExceptionMsg);
                }else if (concurrentOperationExceptionFlag){
                	throw new ConcurrentOperationException(concurrentOperationExceptionMsg);
                }
                else{
                    throw new InternalErrorException("Unable to start the VM " + created.getId() + "-" + created.getName());
                }
                
            } else {
                if (isIso) {
                    started.setIsoId(templateId);
                    _userVmDao.update(started.getId(), started);
                    started = _userVmDao.findById(started.getId());
                }

                try {
					_configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null);															
				} catch (InsufficientAddressCapacityException e) {
					s_logger.debug("Unable to assign public IP address pool: " +e.getMessage());					
				}
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM started: " + started.getId() + "-" + started.getName());
            }
            return started;
        }

        return null;
    }

    @Override
    public UserVm deployVirtualMachine(DeployVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException,
                                                               InternalErrorException, InsufficientStorageCapacityException, ExecutionException,
                                                               StorageUnavailableException, ConcurrentOperationException {
        Account ctxAccount = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        long dataCenterId = cmd.getZoneId();
        long serviceOfferingId = cmd.getServiceOfferingId();
        long templateId = cmd.getTemplateId();
        Long diskOfferingId = cmd.getDiskOfferingId();
        String domain = null; // FIXME:  this was hardcoded to null in DeployVMCmd in the old framework, do we need it?
        String password = generateRandomPassword();
        String displayName = cmd.getDisplayName();
        String group = cmd.getGroup();
        String userData = cmd.getUserData();
        String[] networkGroups = null;
        Long sizeObj = cmd.getSize();
        long size = (sizeObj == null) ? 0 : sizeObj;

        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {
                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }

        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for deploying a virtual machine.");
        }

        List netGrpList = cmd.getNetworkGroupList();
        if ((netGrpList != null) && !netGrpList.isEmpty()) {
            networkGroups = netGrpList.toArray(new String[netGrpList.size()]);
        }

    	AccountVO account = _accountDao.findById(accountId);
        if (account == null) {
            throw new InvalidParameterValueException("Unable to find account: " + accountId);
        }

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        if (dc == null) {
            throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
        }

        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        if (offering == null) {
            throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
        }

        VMTemplateVO template = _templateDao.findById(templateId);
        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        
        if (isIso && !template.isBootable()) {
        	throw new InvalidParameterValueException("Please specify a bootable ISO.");
        }

        // If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
        // Else, a disk offering is optional, and if present will be used to create the data disk
        DiskOfferingVO diskOffering = null;

        if (diskOfferingId != null) {
        	diskOffering = _diskOfferingDao.findById(diskOfferingId);
        }

        if (isIso && diskOffering == null) {
    
        	throw new InvalidParameterValueException("Please specify a valid disk offering ID.");
        }

        // validate that the template is usable by the account
        if (!template.isPublicTemplate()) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType()) && ((templateOwner == null) || (templateOwner.longValue() != accountId))) {
                // since the current account is not the owner of the template, check the launch permissions table to see if the
                // account can launch a VM from this template
                LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(templateId, account.getId());
                if (permission == null) {
                    throw new PermissionDeniedException("Account " + account.getAccountName() + " does not have permission to launch instances from template " + template.getName());
                }
            }
        }

        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	if (decodedUserData.length < 1) {
        		throw new InvalidParameterValueException("User data is too short");
        	}
			
        }
        if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized) {
        	_networkGroupMgr.createDefaultNetworkGroup(accountId);
    	}
        
        if (networkGroups != null) {
        	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
        		throw new InvalidParameterValueException("Network groups are not compatible with service offering " + offering.getName());
        	}
        	Set nameSet = new HashSet(); //handle duplicate names -- allowed
        	nameSet.addAll(Arrays.asList(networkGroups));
        	nameSet.add(NetworkGroupManager.DEFAULT_GROUP_NAME);
        	networkGroups = nameSet.toArray(new String[nameSet.size()]);
        	List networkGroupVOs = _networkSecurityGroupDao.findByAccountAndNames(accountId, networkGroups);
        	if (networkGroupVOs.size() != nameSet.size()) {
        		throw new InvalidParameterValueException("Some network group names do not exist");
        	}
        } else { //create a default group if necessary
        	if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized && _networkGroupsEnabled) {
        		networkGroups = new String[]{NetworkGroupManager.DEFAULT_GROUP_NAME};
        	}
        }

        // FIXME:  this really needs to be invoked when the job is scheduled by the framework, so commands need a callback for
        //         specifying event details that they are tracking...
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "deploying Vm");

        try {
            return deployVirtualMachineImpl(userId, accountId, dataCenterId, serviceOfferingId, templateId, diskOfferingId, domain, password, displayName, group, userData, networkGroups, eventId, size);
        } catch (ResourceAllocationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (ExecutionException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_HOST_LICENSE_EXPIRED", null, eventId);
            throw e;
        } catch (InvalidParameterValueException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INVALID_PARAM_ERROR", null, eventId);
            throw e;
        } catch (InternalErrorException e) {
    @Override
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch (InsufficientStorageCapacityException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (PermissionDeniedException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: ACCOUNT_ERROR", null, eventId);
            throw e;
        } catch (ConcurrentOperationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch(Exception e) {
            s_logger.warn("Unable to deploy VM : " + e.getMessage(), e);
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw new CloudRuntimeException("Unable to deploy VM : " + e.getMessage());
        }
    }

    @Override
    public DomainRouterVO findDomainRouterBy(long accountId, long dataCenterId) {
        return _routerDao.findBy(accountId, dataCenterId);
    }

    @Override
    public DomainRouterVO findDomainRouterById(long domainRouterId) {
        return _routerDao.findById(domainRouterId);
    }

    @Override
    public List listDataCenters(ListZonesByCmd cmd) {
        List dcs = _dcDao.listAll();

        Account account = (Account)UserContext.current().getAccountObject();
        Boolean available = cmd.isAvailable();
        if (account != null) {
            if ((available != null) && Boolean.FALSE.equals(available)) {
                List routers = _routerDao.listBy(account.getId());
                for (Iterator iter = dcs.iterator(); iter.hasNext();) {
                    DataCenterVO dc = iter.next();
                    boolean found = false;
                    for (DomainRouterVO router : routers) {
                        if (dc.getId() == router.getDataCenterId()) {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        iter.remove();
                }
            }
        }

        return dcs;
    }

    @Override
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }

    @Override
    public long getId() {
        return MacAddress.getMacAddress().toLong();
    }

    protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {

        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("publicPort is an invalid value");
        }
        if (!NetUtils.isValidPort(privatePort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");
        }

//        s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
//        if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//            throw new InvalidParameterValueException("Invalid private ip address");
//        }
        if (!NetUtils.isValidProto(proto)) {
            throw new InvalidParameterValueException("Invalid protocol");
        }
    }

    @Override
    @DB
    public void assignSecurityGroup(AssignPortForwardingServiceCmd cmd) throws PermissionDeniedException,
            NetworkRuleConflictException, InvalidParameterValueException, InternalErrorException {
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	Long securityGroupId = cmd.getId();
    	List sgIdList = cmd.getIds();
    	String publicIp = cmd.getPublicIp();
    	Long vmId = cmd.getVirtualMachineId();
    	
    	//Verify input parameters
        if ((securityGroupId == null) && (sgIdList == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }


        if (userId == null) {
            userId = Long.valueOf(1);
        }

        List validateSGList = null;
        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = findAccountById(validatedAccountId);
                if (!isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }
    	
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            s_logger.warn("Unable to find virtual machine with id " + vmId);
            throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
        }
        long startEventId = EventUtils.saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "applying port forwarding service for Vm with Id: "+vmId);
    	
        boolean locked = false;
        Transaction txn = Transaction.currentTxn();
        try {
            EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "Applying port forwarding service for Vm with Id: "+vmId, startEventId);
            State vmState = userVm.getState();
            switch (vmState) {
            case Destroyed:
            case Error:
            case Expunging:
            case Unknown:
                throw new InvalidParameterValueException("Unable to assign port forwarding service(s) '"
                        + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "' to virtual machine " + vmId
                        + " due to virtual machine being in an invalid state for assigning a port forwarding service (" + vmState + ")");
            }

            // sanity check that the vm can be applied to the load balancer
            ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
            if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                }

                throw new InvalidParameterValueException("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }
            
            DomainRouterVO router = null;
            if (userVm.getDomainRouterId() != null)
            	router = _routerDao.findById(userVm.getDomainRouterId());
            if (router == null) {
                s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine " + userVm.toString());
                throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + vmId);
            }

            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;

            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User does not own supplied address");
            }

            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new InvalidParameterValueException("Invalid IP address " + publicIp + " for applying port forwarding services, the IP address is not in a 'virtual network' vlan.");
            }

            txn.start();

            if (securityGroupId == null) {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on list passed in
            } else {
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                {
                    // Save and create the event
                    String description;
                    String type = EventTypes.EVENT_NET_RULE_DELETE;
                    String level = EventVO.LEVEL_INFO;

                    for (FirewallRuleVO fwRule : fwRulesToRemove) {
                        fwRule.setEnabled(false); // disable rule for sending to the agent
                        _firewallRulesDao.remove(fwRule.getId()); // remove the rule from the database

                        description = "deleted ip forwarding rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                                + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                        EventUtils.saveEvent(userId, userVm.getAccountId(), level, type, description);
                    }
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);
                if ((updatedRules != null) && (updatedRules.size() != fwRulesToRemove.size())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to clean up all port forwarding service rules for public IP " + publicIp + " and guest vm " + userVm.getName()
                                + " while applying port forwarding service(s) '" + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "'"
                                + " -- intended to remove " + fwRulesToRemove.size() + " rules, removd " + ((updatedRules == null) ? "null" : updatedRules.size()) + " rules.");
                    }
                }

                List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    boolean success = _securityGroupVMMapDao.remove(sgVmMapping.getId());

                    SecurityGroupVO securityGroup = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());

                    // save off an event for removing the security group
                    EventVO event = new EventVO();
                    event.setUserId(userId);
                    event.setAccountId(userVm.getAccountId());
                    event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
                    String sgRemoveLevel = EventVO.LEVEL_INFO;
    }
                    String sgRemoveDesc = "Successfully removed ";
                    if (!success) {
                        sgRemoveLevel = EventVO.LEVEL_ERROR;
                        sgRemoveDesc = "Failed to remove ";
                    }
                    String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
                    event.setParameters(params);
                    event.setDescription(sgRemoveDesc + "port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
                    event.setLevel(sgRemoveLevel);
                    _eventDao.persist(event);
                }
            } else {
                List existingVMMaps = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId.longValue());
                if ((existingVMMaps != null) && !existingVMMaps.isEmpty()) {
                    for (SecurityGroupVMMapVO existingVMMap : existingVMMaps) {
                        if (existingVMMap.getInstanceId() == userVm.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("port forwarding service " + securityGroupId + " is already applied to virtual machine " + userVm.toString() + ", skipping assignment.");
                            }
                            return;
                        }
                    }
                }
            }

            List finalSecurityGroupIdList = new ArrayList();
            if (securityGroupId != null) {
                finalSecurityGroupIdList.add(securityGroupId);
            } else {
                finalSecurityGroupIdList.addAll(sgIdList);
            }

            for (Long sgId : finalSecurityGroupIdList) {
                if (sgId.longValue() == 0) {
        } finally {
        }
                    // group id of 0 means to remove all groups, which we just did above
                    break;
                }

                SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(sgId));
                if (securityGroup == null) {
                    s_logger.warn("Unable to find port forwarding service with id " + sgId);
                    throw new InvalidParameterValueException("Unable to find port forwarding service with id " + sgId);
                }

                if (!_domainDao.isChildDomain(securityGroup.getDomainId(), userVm.getDomainId())) {
                    s_logger.warn("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                    throw new InvalidParameterValueException("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(publicIp);
                Map> mappedPublicPorts = new HashMap>();

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
                    }
                }

                List loadBalancers = _loadBalancerDao.listByIpAddress(publicIp);
                if (loadBalancers != null) {
                    for (LoadBalancerVO loadBalancer : loadBalancers) {
                        // load balancers don't have to be applied to an
                        // instance for there to be a conflict on the load
                        // balancers ip/port, so just
                        // map the public port to a pair of empty strings
                        mappedPublicPorts.put(loadBalancer.getPublicPort(), new Pair("", ""));
                    }
                }

                List firewallRulesToApply = new ArrayList();
                List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgId);

                for (NetworkRuleConfigVO netRule : netRules) {
                    Pair privateIpPort = mappedPublicPorts.get(netRule.getPublicPort());
                    if (privateIpPort != null) {
                        if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(netRule.getPrivatePort())) {
                            continue; // already mapped
                        } else {
                            throw new NetworkRuleConflictException("An existing service rule for " + publicIp + ":" + netRule.getPublicPort()
                                    + " already exists, found while trying to apply service rule " + netRule.getId() + " from port forwarding service " + securityGroup.getName() + ".");
                        }
                    }

                    FirewallRuleVO newFwRule = new FirewallRuleVO();
                    newFwRule.setEnabled(true);
                    newFwRule.setForwarding(true);
                    newFwRule.setPrivatePort(netRule.getPrivatePort());
                    newFwRule.setProtocol(netRule.getProtocol());
                    newFwRule.setPublicPort(netRule.getPublicPort());
                    newFwRule.setPublicIpAddress(publicIp);
                    newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                    newFwRule.setGroupId(netRule.getSecurityGroupId());

                    firewallRulesToApply.add(newFwRule);
                    _firewallRulesDao.persist(newFwRule);

                    String description = "created new ip forwarding rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                            + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
                }

                // now that individual rules have been created from the security group, save the security group mapping for this ip/vm instance
                SecurityGroupVMMapVO sgVmMap = new SecurityGroupVMMapVO(sgId, publicIp, vmId);
                _securityGroupVMMapDao.persist(sgVmMap);

                // Save off information for the event that the security group was applied
                EventVO event = new EventVO();
                event.setUserId(userId);
                event.setAccountId(userVm.getAccountId());
                event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY);
                event.setStartId(startEventId);
                event.setDescription("Successfully applied port forwarding service " + securityGroup.getName() + " to virtual machine " + userVm.getName());
                String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId+"\nnumRules="+firewallRulesToApply.size()+"\ndcId="+userVm.getDataCenterId();
                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
                _eventDao.persist(event);

                _networkMgr.updateFirewallRules(publicIp, firewallRulesToApply, router);
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public void removeSecurityGroup(RemovePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	
    	Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long securityGroupId = cmd.getId();
        String publicIp = cmd.getPublicIp();
        Long vmId = cmd.getVirtualMachineId();
        
        //verify input parameters
        SecurityGroupVO securityG = _securityGroupDao.findById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
            }
        }
        
        UserVmVO vmInstance = findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing port forwarding services for Vm with Id: "+vmId);

        /*TODO : ASK KRIS AS TO WHAT DO WE DO WITH THIS PART IN THE EXECUTOR CODE
        UserVmVO userVm = userVmDao.findById(param.getInstanceId());
        if(userVm == null)
        	return null;
        
        if (userVm.getDomainRouterId() == null) {
        	return null;
        } else
        	return routerDao.findById(userVm.getDomainRouterId());
	    */
        removeSecurityGroup(userId, securityGroupId, publicIp, vmId, eventId);
    }
    
    @Override
    @DB
    public void removeSecurityGroup(long userId, long securityGroupId, String publicIp, long vmId, long startEventId) throws InvalidParameterValueException, PermissionDeniedException {
        // This gets complicated with overlapping rules. As an example:
        // security group 1 has the following port mappings: 22->22 on TCP,
        // 23->23 on TCP, 80->8080 on TCP
        // security group 2 has the following port mappings: 22->22 on TCP,
        // 7891->7891 on TCP
        // User assigns group 1 & 2 on 192.168.10.120 to vm 1
        // Later, user removed group 1 from 192.168.10.120 and vm 1
        // Final valid port mappings should be 22->22 and 7891->7891 which both
        // come from security group 2. The mapping
        // for port 22 should not be removed.
        boolean locked = false;
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Unable to find vm: " + vmId);
        }
                            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "Removing port forwarding services for Vm with Id: "+vmId, startEventId);
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
            throw new InvalidParameterValueException("Unable to find port forwarding service: " + securityGroupId);
        }

        DomainRouterVO router = null;
        if (userVm.getDomainRouterId() != null)
        	router = _routerDao.findById(userVm.getDomainRouterId());
        if (router == null) {
            throw new InvalidParameterValueException("Unable to find router for ip address: " + publicIp);
        }

        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe
                // for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }

            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User/account does not own supplied address");
            }

            txn.start();

            // get the account for writing events
            Account account = _accountDao.findById(userVm.getAccountId());
            {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on existing SG mappings
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                for (FirewallRuleVO fwRule : fwRulesToRemove) {
                    fwRule.setEnabled(false);
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "ip forwarding";
                String level = EventVO.LEVEL_INFO;

                for (FirewallRuleVO fwRule : updatedRules) {
                    _firewallRulesDao.remove(fwRule.getId());

                    description = "deleted " + ruleName + " rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                            + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), level, type, description);
                }
            }

            // since we know these groups all pass muster, just keep track
            // of the public ports we are mapping on this public IP and
            // don't duplicate
            List alreadyMappedPorts = new ArrayList();
            List fwRulesToAdd = new ArrayList();
            List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                if (sgVmMapping.getSecurityGroupId() == securityGroupId) {
                    _securityGroupVMMapDao.remove(sgVmMapping.getId());
                } else {
                    List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgVmMapping.getSecurityGroupId());
                    for (NetworkRuleConfigVO netRule : netRules) {
                        if (!alreadyMappedPorts.contains(netRule.getPublicPort())) {
                            FirewallRuleVO newFwRule = new FirewallRuleVO();
                            newFwRule.setEnabled(true);
                            newFwRule.setForwarding(true);
                            newFwRule.setPrivatePort(netRule.getPrivatePort());
                            newFwRule.setProtocol(netRule.getProtocol());
                            newFwRule.setPublicPort(netRule.getPublicPort());
                            newFwRule.setPublicIpAddress(publicIp);
                            newFwRule.setGroupId(netRule.getSecurityGroupId());

                            fwRulesToAdd.add(newFwRule);

                            alreadyMappedPorts.add(netRule.getPublicPort());
                        }
                    }
                }
            }

            for (FirewallRuleVO addedRule : fwRulesToAdd) {
                _firewallRulesDao.persist(addedRule);

                String description = "created new ip forwarding rule [" + addedRule.getPublicIpAddress() + ":" + addedRule.getPublicPort() + "]->["
                        + addedRule.getPrivateIpAddress() + ":" + addedRule.getPrivatePort() + "]" + " " + addedRule.getProtocol();

                EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
            }

            // save off an event for removing the security group
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(userVm.getAccountId());
            event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
            event.setDescription("Successfully removed port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
            event.setLevel(EventVO.LEVEL_INFO);
            String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
            event.setParameters(params);
            _eventDao.persist(event);

            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
            } else {
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }
        if (domainId != null) {
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
    @Override
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object accountName = cmd.getAccountName();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            }
        } else if (domainId != null) {
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object name = cmd.getServiceOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    @Override
    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object name = cmd.getClusterName();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (state != null) {
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _hostPodDao.search(sc, searchFilter);
    }

    @Override
    public List searchForZones(Criteria c) {
        return _vlanDao.search(sc, searchFilter);
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        if (accountName != null && domainId != null) {
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
                }
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);

        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        }
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        } else {
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
        return _launchPermissionDao.listPermittedTemplates(accountId);
    }

    @Override
        }
    public List listPods(long dataCenterId) {
        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }

    @Override
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
                }
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
        if (isPublic != null) {
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {

        return _vmInstanceDao.findById(vmId);
    }

    @Override
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    @Override
    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            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();
                }
            } else {
    }
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {

    @Override
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
            accountId = account.getId();
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
            sc.setParameters("id", id);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        	else
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
        }
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
        if (domainId != null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        } else {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        }

        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        _alertMgr.recalculateCapacity();
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        

        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }
        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        
        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
        Object name = cmd.getPortForwardingServiceName();
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
        return success;
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

            } else if (ipAddressOwner != null) {
        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                }

                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
	}
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

	@Override
        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {

        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }
        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Catch clause
Comment
If statement
Method declaration
Method invocation
Method signature
Return statement
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
=======
    public boolean resetVMPassword(long userId, long vmId, String password) {
        if (password == null || password.equals("")) {
            return false;
        }
        boolean succeed = _vmMgr.resetVMPassword(userId, vmId, password);

        // Log event
        UserVmVO userVm = _userVmDao.findById(vmId);
        if (userVm != null) {
            if (succeed) {
                saveEvent(userId, userVm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_VM_RESETPASSWORD, "successfully reset password for VM : " + userVm.getName(), null);
            } else {
                saveEvent(userId, userVm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_RESETPASSWORD, "unable to reset password for VM : " + userVm.getName(), null);
            }
        } else {
            s_logger.warn("Unable to find vm = " + vmId + " to reset password");
        }
        return succeed;
    }

    @Override
    public void attachVolumeToVM(long vmId, long volumeId, Long deviceId, long startEventId) throws InternalErrorException {
        _vmMgr.attachVolumeToVM(vmId, volumeId, deviceId, startEventId);
    }

    @Override
    public long attachVolumeToVMAsync(long vmId, long volumeId, Long deviceId) throws InvalidParameterValueException {
        VolumeVO volume = _volumeDao.findById(volumeId);

        // Check that the volume is a data volume
        if (volume == null || volume.getVolumeType() != VolumeType.DATADISK) {
            throw new InvalidParameterValueException("Please specify a valid data volume.");
        }

        // Check that the volume is stored on shared storage
        if (!_storageMgr.volumeOnSharedStoragePool(volume)) {
            throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
        }

        // Check that the VM is a UserVM
        UserVmVO vm = _userVmDao.findById(vmId);
        if (vm == null || vm.getType() != VirtualMachine.Type.User) {
            throw new InvalidParameterValueException("Please specify a valid User VM.");
        }
        
        // Check that the VM is in the correct state
        if (vm.getState() != State.Running && vm.getState() != State.Stopped) {
        	throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
        }

        // Check that the volume is not currently attached to any VM
        if (volume.getInstanceId() != null) {
            throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
        }

        // Check that the volume is not destroyed
        if (volume.getDestroyed()) {
            throw new InvalidParameterValueException("Please specify a volume that is not destroyed.");
        }

        // Check that the VM has less than 6 data volumes attached
        List existingDataVolumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.DATADISK);
        if (existingDataVolumes.size() >= 6) {
            throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (6). Please specify another VM.");
        }
        
        // Check that the VM and the volume are in the same zone
        if (vm.getDataCenterId() != volume.getDataCenterId()) {
        	throw new InvalidParameterValueException("Please specify a VM that is in the same zone as the volume.");
        }
        long eventId = saveScheduledEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_ATTACH, "attaching volume: "+volumeId+" to Vm: "+vmId);
        VolumeOperationParam param = new VolumeOperationParam();
        param.setUserId(1);
        param.setAccountId(volume.getAccountId());
        param.setOp(VolumeOp.Attach);
        param.setVmId(vmId);
        param.setVolumeId(volumeId);
        param.setEventId(eventId);
        param.setDeviceId(deviceId);

        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
        job.setUserId(UserContext.current().getUserId());
        job.setAccountId(vm.getAccountId());
        job.setCmd("VolumeOperation");
        job.setCmdInfo(gson.toJson(param));
        job.setCmdOriginator("virtualmachine");
        
        return _asyncMgr.submitAsyncJob(job);
    }

    @Override
    public void detachVolumeFromVM(long volumeId, long startEventId, long deviceId, long instanceId) throws InternalErrorException {
        _vmMgr.detachVolumeFromVM(volumeId, startEventId, deviceId, instanceId);
    }

    @Override
    public long detachVolumeFromVMAsync(long volumeId, long deviceId, long instanceId) throws InvalidParameterValueException {
    	VolumeVO volume = null;
    	if(volumeId!=0)
    		volume = _volumeDao.findById(volumeId);
    	else
    		volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);

        // Check that the volume is a data volume
        if (volume.getVolumeType() != VolumeType.DATADISK) {
            throw new InvalidParameterValueException("Please specify a data volume.");
        }

        // Check that the volume is stored on shared storage
        if (!_storageMgr.volumeOnSharedStoragePool(volume)) {
            throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
        }

        Long vmId = volume.getInstanceId();

        // Check that the volume is currently attached to a VM
        if (vmId == null) {
            throw new InvalidParameterValueException("The specified volume is not attached to a VM.");
        }

        // Check that the VM is in the correct state
        UserVmVO vm = _vmDao.findById(vmId);
        if (vm.getState() != State.Running && vm.getState() != State.Stopped) {
        	throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
        }
        
        long eventId = saveScheduledEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_DETACH, "detaching volume: "+volumeId+" from Vm: "+vmId);
        VolumeOperationParam param = new VolumeOperationParam();
        param.setUserId(1);
        param.setAccountId(volume.getAccountId());
        param.setOp(VolumeOp.Detach);
        param.setVolumeId(volumeId);
        param.setDeviceId(deviceId);
        param.setVmId(instanceId);
        param.setEventId(eventId);

        Gson gson = GsonHelper.getBuilder().create();

		AsyncJobVO job = new AsyncJobVO();
		job.setUserId(UserContext.current().getUserId());
		job.setAccountId(vm.getAccountId());
		job.setCmd("VolumeOperation");
		job.setCmdInfo(gson.toJson(param));
		job.setCmdOriginator("virtualmachine");
		
		return _asyncMgr.submitAsyncJob(job);
	}

    @Override
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
    	UserVmVO vm = _userVmDao.findById(vmId);
    	VMTemplateVO iso = _templateDao.findById(isoId);
Solution content
                    }
        if (instanceId != null) {
        }

        return success;
    }

    @Override
import com.cloud.api.commands.ListCfgsByCmd;

import com.cloud.api.commands.ListClustersCmd;
        }
/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */
package com.cloud.server;

import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.alert.AlertVO;
import com.cloud.alert.dao.AlertDao;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AssignPortForwardingServiceCmd;
import com.cloud.api.commands.CreateDomainCmd;
import com.cloud.api.commands.CreatePortForwardingServiceCmd;
import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd;
import com.cloud.api.commands.CreateUserCmd;
import com.cloud.api.commands.DeleteDomainCmd;
import com.cloud.api.commands.DeletePortForwardingServiceCmd;
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeleteUserCmd;
import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.EnableAccountCmd;
import com.cloud.api.commands.EnableUserCmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapabilitiesCmd;
import com.cloud.api.commands.ListCapacityCmd;

import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListIsosCmd;
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPortForwardingServiceRulesCmd;
import com.cloud.api.commands.ListPortForwardingServicesByVmCmd;
import com.cloud.api.commands.ListPortForwardingServicesCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListStoragePoolsAndHostsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMGroupsCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.LockAccountCmd;
import com.cloud.api.commands.LockUserCmd;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.RemovePortForwardingServiceCmd;
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateAccountCmd;
import com.cloud.api.commands.UpdateDomainCmd;
import com.cloud.api.commands.UpdateIPForwardingRuleCmd;
import com.cloud.api.commands.UpdateIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplatePermissionsCmd;
import com.cloud.api.commands.UpdateUserCmd;
import com.cloud.api.commands.UpdateVMGroupCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
            }
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.network.FirewallRuleVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVMMapVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkRuleConfigVO;
import com.cloud.network.SecurityGroupVMMapVO;
import com.cloud.network.SecurityGroupVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.security.NetworkGroupManager;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.network.security.dao.NetworkGroupDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.DiskTemplateVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Snapshot.SnapshotType;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.DiskTemplateDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.LaunchPermissionDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVMMapVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.InstanceGroupVMMapDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

public class ManagementServerImpl implements ManagementServer {	
    public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());

    private final AccountManager _accountMgr;
    private final AgentManager _agentMgr;
    private final ConfigurationManager _configMgr;
    private final FirewallRulesDao _firewallRulesDao;
    private final SecurityGroupDao _securityGroupDao;
	private final NetworkGroupDao _networkSecurityGroupDao;
    private final LoadBalancerDao _loadBalancerDao;
    private final NetworkRuleConfigDao _networkRuleConfigDao;
    private final SecurityGroupVMMapDao _securityGroupVMMapDao;
    private final IPAddressDao _publicIpAddressDao;
    private final DataCenterIpAddressDaoImpl _privateIpAddressDao;
    private final LoadBalancerVMMapDao _loadBalancerVMMapDao;
    private final DomainRouterDao _routerDao;
    private final ConsoleProxyDao _consoleProxyDao;
    private final ClusterDao _clusterDao;
    private final SecondaryStorageVmDao _secStorageVmDao;
    private final EventDao _eventDao;
    private final DataCenterDao _dcDao;
    private final VlanDao _vlanDao;
    private final AccountVlanMapDao _accountVlanMapDao;
    private final PodVlanMapDao _podVlanMapDao;
    private final HostDao _hostDao;
    private final UserDao _userDao;
    private final UserVmDao _userVmDao;
    private final ConfigurationDao _configDao;
    private final NetworkManager _networkMgr;
    private final UserVmManager _vmMgr;
    private final ConsoleProxyManager _consoleProxyMgr;
    private final SecondaryStorageVmManager _secStorageVmMgr;
    private final ServiceOfferingDao _offeringsDao;
    private final DiskOfferingDao _diskOfferingDao;
    private final VMTemplateDao _templateDao;
    private final LaunchPermissionDao _launchPermissionDao;
    private final DomainDao _domainDao;
    private final AccountDao _accountDao;
    private final ResourceLimitDao _resourceLimitDao;
    private final UserAccountDao _userAccountDao;
    private final AlertDao _alertDao;
    private final CapacityDao _capacityDao;
    private final SnapshotDao _snapshotDao;
    private final SnapshotPolicyDao _snapshotPolicyDao;
    private final GuestOSDao _guestOSDao;
    private final GuestOSCategoryDao _guestOSCategoryDao;
    private final StoragePoolDao _poolDao;
    private final StoragePoolHostDao _poolHostDao;
    private final StorageManager _storageMgr;
    private final UserVmDao _vmDao;

    private final Adapters _userAuthenticators;
    private final HostPodDao _hostPodDao;
    private final UserStatisticsDao _userStatsDao;
    private final VMInstanceDao _vmInstanceDao;
    private final VolumeDao _volumeDao;
    private final DiskTemplateDao _diskTemplateDao;
    private final AlertManager _alertMgr;
    private final AsyncJobDao _jobDao;
    private final AsyncJobManager _asyncMgr;
    private final TemplateManager _tmpltMgr;
    private final SnapshotManager _snapMgr;
    private final NetworkGroupManager _networkGroupMgr;
    private final int _purgeDelay;
    private final boolean _directAttachNetworkExternalIpAllocator;
    private final PreallocatedLunDao _lunDao;
    private final InstanceGroupDao _vmGroupDao;
    private final InstanceGroupVMMapDao _groupVMMapDao;
    private final UploadMonitor _uploadMonitor;
    private final UploadDao _uploadDao;

    private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
    private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));

    private final StatsCollector _statsCollector;

    private final Map _configs;

    private String _domain;

    private final int _routerRamSize;
    private final int _proxyRamSize;
    private final int _ssRamSize;

    private final Map _availableIdsMap;

	private boolean _networkGroupsEnabled = false;

    private boolean _isHypervisorSnapshotCapable = false;

    protected ManagementServerImpl() {
        ComponentLocator locator = ComponentLocator.getLocator(Name);
        _lunDao = locator.getDao(PreallocatedLunDao.class);
        _configDao = locator.getDao(ConfigurationDao.class);
        _routerDao = locator.getDao(DomainRouterDao.class);
        _eventDao = locator.getDao(EventDao.class);
        _dcDao = locator.getDao(DataCenterDao.class);
        _vlanDao = locator.getDao(VlanDao.class);
        _accountVlanMapDao = locator.getDao(AccountVlanMapDao.class);
        _podVlanMapDao = locator.getDao(PodVlanMapDao.class);
        _hostDao = locator.getDao(HostDao.class);
        _hostPodDao = locator.getDao(HostPodDao.class);
        _jobDao = locator.getDao(AsyncJobDao.class);
        _clusterDao = locator.getDao(ClusterDao.class);

        _accountMgr = locator.getManager(AccountManager.class);
        _agentMgr = locator.getManager(AgentManager.class);
        _configMgr = locator.getManager(ConfigurationManager.class);
        _networkMgr = locator.getManager(NetworkManager.class);
        _vmMgr = locator.getManager(UserVmManager.class);
        _consoleProxyMgr = locator.getManager(ConsoleProxyManager.class);
        _secStorageVmMgr = locator.getManager(SecondaryStorageVmManager.class);
        _storageMgr = locator.getManager(StorageManager.class);
        _firewallRulesDao = locator.getDao(FirewallRulesDao.class);
        _securityGroupDao = locator.getDao(SecurityGroupDao.class);
        _networkSecurityGroupDao  = locator.getDao(NetworkGroupDao.class);
        _loadBalancerDao = locator.getDao(LoadBalancerDao.class);
        _networkRuleConfigDao = locator.getDao(NetworkRuleConfigDao.class);
        _securityGroupVMMapDao = locator.getDao(SecurityGroupVMMapDao.class);
        _publicIpAddressDao = locator.getDao(IPAddressDao.class);
        _privateIpAddressDao = locator.getDao(DataCenterIpAddressDaoImpl.class);
        _loadBalancerVMMapDao = locator.getDao(LoadBalancerVMMapDao.class);
        _consoleProxyDao = locator.getDao(ConsoleProxyDao.class);
        _secStorageVmDao = locator.getDao(SecondaryStorageVmDao.class);
        _userDao = locator.getDao(UserDao.class);
        _userVmDao = locator.getDao(UserVmDao.class);
        _offeringsDao = locator.getDao(ServiceOfferingDao.class);
        _diskOfferingDao = locator.getDao(DiskOfferingDao.class);
        _templateDao = locator.getDao(VMTemplateDao.class);
        _launchPermissionDao = locator.getDao(LaunchPermissionDao.class);
        _domainDao = locator.getDao(DomainDao.class);
        _accountDao = locator.getDao(AccountDao.class);
        _resourceLimitDao = locator.getDao(ResourceLimitDao.class);
        _userAccountDao = locator.getDao(UserAccountDao.class);
        _alertDao = locator.getDao(AlertDao.class);
        _capacityDao = locator.getDao(CapacityDao.class);
        _snapshotDao = locator.getDao(SnapshotDao.class);
        _snapshotPolicyDao = locator.getDao(SnapshotPolicyDao.class);
        _guestOSDao = locator.getDao(GuestOSDao.class);
        _guestOSCategoryDao = locator.getDao(GuestOSCategoryDao.class);
        _poolDao = locator.getDao(StoragePoolDao.class);
        _poolHostDao = locator.getDao(StoragePoolHostDao.class);
        _vmDao = locator.getDao(UserVmDao.class);
        _vmGroupDao = locator.getDao(InstanceGroupDao.class);
        _groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class);
        _uploadDao = locator.getDao(UploadDao.class);

        _configs = _configDao.getConfiguration();
        _userStatsDao = locator.getDao(UserStatisticsDao.class);
        _vmInstanceDao = locator.getDao(VMInstanceDao.class);
        _volumeDao = locator.getDao(VolumeDao.class);
        _diskTemplateDao = locator.getDao(DiskTemplateDao.class);
        _alertMgr = locator.getManager(AlertManager.class);
        _asyncMgr = locator.getManager(AsyncJobManager.class);
        _tmpltMgr = locator.getManager(TemplateManager.class);
    	if (lun.getTaken() != null) {
        _snapMgr = locator.getManager(SnapshotManager.class);
        _networkGroupMgr = locator.getManager(NetworkGroupManager.class);
        _uploadMonitor = locator.getManager(UploadMonitor.class);                
        
        _userAuthenticators = locator.getAdapters(UserAuthenticator.class);
        if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
            s_logger.error("Unable to find an user authenticator.");
        }

        _domain = _configs.get("domain");
        if (_domain == null) {
            _domain = ".myvm.com";
        }
        if (!_domain.startsWith(".")) {
            _domain = "." + _domain;
        }

        String value = _configs.get("account.cleanup.interval");
        int cleanup = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour.

        // Parse the max number of UserVMs and public IPs from server-setup.xml,
        // and set them in the right places
        _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
        _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
        _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);

        _directAttachNetworkExternalIpAllocator =
        										Boolean.parseBoolean(_configs.get("direct.attach.network.externalIpAllocator.enabled"));
        
        _statsCollector = StatsCollector.getInstance(_configs);
        _executor.scheduleAtFixedRate(new AccountCleanupTask(), cleanup, cleanup, TimeUnit.SECONDS);

        _purgeDelay = NumbersUtil.parseInt(_configs.get("event.purge.delay"), 0);
        if(_purgeDelay != 0){
            _eventExecutor.scheduleAtFixedRate(new EventPurgeTask(), cleanup, cleanup, TimeUnit.SECONDS);
        }
        
        String[] availableIds = TimeZone.getAvailableIDs();
        _availableIdsMap = new HashMap(availableIds.length);
        for (String id: availableIds) {
            _availableIdsMap.put(id, true);
        }
        String enabled =_configDao.getValue("direct.attach.network.groups.enabled");
		if ("true".equalsIgnoreCase(enabled)) {
			_networkGroupsEnabled = true;
		}
 		
		String hypervisorType = _configDao.getValue("hypervisor.type");
        _isHypervisorSnapshotCapable  = hypervisorType.equals(Hypervisor.Type.XenServer.name());
    }

    protected Map getConfigs() {
        return _configs;
    }

    @Override
    public StorageStats getStorageStatistics(long hostId) {
        return _statsCollector.getStorageStats(hostId);
    }
    
    @Override
    public PreallocatedLunVO registerPreallocatedLun(RegisterPreallocatedLunCmd cmd) {
        Long zoneId = cmd.getZoneId();
        String portal = cmd.getPortal();
        String targetIqn = cmd.getTargetIqn();
        Integer lun = cmd.getLun();
        Long size = cmd.getDiskSize();
        String t = cmd.getTags();

        String[] tags = null;
        if (t != null) {
            tags = t.split(",");
            for (int i = 0; i < tags.length; i++) {
                tags[i] = tags[i].trim();
            }
        } else {
            tags = new String[0];
        }
        
        PreallocatedLunVO vo = new PreallocatedLunVO(zoneId, portal, targetIqn, lun, size);
        return _lunDao.persist(vo, tags);
    }
    
    @Override
    public boolean unregisterPreallocatedLun(DeletePreallocatedLunCmd cmd) throws IllegalArgumentException {
        Long id = cmd.getId();
    	PreallocatedLunVO lun = null;
    	if ((lun = _lunDao.findById(id)) == null) {
    		throw new IllegalArgumentException("Unable to find a LUN with ID " + id);
    	}
    	
    		throw new IllegalArgumentException("The LUN is currently in use and cannot be deleted.");
    	}
    	
        return _lunDao.delete(id);
    }

    @Override
    public VolumeStats[] getVolumeStatistics(long[] volIds) {
        return _statsCollector.getVolumeStats(volIds);
    }

    @Override
    public UserAccount createUser(CreateUserCmd cmd) {
        Long accountId = null;
        String username = cmd.getUsername();
        String password = cmd.getPassword();
        String firstName = cmd.getFirstname();
        String lastName = cmd.getLastname();
        Long domainId = cmd.getDomainId();
        String email = cmd.getEmail();
        String timezone = cmd.getTimezone();
        String accountName = cmd.getAccountName();
        short userType = cmd.getAccountType().shortValue();
        try {
            if (accountName == null) {
                accountName = username;
            }
            if (domainId == null) {
                domainId = DomainVO.ROOT_DOMAIN;
            }

            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account != null) {
                if (account.getType() != userType) {
                    throw new CloudRuntimeException("Account " + accountName + " is not the correct account type for user " + username);
                }
                accountId = account.getId();
            }

            if (!_userAccountDao.validateUsernameInDomain(username, domainId)) {
                throw new CloudRuntimeException("The user " + username + " already exists in domain " + domainId);
            }

            if (accountId == null) {
                if ((userType < Account.ACCOUNT_TYPE_NORMAL) || (userType > Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given; unable to create user");
                }

                // create a new account for the user
                AccountVO newAccount = new AccountVO();
                if (domainId == null) {
                    // root domain is default
                    domainId = DomainVO.ROOT_DOMAIN;
                }

        }
                if ((domainId != DomainVO.ROOT_DOMAIN) && (userType == Account.ACCOUNT_TYPE_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given for an account in domain " + domainId + "; unable to create user.");
                }

                newAccount.setAccountName(accountName);
                newAccount.setDomainId(domainId);
                newAccount.setType(userType);
                newAccount.setState("enabled");
                newAccount = _accountDao.persist(newAccount);
                accountId = newAccount.getId();
            }

            if (accountId == null) {
                throw new CloudRuntimeException("Failed to create account for user: " + username + "; unable to create user");
            }

            UserVO user = new UserVO();
            user.setUsername(username);
            user.setPassword(password);
            user.setState("enabled");
            user.setFirstname(firstName);
            user.setLastname(lastName);
            user.setAccountId(accountId.longValue());
            user.setEmail(email);
            user.setTimezone(timezone);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Creating user: " + username + ", account: " + accountName + " (id:" + accountId + "), domain: " + domainId + " timezone:"+ timezone);
            }

            UserVO dbUser = _userDao.persist(user);
            
            _networkGroupMgr.createDefaultNetworkGroup(accountId);

            if (!user.getPassword().equals(dbUser.getPassword())) {
            return null;
                throw new CloudRuntimeException("The user " + username + " being creating is using a password that is different than what's in the db");
            }

            EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_CREATE, "User, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId + " was created.");
            return _userAccountDao.findById(dbUser.getId());
        } catch (Exception e) {
        	EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_CREATE, "Error creating user, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId);
            if (e instanceof CloudRuntimeException) {
                s_logger.info("unable to create user: " + e);
            } else {
                s_logger.warn("unknown exception creating user", e);
            }
            throw new CloudRuntimeException(e.getMessage());
        }
    }

    @Override
    public String updateAdminPassword(long userId, String oldPassword, String newPassword) {
        // String old = StringToMD5(oldPassword);
        // User user = getUser(userId);
        // if (old.equals(user.getPassword())) {
        UserVO userVO = _userDao.createForUpdate(userId);
        userVO.setPassword(StringToMD5(newPassword));
        _userDao.update(userId, userVO);
        return newPassword;
        // } else {
        // return null;
        // }
    }

    private String StringToMD5(String string) {
        MessageDigest md5;

        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new CloudRuntimeException("Error", e);
        }

        md5.reset();
        BigInteger pwInt = new BigInteger(1, md5.digest(string.getBytes()));

        // make sure our MD5 hash value is 32 digits long...
        StringBuffer sb = new StringBuffer();
        String pwStr = pwInt.toString(16);
        int padding = 32 - pwStr.length();
        for (int i = 0; i < padding; i++) {
            sb.append('0');
        }
        sb.append(pwStr);
        return sb.toString();
    }

    @Override
    public User getUser(long userId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId);
        }

        UserVO user = _userDao.getUser(userId);
        if (user == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with id " + userId);
            }
            return null;
        }

        return user;
    }

    @Override
    public User getUser(long userId, boolean active) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId + " and active = " + active);
        }

        if (active) {
            return _userDao.getUser(userId);
        } else {
            return _userDao.findById(userId);
        }
    }

    @Override
    public UserAccount getUserAccount(String username, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user: " + username + " in domain " + domainId);
        }

        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
        return userAccount;
    }

    private UserAccount getUserAccount(String username, String password, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
        }

        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        if (!userAccount.getState().equals("enabled") || !userAccount.getAccountState().equals("enabled")) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("user " + username + " in domain " + domainId + " is disabled/locked (or account is disabled/locked), returning null");
            }
            return null;
        }

        // We only use the first adapter even if multiple have been
        // configured
        Enumeration en = _userAuthenticators.enumeration();
        UserAuthenticator authenticator = en.nextElement();
        boolean authenticated = authenticator.authenticate(username, password, domainId);

        if (authenticated) {
        	return userAccount;
        } else {
        	return null;
        }
    }

    private boolean deleteUserInternal(long userId) {
        UserAccount userAccount = null;
        Long accountId = null;
        String username = null;
        try {
            UserVO user = _userDao.findById(userId);
            if (user == null || user.getRemoved() != null) {
                return true;
            }
            username = user.getUsername();
            boolean result = _userDao.remove(userId);
            if (!result) {
                s_logger.error("Unable to remove the user with id: " + userId + "; username: " + user.getUsername());
                return false;
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("User is removed, id: " + userId + "; username: " + user.getUsername());
            }
            accountId = user.getAccountId();
            userAccount = _userAccountDao.findById(userId);

            List users = _userDao.listByAccount(accountId);
            if (users.size() != 0) {
                s_logger.debug("User (" + userId + "/" + user.getUsername() + ") is deleted but there's still other users in the account so not deleting account.");
                return true;
            }

            result = _accountDao.remove(accountId);
            if (!result) {
                s_logger.error("Unable to delete account " + accountId);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Remove account " + accountId);
            }

            AccountVO account = _accountDao.findById(accountId);
            deleteAccount(account);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "User " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + userAccount.getDomainId() + " was deleted.");
            return true;
        } catch (Exception e) {
            s_logger.error("exception deleting user: " + userId, e);
            long domainId = 0L;
            if (userAccount != null)
                domainId = userAccount.getDomainId();
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "Error deleting user " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + domainId);
            return false;
        }
    }

    public boolean deleteAccount(AccountVO account) {
        long accountId = account.getId();
        long userId = 1L; // only admins can delete users, pass in userId 1 XXX: Shouldn't it be userId 2.
        boolean accountCleanupNeeded = false;
        
        try {
        	//delete all vm groups belonging to accont
        	List groups = _vmGroupDao.listByAccountId(accountId);
            for (InstanceGroupVO group : groups) {
                if (!_vmMgr.deleteVmGroup(group.getId())) {
                    s_logger.error("Unable to delete group: " + group.getId());
                    accountCleanupNeeded = true;
                } 
            }
        	
            // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
            boolean success = _snapMgr.deleteSnapshotDirsForAccount(accountId);
            if (success) {
                s_logger.debug("Successfully deleted snapshots directories for all volumes under account " + accountId + " across all zones");
            }
            // else, there are no snapshots, hence no directory to delete.
            
            // Destroy the account's VMs
            List vms = _userVmDao.listByAccountId(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of vms (accountId=" + accountId + "): " + vms.size());
            }

            for (UserVmVO vm : vms) {
                if (!_vmMgr.destroyVirtualMachine(userId, vm.getId())) {
                    s_logger.error("Unable to destroy vm: " + vm.getId());
                    accountCleanupNeeded = true;
                } 
            }
            
            // Mark the account's volumes as destroyed
            List volumes = _volumeDao.findDetachedByAccount(accountId);
            for (VolumeVO volume : volumes) {
            	if(volume.getPoolId()==null){
            		accountCleanupNeeded = true;
            	}
            	_storageMgr.destroyVolume(volume);
            }

            // Destroy the account's routers
            List routers = _routerDao.listBy(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of routers (accountId=" + accountId + "): " + routers.size());
            }

            boolean routersCleanedUp = true;
        return success;
            for (DomainRouterVO router : routers) {
                if (!_networkMgr.destroyRouter(router.getId())) {
                    s_logger.error("Unable to destroy router: " + router.getId());
                    routersCleanedUp = false;
                }
            }

            if (routersCleanedUp) {
            	List ips = _publicIpAddressDao.listByAccount(accountId);
            	
                if (s_logger.isDebugEnabled()) {
            		s_logger.debug("Found " + ips.size() + " public IP addresses for account with ID " + accountId);
                }

            	for (IPAddressVO ip : ips) {
            		Long podId = getPodIdForVlan(ip.getVlanDbId());
            		if (podId != null) {
            			continue;//bug 5561 do not release direct attach pod ips until vm is destroyed
            		}
            		if (!_networkMgr.releasePublicIpAddress(User.UID_SYSTEM, ip.getAddress())) {
            			s_logger.error("Unable to release IP: " + ip.getAddress());
                        accountCleanupNeeded = true;
                    } else {
                    	_accountMgr.decrementResourceCount(accountId, ResourceType.public_ip);
                    }
                }
            } else {
            	accountCleanupNeeded = true;
            }
            
            List securityGroups = _securityGroupDao.listByAccountId(accountId);
            if (securityGroups != null) {
                for (SecurityGroupVO securityGroup : securityGroups) {
                    // All vm instances have been destroyed, delete the security group -> instance_id mappings
    public boolean lockUser(LockUserCmd cmd) {
                    SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();
                    sc.addAnd("securityGroupId", SearchCriteria.Op.EQ, securityGroup.getId());
                    _securityGroupVMMapDao.expunge(sc);

                    // now clean the network rules and security groups themselves
                    _networkRuleConfigDao.deleteBySecurityGroup(securityGroup.getId());
                    _securityGroupDao.remove(securityGroup.getId());
                }
            }
            
            // Delete the account's VLANs
            List accountVlans = _vlanDao.listVlansForAccountByType(null, accountId, VlanType.DirectAttached);
            boolean allVlansDeleted = true;
            for (VlanVO vlan : accountVlans) {
            	try {
            		allVlansDeleted = _configMgr.deleteVlanAndPublicIpRange(User.UID_SYSTEM, vlan.getId());
            	} catch (InvalidParameterValueException e) {
            		allVlansDeleted = false;
            	}
            }

            if (!allVlansDeleted) {
            	accountCleanupNeeded = true;
            }
            
            // clean up templates
            List userTemplates = _templateDao.listByAccountId(accountId);
            boolean allTemplatesDeleted = true;
            for (VMTemplateVO template : userTemplates) {
            	try {
            		allTemplatesDeleted = _tmpltMgr.delete(userId, template.getId(), null);
            	} catch (InternalErrorException e) {
            		s_logger.warn("Failed to delete template while removing account: " + template.getName() + " due to: " + e.getMessage());
            		allTemplatesDeleted = false;
            	}
            }
            
            if (!allTemplatesDeleted) {
            	accountCleanupNeeded = true;
            }

            return true;
        } finally {
            s_logger.info("Cleanup for account " + account.getId() + (accountCleanupNeeded ? " is needed." : " is not needed."));
            
            if (accountCleanupNeeded) {
            	_accountDao.markForCleanup(accountId);
            }
        }
    }

    @Override
    public boolean disableUser(long userId) {
        if (userId <= 2) {
    }
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableUser -- invalid user id: " + userId);
            }
            return false;
        }

        return doSetUserStatus(userId, Account.ACCOUNT_STATE_DISABLED);
    }

    @Override
    public boolean enableUser(EnableUserCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long userId = cmd.getId();
    	Account adminAccount = (Account)UserContext.current().getAccountObject();
        boolean success = false;
        
        //Check if user exists in the system
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);
        
        // If the user is a System user, return an error
        Account account = findAccountById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed");
        }

        if ((adminAccount != null) && !isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
        	throw new PermissionDeniedException("Failed to enable user " + userId + ", permission denied.");
        }
        
        success = doSetUserStatus(userId, Account.ACCOUNT_STATE_ENABLED);

        // make sure the account is enabled too
        success = (success && enableAccount(user.getAccountId()));
        
        boolean success = false;
        
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long id = cmd.getId();

        // Check if user with id exists in the system
        User user = _userDao.findById(id);
        if (user == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        } else if (user.getRemoved() != null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        }

        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is a system user, locking is not allowed");
        }

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock user " + id + ", permission denied.");
        }

        // make sure the account is enabled too
        // if the user is either locked already or disabled already, don't change state...only lock currently enabled users
        if (user.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
            // already locked...no-op
            return true;
        } else if (user.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
            success = doSetUserStatus(user.getId(), Account.ACCOUNT_STATE_LOCKED);

            boolean lockAccount = true;
            List allUsersByAccount = _userDao.listByAccount(user.getAccountId());
            for (UserVO oneUser : allUsersByAccount) {
                if (oneUser.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                    lockAccount = false;
                    break;
                }
            }

            if (lockAccount) {
                success = (success && lockAccountInternal(user.getAccountId()));
            }
        } else {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Attempting to lock a non-enabled user, current state is " + user.getState() + " (userId: " + user.getId() + "), locking failed.");
    private boolean doSetUserStatus(long userId, String state) {
        UserVO userForUpdate = _userDao.createForUpdate();
        userForUpdate.setState(state);
        return _userDao.update(Long.valueOf(userId), userForUpdate);
    }

    @Override
    public boolean disableAccount(long accountId) {
        boolean success = false;
        if (accountId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableAccount -- invalid account id: " + accountId);
            }
            return false;
        }

        AccountVO account = _accountDao.findById(accountId);
        if ((account == null) || account.getState().equals(Account.ACCOUNT_STATE_DISABLED)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setState(Account.ACCOUNT_STATE_DISABLED);
            success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);

            success = (success && doDisableAccount(accountId));
        }
        return success;
    }

    @Override
    public boolean updateAccount(UpdateAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getDomainId();
    	String accountName = cmd.getAccountName();
    	String newAccountName = cmd.getNewName();
    	
    	if (newAccountName == null) {
    		newAccountName = accountName;
    	}
    	
        boolean success = false;
        Account account = _accountDao.findAccount(accountName, domainId);

            } else {
        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        if (account.getAccountName().equals(accountName)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setAccountName(newAccountName);
            success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate);
        }
        return success;
    }

    private boolean doDisableAccount(long accountId) {
        List vms = _userVmDao.listByAccountId(accountId);
        boolean success = true;
        for (UserVmVO vm : vms) {
            try {
                success = (success && _vmMgr.stop(vm, 0));
            } catch (AgentUnavailableException aue) {
                s_logger.warn("Agent running on host " + vm.getHostId() + " is unavailable, unable to stop vm " + vm.getName());
                success = false;
            }
        }

        List routers = _routerDao.listBy(accountId);
        for (DomainRouterVO router : routers) {
            success = (success && _networkMgr.stopRouter(router.getId(), 0));
        }

        return success;
    }

    public boolean enableAccount(long accountId) {
        boolean success = false;
        AccountVO acctForUpdate = _accountDao.createForUpdate();
        acctForUpdate.setState(Account.ACCOUNT_STATE_ENABLED);
        success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
        return success;
    }
    	
    
    @Override
    public boolean enableAccount(EnableAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String accountName = cmd.getAccountName();
    	Long domainId = cmd.getDomainId();
        boolean success = false;
        Account account = _accountDao.findActiveAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        success = enableAccount(account.getId());
        return success;
    }

    private boolean lockAccountInternal(long accountId) {
        boolean success = false;
        Account account = _accountDao.findById(accountId);
        if (account != null) {
            if (account.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
                return true; // already locked, no-op
            } else if (account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                AccountVO acctForUpdate = _accountDao.createForUpdate();
                acctForUpdate.setState(Account.ACCOUNT_STATE_LOCKED);
                success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
            } else {
                if (s_logger.isInfoEnabled()) {
                    s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
                }
            }
        } else {
            s_logger.warn("Failed to lock account " + accountId + ", account not found.");
        }
        return success;
    }

    @Override
    public boolean updateUser(UpdateUserCmd cmd) throws InvalidParameterValueException {
        Long id = cmd.getId();
        String apiKey = cmd.getApiKey();
        String firstName = cmd.getFirstname();
    	String email = cmd.getEmail();
    	String lastName = cmd.getLastname();
    	String password = cmd.getPassword();
    	String secretKey = cmd.getSecretKey();
    	String timeZone = cmd.getTimezone();
    	String userName = cmd.getUsername();
    	
        //Input validation
    	UserVO user = _userDao.getUser(id);
    	
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user by id");
        }

        if((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide an api key/secret key pair");
        }
        
        // If the account is an admin type, return an error.  We do not allow this
        Account account = (Account)UserContext.current().getAccountObject();
        
        if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is system account, update is not allowed");
        }

        if (firstName == null) { 
        	firstName = user.getFirstname();
        if (lastName == null) { 
        	lastName = user.getLastname(); 
        }
        if (userName == null) { 
        	userName = user.getUsername();  
        }
        if (password == null) { 
        	password = user.getPassword();
        }
        if (email == null) {
        	email = user.getEmail();
        }
        if (timeZone == null) {
        	timeZone = user.getTimezone();
        }
        if (apiKey == null) {
        	apiKey = user.getApiKey();
        }
        if (secretKey == null) {
        	secretKey = user.getSecretKey();
        }

        Long accountId = user.getAccountId();

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("updating user with id: " + id);
        }
        UserAccount userAccount = _userAccountDao.findById(id);
        try {
        	//check if the apiKey and secretKey are globally unique
        	if (apiKey != null && secretKey != null) {
        		Pair apiKeyOwner = findUserByApiKey(apiKey);

        		if(apiKeyOwner != null) {
        			User usr = apiKeyOwner.first();
        			if (usr.getId() != id) {
            			throw new InvalidParameterValueException("The api key:"+apiKey+" exists in the system for user id:"+id+" ,please provide a unique key");
        			} else {
        				//allow the updation to take place
        			}
        		}
        	}

    private boolean validPassword(String password) {
            _userDao.update(id, userName, password, firstName, lastName, email, accountId, timeZone, apiKey, secretKey);
            EventUtils.saveEvent(new Long(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_UPDATE, "User, " + userName + " for accountId = "
                    + accountId + " domainId = " + userAccount.getDomainId() + " and timezone = "+timeZone + " was updated.");
        } catch (Throwable th) {
            s_logger.error("error updating user", th);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_UPDATE, "Error updating user, " + userName
                    + " for accountId = " + accountId + " and domainId = " + userAccount.getDomainId());
            return false;
        }
        return true;
    }
    
    @Override
    public Pair findUserByApiKey(String apiKey) {
        return _accountDao.findUserAccountByApiKey(apiKey);
    }

    @Override
    public Account getAccount(long accountId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving account with id: " + accountId);
        }

        AccountVO account = _accountDao.findById(Long.valueOf(accountId));
        if (account == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find account with id " + accountId);
            }
            return null;
        }

        return account;
    }
    
    @Override
    public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
    	Long userId = cmd.getId();
    	User user = _userDao.findById(userId);

    	if (user == null) {
           throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find user for id : " + userId);
    	}

    	// generate both an api key and a secret key, update the user table with the keys, return the keys to the user
    	String[] keys = new String[2];
    	keys[0] = createApiKey(userId);
    	keys[1] = createSecretKey(userId);

    	return keys;
    }

    private String createApiKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            Pair userAcct = null;
            int retryLimit = 10;
            do {
                // FIXME: what algorithm should we use for API keys?
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userAcct = _accountDao.findUserAccountByApiKey(encodedKey);
                retryLimit--;
            } while ((userAcct != null) && (retryLimit >= 0));

            if (userAcct != null) {
                return null;
            }
            updatedUser.setApiKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    private String createSecretKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            int retryLimit = 10;
            UserVO userBySecretKey = null;
            do {
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userBySecretKey = _userDao.findUserBySecretKey(encodedKey);
                retryLimit--;
            } while ((userBySecretKey != null) && (retryLimit >= 0));

            if (userBySecretKey != null) {
                return null;
            }

            updatedUser.setSecretKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }

    @Override
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
        SearchCriteria sc = _publicIpAddressDao.createSearchCriteria();

        if (accountId != null)
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        if (zoneId != null)
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        if (vlanDbId != null)
            sc.addAnd("vlanDbId", SearchCriteria.Op.EQ, vlanDbId);
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

        return _publicIpAddressDao.search(sc, null);
    }

    @Override
    public List listPrivateIpAddressesBy(Long podId, Long zoneId) {
        if (podId != null && zoneId != null)
            return _privateIpAddressDao.listByPodIdDcId(podId.longValue(), zoneId.longValue());
        else
            return new ArrayList();
    }

    @Override
    public String generateRandomPassword() {
    	return PasswordGenerator.generateRandomPassword();
    }

    @Override
    public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
    	UserVmVO vm = _userVmDao.findById(vmId);
    	VMTemplateVO iso = _templateDao.findById(isoId);
    	if(attach){
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_ATTACH, "Attaching ISO: "+isoId+" to Vm: "+vmId, startEventId);
    	} else {
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_DETACH, "Detaching ISO: "+isoId+" from Vm: "+vmId, startEventId);
    	}
        boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach);

        if (success) {
            if (attach) {
                vm.setIsoId(iso.getId().longValue());
            } else {
                vm.setIsoId(null);
            }
            _userVmDao.update(vmId, vm);

            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_ATTACH, "Successfully attached ISO: " + iso.getName() + " to VM with ID: " + vmId,
                        null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_DETACH, "Successfully detached ISO from VM with ID: " + vmId, null, startEventId);
            }
        } else {
            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_ATTACH, "Failed to attach ISO: " + iso.getName() + " to VM with ID: " + vmId, null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_DETACH, "Failed to detach ISO from VM with ID: " + vmId, null, startEventId);
            }
        }
        return success;
    }

                }
        for (int i = 0; i < password.length(); i++) {
            if (password.charAt(i) == ' ') {
                return false;
            }
        }
        return true;
    }

    private UserVm deployVirtualMachineImpl(long userId, long accountId, long dataCenterId, long serviceOfferingId, long templateId, Long diskOfferingId,
            String domain, String password, String displayName, String group, String userData, String [] networkGroups, long startEventId, long size) throws ResourceAllocationException, InvalidParameterValueException, InternalErrorException,
            InsufficientStorageCapacityException, PermissionDeniedException, ExecutionException, StorageUnavailableException, ConcurrentOperationException {

    	EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "Deploying Vm", startEventId);
        
        AccountVO account = _accountDao.findById(accountId);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        VMTemplateVO template = _templateDao.findById(templateId);

        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }
        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
			
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        
        // TODO: Checks such as is the user allowed to use the template and purchase the service offering id.

        if (domain == null) {
            domain = "v" + Long.toHexString(accountId) + _domain;
        }

        // Check that the password was passed in and is valid
        if (!template.getEnablePassword()) {
                }
            password = "saved_password";
        }

        if (password == null || password.equals("") || (!validPassword(password))) {
            throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
        }
        List networkGroupVOs = new ArrayList();
        if (networkGroups != null) {
        	for (String groupName: networkGroups) {
        		NetworkGroupVO networkGroupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
        		if (networkGroupVO == null) {
        			throw new InvalidParameterValueException("Network Group " + groupName + " does not exist");
        		}
        		networkGroupVOs.add(networkGroupVO);
        	}
        }
        
        UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dataCenterId);
        if (stats == null) {
            stats = new UserStatisticsVO(account.getId(), dataCenterId);
            _userStatsDao.persist(stats);
        }
        
    	Long vmId = _vmDao.getNextInSequence(Long.class, "id");
    	
        // check if we are within context of async-execution
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("DeployVM acquired a new instance " + vmId + ", update async job-" + job.getId() + " progress status");

            _asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", vmId);
            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, vmId);
        }

        HashMap avoids = new HashMap();

        // Pod allocator now allocate VM based on a reservation style allocation, disable retry here for now
        for (int retry = 0; retry < 1; retry++) {
            String externalIp = null;
            UserVmVO created = null;

            ArrayList a = new ArrayList(avoids.values());
            if (_directAttachNetworkExternalIpAllocator) {
            	try {
            		created = _vmMgr.createDirectlyAttachedVMExternal(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            	} catch (ResourceAllocationException rae) {
            		throw rae;
            	}
            } else {
            	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
            		try {
            			externalIp = _networkMgr.assignSourceNatIpAddress(account, dc, domain, offering, startEventId);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}

            		if (externalIp == null) {
            			throw new InternalErrorException("Unable to allocate a source nat ip address");
            		}

            		if (s_logger.isDebugEnabled()) {
            			s_logger.debug("Source Nat acquired: " + externalIp);
            		}

            		try {
            			created = _vmMgr.createVirtualMachine(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	} else {
            		try {
            			created = _vmMgr.createDirectlyAttachedVM(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	}
            }

            //assign vm to the group
            try{
            	if (group != null) {
            	boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
            	if (!addToGroup) {

            		throw new InternalErrorException("Unable to assing Vm to the group " + group);
            	}
                }
            } catch (Exception ex) {
            	throw new InternalErrorException("Unable to assing Vm to the group " + group);
            }
            
            
            if (created == null) {
                throw new InternalErrorException("Unable to create VM for account (" + accountId + "): " + account.getAccountName());
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM created: " + created.getId() + "-" + created.getName());
            }
            boolean executionExceptionFlag = false;
            boolean storageUnavailableExceptionFlag = false;
            boolean concurrentOperationExceptionFlag = false;
            String executionExceptionMsg= "";
            String storageUnavailableExceptionMsg = "";
            String concurrentOperationExceptionMsg = "";
            UserVmVO started = null;
            if (isIso) {
                String isoPath = _storageMgr.getAbsoluteIsoPath(templateId, dataCenterId);
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, isoPath, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, null, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }

            }

            if (started == null) {
                List> disks = _storageMgr.isStoredOn(created);
                // NOTE: We now destroy a VM if the deploy process fails at any step. We now
                // have a lazy delete so there is still some time to figure out what's wrong.
                _vmMgr.destroyVirtualMachine(userId, created.getId());

                boolean retryCreate = true;
                for (Pair disk : disks) {
                    if (disk.second().isLocal()) {
                        avoids.put(disk.second().getId(), disk.second());
                    } else {
                        retryCreate = false;
                    }
                }

                if (retryCreate) {
                    continue;
                } else if(executionExceptionFlag){
                    throw new ExecutionException(executionExceptionMsg);
                } else if (storageUnavailableExceptionFlag){
                	throw new StorageUnavailableException(storageUnavailableExceptionMsg);
                }else if (concurrentOperationExceptionFlag){
                	throw new ConcurrentOperationException(concurrentOperationExceptionMsg);
                }
                else{
                    throw new InternalErrorException("Unable to start the VM " + created.getId() + "-" + created.getName());
                }
                
            } else {
                if (isIso) {
                    started.setIsoId(templateId);
        // Make sure a valid template ID was specified
                    _userVmDao.update(started.getId(), started);
                    started = _userVmDao.findById(started.getId());
                }

                try {
					_configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null);															
				} catch (InsufficientAddressCapacityException e) {
					s_logger.debug("Unable to assign public IP address pool: " +e.getMessage());					
				}
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM started: " + started.getId() + "-" + started.getName());
            }
            return started;
        }

        return null;
    }

    @Override
    public UserVm deployVirtualMachine(DeployVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException,
                                                               InternalErrorException, InsufficientStorageCapacityException, ExecutionException,
                                                               StorageUnavailableException, ConcurrentOperationException {
        Account ctxAccount = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        long dataCenterId = cmd.getZoneId();
        long serviceOfferingId = cmd.getServiceOfferingId();
        long templateId = cmd.getTemplateId();
        Long diskOfferingId = cmd.getDiskOfferingId();
        String domain = null; // FIXME:  this was hardcoded to null in DeployVMCmd in the old framework, do we need it?
        String password = generateRandomPassword();
        String displayName = cmd.getDisplayName();
        String group = cmd.getGroup();
        String userData = cmd.getUserData();
        String[] networkGroups = null;
        Long sizeObj = cmd.getSize();
        long size = (sizeObj == null) ? 0 : sizeObj;

        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {
                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }

        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for deploying a virtual machine.");
        }

        List netGrpList = cmd.getNetworkGroupList();
        if ((netGrpList != null) && !netGrpList.isEmpty()) {
            networkGroups = netGrpList.toArray(new String[netGrpList.size()]);
        }

    	AccountVO account = _accountDao.findById(accountId);
        if (account == null) {
            throw new InvalidParameterValueException("Unable to find account: " + accountId);
        }

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        if (dc == null) {
            throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
        }

        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        if (offering == null) {
            throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
        }

        VMTemplateVO template = _templateDao.findById(templateId);
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        
        if (isIso && !template.isBootable()) {
        	throw new InvalidParameterValueException("Please specify a bootable ISO.");
        }

        // If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
        // Else, a disk offering is optional, and if present will be used to create the data disk
        DiskOfferingVO diskOffering = null;

        if (diskOfferingId != null) {
        	diskOffering = _diskOfferingDao.findById(diskOfferingId);
        }

        if (isIso && diskOffering == null) {
        	throw new InvalidParameterValueException("Please specify a valid disk offering ID.");
        }

        // validate that the template is usable by the account
        if (!template.isPublicTemplate()) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType()) && ((templateOwner == null) || (templateOwner.longValue() != accountId))) {
                // since the current account is not the owner of the template, check the launch permissions table to see if the
                // account can launch a VM from this template
                LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(templateId, account.getId());
                if (permission == null) {
                    throw new PermissionDeniedException("Account " + account.getAccountName() + " does not have permission to launch instances from template " + template.getName());
                }
            }
        }

        }
        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	if (decodedUserData.length < 1) {
        		throw new InvalidParameterValueException("User data is too short");
        	}
			
        }
        if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized) {
        	_networkGroupMgr.createDefaultNetworkGroup(accountId);
    	}
        
        if (networkGroups != null) {
        	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
        		throw new InvalidParameterValueException("Network groups are not compatible with service offering " + offering.getName());
        	}
        	Set nameSet = new HashSet(); //handle duplicate names -- allowed
        	nameSet.addAll(Arrays.asList(networkGroups));
        	nameSet.add(NetworkGroupManager.DEFAULT_GROUP_NAME);
        	networkGroups = nameSet.toArray(new String[nameSet.size()]);
        	List networkGroupVOs = _networkSecurityGroupDao.findByAccountAndNames(accountId, networkGroups);
        	if (networkGroupVOs.size() != nameSet.size()) {
        		throw new InvalidParameterValueException("Some network group names do not exist");
        	}
        } else { //create a default group if necessary
        	if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized && _networkGroupsEnabled) {
        		networkGroups = new String[]{NetworkGroupManager.DEFAULT_GROUP_NAME};
        	}
        }

        // FIXME:  this really needs to be invoked when the job is scheduled by the framework, so commands need a callback for
        //         specifying event details that they are tracking...
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "deploying Vm");

        try {
            return deployVirtualMachineImpl(userId, accountId, dataCenterId, serviceOfferingId, templateId, diskOfferingId, domain, password, displayName, group, userData, networkGroups, eventId, size);
        } catch (ResourceAllocationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (ExecutionException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_HOST_LICENSE_EXPIRED", null, eventId);
            throw e;
        } catch (InvalidParameterValueException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INVALID_PARAM_ERROR", null, eventId);
            throw e;
        } catch (InternalErrorException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch (InsufficientStorageCapacityException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (PermissionDeniedException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: ACCOUNT_ERROR", null, eventId);
            throw e;
        } catch (ConcurrentOperationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch(Exception e) {
            s_logger.warn("Unable to deploy VM : " + e.getMessage(), e);
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw new CloudRuntimeException("Unable to deploy VM : " + e.getMessage());
        }
    }

    @Override
    public DomainRouterVO findDomainRouterBy(long accountId, long dataCenterId) {
        return _routerDao.findBy(accountId, dataCenterId);
    }

    @Override
    public DomainRouterVO findDomainRouterById(long domainRouterId) {
        return _routerDao.findById(domainRouterId);
    }

    @Override
    public List listDataCenters(ListZonesByCmd cmd) {
        List dcs = _dcDao.listAll();

        Account account = (Account)UserContext.current().getAccountObject();
        Boolean available = cmd.isAvailable();
        if (account != null) {
            if ((available != null) && Boolean.FALSE.equals(available)) {
                List routers = _routerDao.listBy(account.getId());
                for (Iterator iter = dcs.iterator(); iter.hasNext();) {
                    DataCenterVO dc = iter.next();
                    boolean found = false;
                    for (DomainRouterVO router : routers) {
                        if (dc.getId() == router.getDataCenterId()) {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        iter.remove();
                }
            }
        }

        return dcs;
    }

    @Override
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }

    @Override

        }
    public long getId() {
        return MacAddress.getMacAddress().toLong();
    }

    protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {

        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("publicPort is an invalid value");
        }
        if (!NetUtils.isValidPort(privatePort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");
        }

//        s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
//        if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//            throw new InvalidParameterValueException("Invalid private ip address");
//        }
        if (!NetUtils.isValidProto(proto)) {
            throw new InvalidParameterValueException("Invalid protocol");
        }
    }

    @Override
    @DB
    public void assignSecurityGroup(AssignPortForwardingServiceCmd cmd) throws PermissionDeniedException,
            NetworkRuleConflictException, InvalidParameterValueException, InternalErrorException {
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	Long securityGroupId = cmd.getId();
    	List sgIdList = cmd.getIds();
    	String publicIp = cmd.getPublicIp();
    	Long vmId = cmd.getVirtualMachineId();
    	
    	//Verify input parameters
        if ((securityGroupId == null) && (sgIdList == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }


        if (userId == null) {
            userId = Long.valueOf(1);
        }

        List validateSGList = null;
        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = findAccountById(validatedAccountId);
                if (!isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }
    	
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            s_logger.warn("Unable to find virtual machine with id " + vmId);
            throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
        }
        long startEventId = EventUtils.saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "applying port forwarding service for Vm with Id: "+vmId);
    	
        boolean locked = false;
        Transaction txn = Transaction.currentTxn();
        try {
            EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "Applying port forwarding service for Vm with Id: "+vmId, startEventId);
            State vmState = userVm.getState();
            switch (vmState) {
            case Destroyed:
            case Error:
            case Expunging:
                    newFwRule.setPublicPort(netRule.getPublicPort());
            case Unknown:
                throw new InvalidParameterValueException("Unable to assign port forwarding service(s) '"
                        + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "' to virtual machine " + vmId
                        + " due to virtual machine being in an invalid state for assigning a port forwarding service (" + vmState + ")");
            }

            // sanity check that the vm can be applied to the load balancer
            ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
            if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                }

                throw new InvalidParameterValueException("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }
            
            DomainRouterVO router = null;
            if (userVm.getDomainRouterId() != null)
            	router = _routerDao.findById(userVm.getDomainRouterId());
            if (router == null) {
                s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine " + userVm.toString());
                throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + vmId);
            }

            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;

            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User does not own supplied address");
            }

            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new InvalidParameterValueException("Invalid IP address " + publicIp + " for applying port forwarding services, the IP address is not in a 'virtual network' vlan.");
            }

            txn.start();

            if (securityGroupId == null) {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on list passed in
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                {
                    // Save and create the event
                    String description;
                    String type = EventTypes.EVENT_NET_RULE_DELETE;
                    String level = EventVO.LEVEL_INFO;

                    for (FirewallRuleVO fwRule : fwRulesToRemove) {
                        fwRule.setEnabled(false); // disable rule for sending to the agent
                        _firewallRulesDao.remove(fwRule.getId()); // remove the rule from the database

                        description = "deleted ip forwarding rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                                + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                        EventUtils.saveEvent(userId, userVm.getAccountId(), level, type, description);
                    }
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);
                if ((updatedRules != null) && (updatedRules.size() != fwRulesToRemove.size())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to clean up all port forwarding service rules for public IP " + publicIp + " and guest vm " + userVm.getName()
                                + " while applying port forwarding service(s) '" + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "'"
                                + " -- intended to remove " + fwRulesToRemove.size() + " rules, removd " + ((updatedRules == null) ? "null" : updatedRules.size()) + " rules.");
                List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    boolean success = _securityGroupVMMapDao.remove(sgVmMapping.getId());

                    SecurityGroupVO securityGroup = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());

                    // save off an event for removing the security group
                    EventVO event = new EventVO();
                    event.setUserId(userId);
                    event.setAccountId(userVm.getAccountId());
                    event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
                    String sgRemoveLevel = EventVO.LEVEL_INFO;
                    String sgRemoveDesc = "Successfully removed ";
                    if (!success) {
                        sgRemoveLevel = EventVO.LEVEL_ERROR;
                        sgRemoveDesc = "Failed to remove ";
                    }
                    String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
                    event.setParameters(params);
                    event.setDescription(sgRemoveDesc + "port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
                    event.setLevel(sgRemoveLevel);
                    _eventDao.persist(event);
                }
            } else {
                List existingVMMaps = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId.longValue());
                if ((existingVMMaps != null) && !existingVMMaps.isEmpty()) {
                    for (SecurityGroupVMMapVO existingVMMap : existingVMMaps) {
                        if (existingVMMap.getInstanceId() == userVm.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("port forwarding service " + securityGroupId + " is already applied to virtual machine " + userVm.toString() + ", skipping assignment.");
                            }
                            return;
                        }
                    }
                }
            }

            List finalSecurityGroupIdList = new ArrayList();
            if (securityGroupId != null) {
                finalSecurityGroupIdList.add(securityGroupId);
            } else {
                finalSecurityGroupIdList.addAll(sgIdList);
            }

            for (Long sgId : finalSecurityGroupIdList) {
                if (sgId.longValue() == 0) {
                    // group id of 0 means to remove all groups, which we just did above
                    break;
                }

                SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(sgId));
                if (securityGroup == null) {
                    s_logger.warn("Unable to find port forwarding service with id " + sgId);
                    throw new InvalidParameterValueException("Unable to find port forwarding service with id " + sgId);
                }

                if (!_domainDao.isChildDomain(securityGroup.getDomainId(), userVm.getDomainId())) {
                    s_logger.warn("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                    throw new InvalidParameterValueException("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(publicIp);
                Map> mappedPublicPorts = new HashMap>();

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
                    }
                }

                List loadBalancers = _loadBalancerDao.listByIpAddress(publicIp);
                if (loadBalancers != null) {
                    for (LoadBalancerVO loadBalancer : loadBalancers) {
                        // load balancers don't have to be applied to an
                        // instance for there to be a conflict on the load
                        // balancers ip/port, so just
                        // map the public port to a pair of empty strings
                        mappedPublicPorts.put(loadBalancer.getPublicPort(), new Pair("", ""));
                    }
                }

                List firewallRulesToApply = new ArrayList();
                List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgId);
                for (NetworkRuleConfigVO netRule : netRules) {
                    Pair privateIpPort = mappedPublicPorts.get(netRule.getPublicPort());
                    if (privateIpPort != null) {
                        if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(netRule.getPrivatePort())) {
                            continue; // already mapped
                        } else {
                            throw new NetworkRuleConflictException("An existing service rule for " + publicIp + ":" + netRule.getPublicPort()
                                    + " already exists, found while trying to apply service rule " + netRule.getId() + " from port forwarding service " + securityGroup.getName() + ".");
                        }
                    }

                    FirewallRuleVO newFwRule = new FirewallRuleVO();
                    newFwRule.setEnabled(true);
                    newFwRule.setForwarding(true);
                    newFwRule.setPrivatePort(netRule.getPrivatePort());
                    newFwRule.setProtocol(netRule.getProtocol());

                    newFwRule.setPublicIpAddress(publicIp);
                    newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                    newFwRule.setGroupId(netRule.getSecurityGroupId());

                    firewallRulesToApply.add(newFwRule);
                    _firewallRulesDao.persist(newFwRule);

                    String description = "created new ip forwarding rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                            + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
                }

                // now that individual rules have been created from the security group, save the security group mapping for this ip/vm instance
                SecurityGroupVMMapVO sgVmMap = new SecurityGroupVMMapVO(sgId, publicIp, vmId);
                _securityGroupVMMapDao.persist(sgVmMap);

                // Save off information for the event that the security group was applied
                EventVO event = new EventVO();
                event.setUserId(userId);
                event.setAccountId(userVm.getAccountId());
                event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY);
                event.setStartId(startEventId);
                event.setDescription("Successfully applied port forwarding service " + securityGroup.getName() + " to virtual machine " + userVm.getName());
                String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId+"\nnumRules="+firewallRulesToApply.size()+"\ndcId="+userVm.getDataCenterId();
                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
                _eventDao.persist(event);

                _networkMgr.updateFirewallRules(publicIp, firewallRulesToApply, router);
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public void removeSecurityGroup(RemovePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	
    	Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long securityGroupId = cmd.getId();
        String publicIp = cmd.getPublicIp();
        Long vmId = cmd.getVirtualMachineId();
        
        //verify input parameters
        SecurityGroupVO securityG = _securityGroupDao.findById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
            }
        }
        
        UserVmVO vmInstance = findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing port forwarding services for Vm with Id: "+vmId);

        /*TODO : ASK KRIS AS TO WHAT DO WE DO WITH THIS PART IN THE EXECUTOR CODE
        UserVmVO userVm = userVmDao.findById(param.getInstanceId());
        if(userVm == null)
        	return null;
        
        if (userVm.getDomainRouterId() == null) {
        	return null;
        } else
        	return routerDao.findById(userVm.getDomainRouterId());
	    */
        removeSecurityGroup(userId, securityGroupId, publicIp, vmId, eventId);
    }
    
    @Override
    @DB
    public void removeSecurityGroup(long userId, long securityGroupId, String publicIp, long vmId, long startEventId) throws InvalidParameterValueException, PermissionDeniedException {
        // This gets complicated with overlapping rules. As an example:
        // security group 1 has the following port mappings: 22->22 on TCP,
        // 23->23 on TCP, 80->8080 on TCP
        // security group 2 has the following port mappings: 22->22 on TCP,
        // 7891->7891 on TCP
        // User assigns group 1 & 2 on 192.168.10.120 to vm 1
        // Later, user removed group 1 from 192.168.10.120 and vm 1
        // Final valid port mappings should be 22->22 and 7891->7891 which both
        // come from security group 2. The mapping
        // for port 22 should not be removed.
        boolean locked = false;
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Unable to find vm: " + vmId);
        }
        EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "Removing port forwarding services for Vm with Id: "+vmId, startEventId);
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
            throw new InvalidParameterValueException("Unable to find port forwarding service: " + securityGroupId);
        }

        DomainRouterVO router = null;
        if (userVm.getDomainRouterId() != null)
        	router = _routerDao.findById(userVm.getDomainRouterId());
        if (router == null) {
            throw new InvalidParameterValueException("Unable to find router for ip address: " + publicIp);
        }

        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe
                // for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User/account does not own supplied address");
            }

            txn.start();

            // get the account for writing events
            Account account = _accountDao.findById(userVm.getAccountId());
            {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on existing SG mappings
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                for (FirewallRuleVO fwRule : fwRulesToRemove) {
                    fwRule.setEnabled(false);
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "ip forwarding";
                String level = EventVO.LEVEL_INFO;

                for (FirewallRuleVO fwRule : updatedRules) {
                    _firewallRulesDao.remove(fwRule.getId());

                    description = "deleted " + ruleName + " rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                            + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), level, type, description);
                }
            }

            // since we know these groups all pass muster, just keep track
            // of the public ports we are mapping on this public IP and
            // don't duplicate
            List alreadyMappedPorts = new ArrayList();
            List fwRulesToAdd = new ArrayList();
            List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                if (sgVmMapping.getSecurityGroupId() == securityGroupId) {
                    _securityGroupVMMapDao.remove(sgVmMapping.getId());
                } else {
        }
                    List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgVmMapping.getSecurityGroupId());
                    for (NetworkRuleConfigVO netRule : netRules) {
                        if (!alreadyMappedPorts.contains(netRule.getPublicPort())) {
                            FirewallRuleVO newFwRule = new FirewallRuleVO();
                            newFwRule.setEnabled(true);
                            newFwRule.setForwarding(true);
                            newFwRule.setPrivatePort(netRule.getPrivatePort());
                            newFwRule.setProtocol(netRule.getProtocol());
                            newFwRule.setPublicPort(netRule.getPublicPort());
                            newFwRule.setPublicIpAddress(publicIp);
                            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                            newFwRule.setGroupId(netRule.getSecurityGroupId());

                            fwRulesToAdd.add(newFwRule);

                            alreadyMappedPorts.add(netRule.getPublicPort());
                        }
                    }
                }
            }

            for (FirewallRuleVO addedRule : fwRulesToAdd) {
                _firewallRulesDao.persist(addedRule);

                String description = "created new ip forwarding rule [" + addedRule.getPublicIpAddress() + ":" + addedRule.getPublicPort() + "]->["
                        + addedRule.getPrivateIpAddress() + ":" + addedRule.getPrivatePort() + "]" + " " + addedRule.getProtocol();

                EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
            }

            // save off an event for removing the security group
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(userVm.getAccountId());
            event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
            event.setDescription("Successfully removed port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
            event.setLevel(EventVO.LEVEL_INFO);
            String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
            event.setParameters(params);
            _eventDao.persist(event);

            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }


    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
            } else {
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }
        if (domainId != null) {
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object accountName = cmd.getAccountName();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        if (id != null) {
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            }
        } else if (domainId != null) {
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object name = cmd.getServiceOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    @Override
    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object name = cmd.getClusterName();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (state != null) {
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _hostPodDao.search(sc, searchFilter);
    }

    @Override
    public List searchForZones(Criteria c) {
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        if (accountName != null && domainId != null) {
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

        return _vlanDao.search(sc, searchFilter);
    }
    
    @Override
    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        } else {
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);

        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        }
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
        return _launchPermissionDao.listPermittedTemplates(accountId);
    }

    @Override
    public List listPods(long dataCenterId) {
        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }

    @Override
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
    	//verify that template exists

        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
        if (isPublic != null) {
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {
        return _vmInstanceDao.findById(vmId);
    }

    @Override
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    @Override
    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
                }
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.setParameters("createDateG", startDate);
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
            }
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        if (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }


        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	else
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override


    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }
            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
        if (podId != null) {
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

    
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
            if (domainId != null) {
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +

                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
            // validate domainId before proceeding
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
            if (domainId != null) {
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
            }
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
        }
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
        Account account = (Account)UserContext.current().getAccountObject();
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (targetIqn != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
    	} catch (Exception e) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}
	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        	_vmGroupDao.updateVmGroup(groupId, groupName);
        Object id = cmd.getId();
        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
        Object name = cmd.getGroupName();
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
=======
    public boolean recoverVirtualMachine(long vmId) throws ResourceAllocationException, InternalErrorException {
        return _vmMgr.recoverVirtualMachine(vmId);
    }

    @Override
    public boolean upgradeVirtualMachine(long userId, long vmId, long serviceOfferingId,long startEventId) {
        UserVmVO userVm = _userVmDao.findById(vmId);
        saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_VM_UPGRADE, "upgrading service offering on VM : " + userVm.getName(), startEventId);
        boolean success = _vmMgr.upgradeVirtualMachine(vmId, serviceOfferingId);

        String params = "id=" + vmId + "\nvmName=" + userVm.getName() + "\nsoId=" + serviceOfferingId + "\ntId=" + userVm.getTemplateId() + "\ndcId=" + userVm.getDataCenterId();

        if (success) {
            this.saveEvent(userId, userVm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_VM_UPGRADE, "Successfully upgrade service offering on VM : " + userVm.getName(), params, startEventId);
        } else {
            this.saveEvent(userId, userVm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_UPGRADE, "Failed to upgrade service offering on VM : " + userVm.getName(), params, startEventId);
        }
        
        return success;
    }

    @Override
    public long upgradeVirtualMachineAsync(long userId, long vmId, long serviceOfferingId) throws InvalidParameterValueException {
        UpgradeVMParam param = new UpgradeVMParam(userId, vmId, serviceOfferingId);
        Gson gson = GsonHelper.getBuilder().create();
                       
        // Check that the specified VM ID is valid
        UserVmVO vm = _vmDao.findById(vmId);
        if (vm == null) {
        	throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId);
        }
        
        // Check that the specified service offering ID is valid
        ServiceOfferingVO newServiceOffering = _offeringsDao.findById(serviceOfferingId);
        if (newServiceOffering == null) {
        	throw new InvalidParameterValueException("Unable to find a service offering with id " + serviceOfferingId);
        }
        
        // Check that the VM is stopped
        if (!vm.getState().equals(State.Stopped)) {
            s_logger.warn("Unable to upgrade virtual machine " + vm.toString() + " in state " + vm.getState());
            throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vm.toString() + " in state " + vm.getState() + "; make sure the virtual machine is stopped and not in an error state before upgrading.");
        }
        
        // Check if the service offering being upgraded to is what the VM is already running with
        if (vm.getServiceOfferingId() == newServiceOffering.getId()) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Not upgrading vm " + vm.toString() + " since it already has the requested service offering (" + newServiceOffering.getName() + ")");
            }
            
            throw new InvalidParameterValueException("Not upgrading vm " + vm.toString() + " since it already has the requested service offering (" + newServiceOffering.getName() + ")");
        }
        
        // Check that the service offering being upgraded to has the same Guest IP type as the VM's current service offering
    @Override
        ServiceOfferingVO currentServiceOffering = _offeringsDao.findById(vm.getServiceOfferingId());
        if (!currentServiceOffering.getGuestIpType().equals(newServiceOffering.getGuestIpType())) {
        	String errorMsg = "The service offering being upgraded to has a guest IP type: " + newServiceOffering.getGuestIpType();
        	errorMsg += ". Please select a service offering with the same guest IP type as the VM's current service offering (" + currentServiceOffering.getGuestIpType() + ").";
        	throw new InvalidParameterValueException(errorMsg);
        }
        
        // Check that the service offering being upgraded to has the same storage pool preference as the VM's current service offering
        if (currentServiceOffering.getUseLocalStorage() != newServiceOffering.getUseLocalStorage()) {
            throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vm.toString() + ", cannot switch between local storage and shared storage service offerings.  Current offering useLocalStorage=" +
                   currentServiceOffering.getUseLocalStorage() + ", target offering useLocalStorage=" + newServiceOffering.getUseLocalStorage());
        }

        // Check that there are enough resources to upgrade the service offering
        if (!_agentMgr.isVirtualMachineUpgradable(vm, newServiceOffering)) {
           throw new InvalidParameterValueException("Unable to upgrade virtual machine, not enough resources available for an offering of " +
                   newServiceOffering.getCpu() + " cpu(s) at " + newServiceOffering.getSpeed() + " Mhz, and " + newServiceOffering.getRamSize() + " MB of memory");
        }
        
        // Check that the service offering being upgraded to has all the tags of the current service offering
        List currentTags = _configMgr.csvTagsToList(currentServiceOffering.getTags());
        List newTags = _configMgr.csvTagsToList(newServiceOffering.getTags());
        if (!newTags.containsAll(currentTags)) {
        	throw new InvalidParameterValueException("Unable to upgrade virtual machine; the new service offering does not have all the tags of the " +
        											 "current service offering. Current service offering tags: " + currentTags + "; " +
        											 "new service offering tags: " + newTags);
        }
        
        long eventId = saveScheduledEvent(userId, vm.getAccountId(), EventTypes.EVENT_VM_UPGRADE, "upgrading Vm with Id: "+vmId);
        param.setEventId(eventId);
        
        AsyncJobVO job = new AsyncJobVO();
    	job.setUserId(UserContext.current().getUserId());
    	job.setAccountId(vm.getAccountId());
        job.setCmd("UpgradeVM");
        job.setCmdInfo(gson.toJson(param));
        job.setCmdOriginator(UpgradeVMCmd.getResultObjectName());
        
        return _asyncMgr.submitAsyncJob(job, true);
    }

    @Override
    public void updateVirtualMachine(long vmId, String displayName, String group, boolean enable, Long userId, long accountId) {
        UserVmVO vm = _userVmDao.findById(vmId);
        if (vm == null) {
            throw new CloudRuntimeException("Unable to find virual machine with id " + vmId);
        }
        
        if (group != null) {
        	boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
        	if (!addToGroup) {
        		throw new CloudRuntimeException("Unable to update Vm with the the group " + group);
        	}
        }

        boolean haEnabled = vm.isHaEnabled();
        _userVmDao.updateVM(vmId, displayName, enable);
        if (haEnabled != enable) {
            String description = null;
            String type = null;
            if (enable) {
                description = "Successfully enabled HA for virtual machine " + vm.getName();
                type = EventTypes.EVENT_VM_ENABLE_HA;
            } else {
                description = "Successfully disabled HA for virtual machine " + vm.getName();
                type = EventTypes.EVENT_VM_DISABLE_HA;
            }
            // create a event for the change in HA Enabled flag
            saveEvent(userId, accountId, EventVO.LEVEL_INFO, type, description, null);
        }
    }
    
    @Override
    public StoragePoolVO updateStoragePool(long poolId, String tags) throws IllegalArgumentException {
    	return _storageMgr.updateStoragePool(poolId, tags);
    }

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public DomainRouter startRouter(long routerId, long startEventId) throws InternalErrorException {
        return _networkMgr.startRouter(routerId, startEventId);
    }
Solution content
    @Override
    		} else {

        }
    }

    @Override
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }

    @Override
    public long getId() {
        return MacAddress.getMacAddress().toLong();
    }

    protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {

        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("publicPort is an invalid value");
        }
        if (!NetUtils.isValidPort(privatePort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");
        }

//        s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
//        if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//            throw new InvalidParameterValueException("Invalid private ip address");
//        }
        if (!NetUtils.isValidProto(proto)) {
            throw new InvalidParameterValueException("Invalid protocol");
        }
    }

    @Override
    @DB
    public void assignSecurityGroup(AssignPortForwardingServiceCmd cmd) throws PermissionDeniedException,
            NetworkRuleConflictException, InvalidParameterValueException, InternalErrorException {
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	Long securityGroupId = cmd.getId();
    	List sgIdList = cmd.getIds();
    	String publicIp = cmd.getPublicIp();
    	Long vmId = cmd.getVirtualMachineId();
    	
    	//Verify input parameters
        if ((securityGroupId == null) && (sgIdList == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }


        if (userId == null) {
            userId = Long.valueOf(1);
        }

        List validateSGList = null;
        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = findAccountById(validatedAccountId);
                if (!isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }
    	
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            s_logger.warn("Unable to find virtual machine with id " + vmId);
            throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
        }
        long startEventId = EventUtils.saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "applying port forwarding service for Vm with Id: "+vmId);
    	
        boolean locked = false;
        Transaction txn = Transaction.currentTxn();
        try {
            EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "Applying port forwarding service for Vm with Id: "+vmId, startEventId);
            State vmState = userVm.getState();
            switch (vmState) {
            case Destroyed:
            case Error:
            case Expunging:
            case Unknown:
                throw new InvalidParameterValueException("Unable to assign port forwarding service(s) '"
                        + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "' to virtual machine " + vmId
                        + " due to virtual machine being in an invalid state for assigning a port forwarding service (" + vmState + ")");
            }

            // sanity check that the vm can be applied to the load balancer
            ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
            if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                }

                throw new InvalidParameterValueException("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }
            
            DomainRouterVO router = null;
            if (userVm.getDomainRouterId() != null)
            	router = _routerDao.findById(userVm.getDomainRouterId());
            if (router == null) {
                s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine " + userVm.toString());
                throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + vmId);
            }

            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;

            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User does not own supplied address");
            }

            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new InvalidParameterValueException("Invalid IP address " + publicIp + " for applying port forwarding services, the IP address is not in a 'virtual network' vlan.");
            }

            txn.start();

            if (securityGroupId == null) {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on list passed in

                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                {
                    // Save and create the event
                    String description;
                    String type = EventTypes.EVENT_NET_RULE_DELETE;
                    String level = EventVO.LEVEL_INFO;

                    for (FirewallRuleVO fwRule : fwRulesToRemove) {
                        fwRule.setEnabled(false); // disable rule for sending to the agent
                        _firewallRulesDao.remove(fwRule.getId()); // remove the rule from the database

                        description = "deleted ip forwarding rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                                + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                        EventUtils.saveEvent(userId, userVm.getAccountId(), level, type, description);
                    }
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);
                if ((updatedRules != null) && (updatedRules.size() != fwRulesToRemove.size())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to clean up all port forwarding service rules for public IP " + publicIp + " and guest vm " + userVm.getName()
                                + " while applying port forwarding service(s) '" + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "'"
                                + " -- intended to remove " + fwRulesToRemove.size() + " rules, removd " + ((updatedRules == null) ? "null" : updatedRules.size()) + " rules.");
                    }
                }

                List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    boolean success = _securityGroupVMMapDao.remove(sgVmMapping.getId());

                    SecurityGroupVO securityGroup = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());

                    // save off an event for removing the security group
                    EventVO event = new EventVO();
                    event.setUserId(userId);
                    event.setAccountId(userVm.getAccountId());
                    event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
                    String sgRemoveLevel = EventVO.LEVEL_INFO;
                    String sgRemoveDesc = "Successfully removed ";
                    if (!success) {
                        sgRemoveLevel = EventVO.LEVEL_ERROR;
                        sgRemoveDesc = "Failed to remove ";
                    }
                    String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
                    event.setParameters(params);
                    event.setDescription(sgRemoveDesc + "port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
                    event.setLevel(sgRemoveLevel);
                    _eventDao.persist(event);
                }
            } else {
                List existingVMMaps = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId.longValue());
                if ((existingVMMaps != null) && !existingVMMaps.isEmpty()) {
                    for (SecurityGroupVMMapVO existingVMMap : existingVMMaps) {
                        if (existingVMMap.getInstanceId() == userVm.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("port forwarding service " + securityGroupId + " is already applied to virtual machine " + userVm.toString() + ", skipping assignment.");
                            }
                            return;
                        }
                    }
                }
            }

            List finalSecurityGroupIdList = new ArrayList();
            if (securityGroupId != null) {
                finalSecurityGroupIdList.add(securityGroupId);
            } else {
                finalSecurityGroupIdList.addAll(sgIdList);
            }

            for (Long sgId : finalSecurityGroupIdList) {
                if (sgId.longValue() == 0) {
                    // group id of 0 means to remove all groups, which we just did above
                    break;
                }

                SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(sgId));
                if (securityGroup == null) {
                    s_logger.warn("Unable to find port forwarding service with id " + sgId);
                    throw new InvalidParameterValueException("Unable to find port forwarding service with id " + sgId);
                }

                if (!_domainDao.isChildDomain(securityGroup.getDomainId(), userVm.getDomainId())) {
                    s_logger.warn("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                    throw new InvalidParameterValueException("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(publicIp);
                Map> mappedPublicPorts = new HashMap>();

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
                    }
                }

                List loadBalancers = _loadBalancerDao.listByIpAddress(publicIp);
                if (loadBalancers != null) {
                    for (LoadBalancerVO loadBalancer : loadBalancers) {
                        // load balancers don't have to be applied to an
                        // instance for there to be a conflict on the load
                        // balancers ip/port, so just
                        // map the public port to a pair of empty strings
                        mappedPublicPorts.put(loadBalancer.getPublicPort(), new Pair("", ""));
                    }
                }

                List firewallRulesToApply = new ArrayList();
                List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgId);
                for (NetworkRuleConfigVO netRule : netRules) {
                    Pair privateIpPort = mappedPublicPorts.get(netRule.getPublicPort());
                    if (privateIpPort != null) {
                        if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(netRule.getPrivatePort())) {
                            continue; // already mapped
                        } else {
                            throw new NetworkRuleConflictException("An existing service rule for " + publicIp + ":" + netRule.getPublicPort()
                                    + " already exists, found while trying to apply service rule " + netRule.getId() + " from port forwarding service " + securityGroup.getName() + ".");
                        }
                    }

                    FirewallRuleVO newFwRule = new FirewallRuleVO();
                    newFwRule.setEnabled(true);
                    newFwRule.setForwarding(true);
                    newFwRule.setPrivatePort(netRule.getPrivatePort());
                    newFwRule.setProtocol(netRule.getProtocol());
                    newFwRule.setPublicPort(netRule.getPublicPort());
                    newFwRule.setPublicIpAddress(publicIp);
                    newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                    newFwRule.setGroupId(netRule.getSecurityGroupId());

                    firewallRulesToApply.add(newFwRule);
                    _firewallRulesDao.persist(newFwRule);

                    String description = "created new ip forwarding rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                            + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
                }

                // now that individual rules have been created from the security group, save the security group mapping for this ip/vm instance
                SecurityGroupVMMapVO sgVmMap = new SecurityGroupVMMapVO(sgId, publicIp, vmId);
                _securityGroupVMMapDao.persist(sgVmMap);

                // Save off information for the event that the security group was applied
                EventVO event = new EventVO();
                event.setUserId(userId);
                event.setAccountId(userVm.getAccountId());
                event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY);
                event.setStartId(startEventId);
                event.setDescription("Successfully applied port forwarding service " + securityGroup.getName() + " to virtual machine " + userVm.getName());
                String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId+"\nnumRules="+firewallRulesToApply.size()+"\ndcId="+userVm.getDataCenterId();
                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
                _eventDao.persist(event);

                _networkMgr.updateFirewallRules(publicIp, firewallRulesToApply, router);
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public void removeSecurityGroup(RemovePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	
    	Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long securityGroupId = cmd.getId();
        String publicIp = cmd.getPublicIp();
        Long vmId = cmd.getVirtualMachineId();
        
        //verify input parameters
        SecurityGroupVO securityG = _securityGroupDao.findById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
            }
        }
        
        UserVmVO vmInstance = findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
            } else {
            throw new CloudRuntimeException("Unhandled exception", ex);
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing port forwarding services for Vm with Id: "+vmId);

        /*TODO : ASK KRIS AS TO WHAT DO WE DO WITH THIS PART IN THE EXECUTOR CODE
        UserVmVO userVm = userVmDao.findById(param.getInstanceId());
        if(userVm == null)
        	return null;
        
        if (userVm.getDomainRouterId() == null) {
        	return null;
        } else
        	return routerDao.findById(userVm.getDomainRouterId());
	    */
        removeSecurityGroup(userId, securityGroupId, publicIp, vmId, eventId);
    }
    
    @Override
    @DB
    public void removeSecurityGroup(long userId, long securityGroupId, String publicIp, long vmId, long startEventId) throws InvalidParameterValueException, PermissionDeniedException {
        // This gets complicated with overlapping rules. As an example:
        // security group 1 has the following port mappings: 22->22 on TCP,
        // 23->23 on TCP, 80->8080 on TCP
    }
        // security group 2 has the following port mappings: 22->22 on TCP,
        // 7891->7891 on TCP
        // User assigns group 1 & 2 on 192.168.10.120 to vm 1
        // Later, user removed group 1 from 192.168.10.120 and vm 1
        // Final valid port mappings should be 22->22 and 7891->7891 which both
        // come from security group 2. The mapping
        // for port 22 should not be removed.
        boolean locked = false;
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Unable to find vm: " + vmId);
        }
        EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "Removing port forwarding services for Vm with Id: "+vmId, startEventId);
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
            throw new InvalidParameterValueException("Unable to find port forwarding service: " + securityGroupId);
        }

        DomainRouterVO router = null;
        if (userVm.getDomainRouterId() != null)
        	router = _routerDao.findById(userVm.getDomainRouterId());
        if (router == null) {
            throw new InvalidParameterValueException("Unable to find router for ip address: " + publicIp);
        }

        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe
                // for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }

            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User/account does not own supplied address");
            }

            txn.start();

            // get the account for writing events
            Account account = _accountDao.findById(userVm.getAccountId());
            {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on existing SG mappings
        } finally {
            if (locked) {
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                for (FirewallRuleVO fwRule : fwRulesToRemove) {
                    fwRule.setEnabled(false);
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "ip forwarding";
                String level = EventVO.LEVEL_INFO;

                for (FirewallRuleVO fwRule : updatedRules) {
                    _firewallRulesDao.remove(fwRule.getId());

                    description = "deleted " + ruleName + " rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                            + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), level, type, description);
                }
            }

            // since we know these groups all pass muster, just keep track
            // of the public ports we are mapping on this public IP and
            // don't duplicate
            List alreadyMappedPorts = new ArrayList();
            List fwRulesToAdd = new ArrayList();
            List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                if (sgVmMapping.getSecurityGroupId() == securityGroupId) {
                    _securityGroupVMMapDao.remove(sgVmMapping.getId());
                } else {
                    List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgVmMapping.getSecurityGroupId());
                    for (NetworkRuleConfigVO netRule : netRules) {
                        if (!alreadyMappedPorts.contains(netRule.getPublicPort())) {
                            FirewallRuleVO newFwRule = new FirewallRuleVO();
                            newFwRule.setEnabled(true);
                            newFwRule.setForwarding(true);
                            newFwRule.setPrivatePort(netRule.getPrivatePort());
                            newFwRule.setProtocol(netRule.getProtocol());
                            newFwRule.setPublicPort(netRule.getPublicPort());
                            newFwRule.setPublicIpAddress(publicIp);
                            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                            newFwRule.setGroupId(netRule.getSecurityGroupId());

                            fwRulesToAdd.add(newFwRule);

                            alreadyMappedPorts.add(netRule.getPublicPort());
                        }
                    }
                }
            }

            for (FirewallRuleVO addedRule : fwRulesToAdd) {
                _firewallRulesDao.persist(addedRule);

                String description = "created new ip forwarding rule [" + addedRule.getPublicIpAddress() + ":" + addedRule.getPublicPort() + "]->["
                        + addedRule.getPrivateIpAddress() + ":" + addedRule.getPrivatePort() + "]" + " " + addedRule.getProtocol();

                EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
            }

            // save off an event for removing the security group
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(userVm.getAccountId());
            event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
            event.setDescription("Successfully removed port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
            event.setLevel(EventVO.LEVEL_INFO);
            String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
            event.setParameters(params);
            _eventDao.persist(event);

            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
            } else {
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }
        if (domainId != null) {
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        }
        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object accountName = cmd.getAccountName();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        Object name = cmd.getClusterName();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            }
        } else if (domainId != null) {
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object name = cmd.getServiceOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    @Override
    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (state != null) {
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _hostPodDao.search(sc, searchFilter);
    }

    @Override
    public List searchForZones(Criteria c) {
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        if (accountName != null && domainId != null) {
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

        return _vlanDao.search(sc, searchFilter);
    }
    
    @Override
    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

    @Override
        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);

        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        }
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
        return _launchPermissionDao.listPermittedTemplates(accountId);
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        } else {
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
    }

    public List listPods(long dataCenterId) {
        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }

    @Override
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
        if (isPublic != null) {
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {
        return _vmInstanceDao.findById(vmId);
    }

    @Override
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    @Override
    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
            if (domainId != null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
                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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
            accountId = account.getId();
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
        if (id != null) {
            sc.setParameters("id", id);
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        }
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
        
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	else
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }
        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }


            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
        
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

    }
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
            }
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
    @Override
            {
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

            }
        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            event.setLevel(EventVO.LEVEL_ERROR);
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        if (account != null) {
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                Account userAccount = _accountDao.findById(lbAcctId);
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
        }
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
			
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                    if (userAccount != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);

                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
			if(hostsInPool!=null && hostsInPool.size()>1)
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
        Long volumeId = cmd.getId();
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public List listDataCenters(ListZonesByCmd cmd) {
        List dcs = _dcDao.listAllActive();

        Account account = (Account)UserContext.current().getAccountObject();
        Boolean available = cmd.isAvailable();
        if (account != null) {
            if ((available != null) && Boolean.FALSE.equals(available)) {
                List routers = _routerDao.listBy(account.getId());
                for (Iterator iter = dcs.iterator(); iter.hasNext();) {
                    DataCenterVO dc = iter.next();
                    boolean found = false;
                    for (DomainRouterVO router : routers) {
                        if (dc.getId() == router.getDataCenterId()) {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        iter.remove();
=======
    public DataCenterVO getDataCenterBy(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public HostPodVO getPodBy(long podId) {
        return _hostPodDao.findById(podId);
    }

    
    @Override
    public List listDataCenters() {
        return _dcDao.listAll();
    }

    @Override
    public List listDataCentersBy(long accountId) {
        List dcs = _dcDao.listAll();
        List routers = _routerDao.listBy(accountId);
        for (Iterator iter = dcs.iterator(); iter.hasNext();) {
            DataCenterVO dc = iter.next();
            boolean found = false;
            for (DomainRouterVO router : routers) {
                if (dc.getId() == router.getDataCenterId()) {
                    found = true;
                    break;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
                }
            }
        }
Solution content
/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */
package com.cloud.server;

import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.alert.AlertVO;
import com.cloud.alert.dao.AlertDao;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
    }
import com.cloud.api.commands.AssignPortForwardingServiceCmd;
import com.cloud.api.commands.CreateDomainCmd;
import com.cloud.api.commands.CreatePortForwardingServiceCmd;
import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd;
import com.cloud.api.commands.CreateUserCmd;
import com.cloud.api.commands.DeleteDomainCmd;
import com.cloud.api.commands.DeletePortForwardingServiceCmd;
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeleteUserCmd;
import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.EnableAccountCmd;
import com.cloud.api.commands.EnableUserCmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapabilitiesCmd;
import com.cloud.api.commands.ListCapacityCmd;
import com.cloud.api.commands.ListCfgsByCmd;
import com.cloud.api.commands.ListClustersCmd;
import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListIsosCmd;
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPortForwardingServiceRulesCmd;
import com.cloud.api.commands.ListPortForwardingServicesByVmCmd;
import com.cloud.api.commands.ListPortForwardingServicesCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListStoragePoolsAndHostsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMGroupsCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.LockAccountCmd;
import com.cloud.api.commands.LockUserCmd;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.RemovePortForwardingServiceCmd;
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateAccountCmd;
import com.cloud.api.commands.UpdateDomainCmd;
import com.cloud.api.commands.UpdateIPForwardingRuleCmd;
import com.cloud.api.commands.UpdateIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplatePermissionsCmd;
import com.cloud.api.commands.UpdateUserCmd;
import com.cloud.api.commands.UpdateVMGroupCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.network.FirewallRuleVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVMMapVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkRuleConfigVO;
import com.cloud.network.SecurityGroupVMMapVO;
import com.cloud.network.SecurityGroupVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.security.NetworkGroupManager;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.network.security.dao.NetworkGroupDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.DiskTemplateVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Snapshot.SnapshotType;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.DiskTemplateDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.LaunchPermissionDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVMMapVO;
        } else {
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.InstanceGroupVMMapDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

public class ManagementServerImpl implements ManagementServer {	
    public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());

    private final AccountManager _accountMgr;
    private final AgentManager _agentMgr;
    private final ConfigurationManager _configMgr;
    private final FirewallRulesDao _firewallRulesDao;
    private final SecurityGroupDao _securityGroupDao;
	private final NetworkGroupDao _networkSecurityGroupDao;
    private final LoadBalancerDao _loadBalancerDao;
    private final NetworkRuleConfigDao _networkRuleConfigDao;
    private final SecurityGroupVMMapDao _securityGroupVMMapDao;
    private final IPAddressDao _publicIpAddressDao;
    private final DataCenterIpAddressDaoImpl _privateIpAddressDao;
    private final LoadBalancerVMMapDao _loadBalancerVMMapDao;
    private final DomainRouterDao _routerDao;
    private final ConsoleProxyDao _consoleProxyDao;
    private final ClusterDao _clusterDao;
    private final SecondaryStorageVmDao _secStorageVmDao;
    private final EventDao _eventDao;
    private final DataCenterDao _dcDao;
    private final VlanDao _vlanDao;
    private final AccountVlanMapDao _accountVlanMapDao;
    private final PodVlanMapDao _podVlanMapDao;
    private final HostDao _hostDao;
    private final UserDao _userDao;
    private final UserVmDao _userVmDao;
    private final ConfigurationDao _configDao;
    private final NetworkManager _networkMgr;
    private final UserVmManager _vmMgr;
    private final ConsoleProxyManager _consoleProxyMgr;
    private final SecondaryStorageVmManager _secStorageVmMgr;
    private final ServiceOfferingDao _offeringsDao;
    private final DiskOfferingDao _diskOfferingDao;
    private final VMTemplateDao _templateDao;
    private final LaunchPermissionDao _launchPermissionDao;
    private final DomainDao _domainDao;
    private final AccountDao _accountDao;
    private final ResourceLimitDao _resourceLimitDao;
    private final UserAccountDao _userAccountDao;
    private final AlertDao _alertDao;
    private final CapacityDao _capacityDao;
    private final SnapshotDao _snapshotDao;
    private final SnapshotPolicyDao _snapshotPolicyDao;
    private final GuestOSDao _guestOSDao;
    private final GuestOSCategoryDao _guestOSCategoryDao;
    private final StoragePoolDao _poolDao;
    private final StoragePoolHostDao _poolHostDao;
    private final StorageManager _storageMgr;
    private final UserVmDao _vmDao;

    private final Adapters _userAuthenticators;
    private final HostPodDao _hostPodDao;
    private final UserStatisticsDao _userStatsDao;
    private final VMInstanceDao _vmInstanceDao;
    private final VolumeDao _volumeDao;
    private final DiskTemplateDao _diskTemplateDao;
    private final AlertManager _alertMgr;
    private final AsyncJobDao _jobDao;
    private final AsyncJobManager _asyncMgr;
    private final TemplateManager _tmpltMgr;
    private final SnapshotManager _snapMgr;
    private final NetworkGroupManager _networkGroupMgr;
    private final int _purgeDelay;
    private final boolean _directAttachNetworkExternalIpAllocator;
    private final PreallocatedLunDao _lunDao;
    private final InstanceGroupDao _vmGroupDao;
    private final InstanceGroupVMMapDao _groupVMMapDao;
    private final UploadMonitor _uploadMonitor;
    private final UploadDao _uploadDao;

        _volumeDao = locator.getDao(VolumeDao.class);
    private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
    private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));

    private final StatsCollector _statsCollector;

    private final Map _configs;

    private String _domain;

    private final int _routerRamSize;
    private final int _proxyRamSize;
    private final int _ssRamSize;

    private final Map _availableIdsMap;

	private boolean _networkGroupsEnabled = false;

    private boolean _isHypervisorSnapshotCapable = false;

    protected ManagementServerImpl() {
        ComponentLocator locator = ComponentLocator.getLocator(Name);
        _lunDao = locator.getDao(PreallocatedLunDao.class);
        _configDao = locator.getDao(ConfigurationDao.class);
        _routerDao = locator.getDao(DomainRouterDao.class);
        _eventDao = locator.getDao(EventDao.class);
        _dcDao = locator.getDao(DataCenterDao.class);
        _vlanDao = locator.getDao(VlanDao.class);
        _accountVlanMapDao = locator.getDao(AccountVlanMapDao.class);
        _podVlanMapDao = locator.getDao(PodVlanMapDao.class);
        _hostDao = locator.getDao(HostDao.class);
        _hostPodDao = locator.getDao(HostPodDao.class);
        _jobDao = locator.getDao(AsyncJobDao.class);
        _clusterDao = locator.getDao(ClusterDao.class);

        _accountMgr = locator.getManager(AccountManager.class);
        _agentMgr = locator.getManager(AgentManager.class);
        _configMgr = locator.getManager(ConfigurationManager.class);
        _networkMgr = locator.getManager(NetworkManager.class);
        _vmMgr = locator.getManager(UserVmManager.class);
        _consoleProxyMgr = locator.getManager(ConsoleProxyManager.class);
        _secStorageVmMgr = locator.getManager(SecondaryStorageVmManager.class);
        _storageMgr = locator.getManager(StorageManager.class);
        _firewallRulesDao = locator.getDao(FirewallRulesDao.class);
        _securityGroupDao = locator.getDao(SecurityGroupDao.class);
        _networkSecurityGroupDao  = locator.getDao(NetworkGroupDao.class);
        _loadBalancerDao = locator.getDao(LoadBalancerDao.class);
        _networkRuleConfigDao = locator.getDao(NetworkRuleConfigDao.class);
        _securityGroupVMMapDao = locator.getDao(SecurityGroupVMMapDao.class);
        _publicIpAddressDao = locator.getDao(IPAddressDao.class);
        _privateIpAddressDao = locator.getDao(DataCenterIpAddressDaoImpl.class);
        _loadBalancerVMMapDao = locator.getDao(LoadBalancerVMMapDao.class);
        _consoleProxyDao = locator.getDao(ConsoleProxyDao.class);
        _secStorageVmDao = locator.getDao(SecondaryStorageVmDao.class);
        _userDao = locator.getDao(UserDao.class);
        _userVmDao = locator.getDao(UserVmDao.class);
        _offeringsDao = locator.getDao(ServiceOfferingDao.class);
        _diskOfferingDao = locator.getDao(DiskOfferingDao.class);
        _templateDao = locator.getDao(VMTemplateDao.class);
        _launchPermissionDao = locator.getDao(LaunchPermissionDao.class);
        _domainDao = locator.getDao(DomainDao.class);
        _accountDao = locator.getDao(AccountDao.class);
        _resourceLimitDao = locator.getDao(ResourceLimitDao.class);
        _userAccountDao = locator.getDao(UserAccountDao.class);
        _alertDao = locator.getDao(AlertDao.class);
        _capacityDao = locator.getDao(CapacityDao.class);
        _snapshotDao = locator.getDao(SnapshotDao.class);
        _snapshotPolicyDao = locator.getDao(SnapshotPolicyDao.class);
        _guestOSDao = locator.getDao(GuestOSDao.class);
        _guestOSCategoryDao = locator.getDao(GuestOSCategoryDao.class);
        _poolDao = locator.getDao(StoragePoolDao.class);
        _poolHostDao = locator.getDao(StoragePoolHostDao.class);
        _vmDao = locator.getDao(UserVmDao.class);
        _vmGroupDao = locator.getDao(InstanceGroupDao.class);
        _groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class);
        _uploadDao = locator.getDao(UploadDao.class);

        _configs = _configDao.getConfiguration();
        _userStatsDao = locator.getDao(UserStatisticsDao.class);
        _vmInstanceDao = locator.getDao(VMInstanceDao.class);
        _diskTemplateDao = locator.getDao(DiskTemplateDao.class);
        _alertMgr = locator.getManager(AlertManager.class);
        _asyncMgr = locator.getManager(AsyncJobManager.class);
        _tmpltMgr = locator.getManager(TemplateManager.class);
        _snapMgr = locator.getManager(SnapshotManager.class);
        _networkGroupMgr = locator.getManager(NetworkGroupManager.class);
        _uploadMonitor = locator.getManager(UploadMonitor.class);                
        
        _userAuthenticators = locator.getAdapters(UserAuthenticator.class);
        if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
            s_logger.error("Unable to find an user authenticator.");
        }

        _domain = _configs.get("domain");
        if (_domain == null) {
            _domain = ".myvm.com";
        }
        if (!_domain.startsWith(".")) {
            _domain = "." + _domain;
        }

        String value = _configs.get("account.cleanup.interval");
        int cleanup = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour.

        // Parse the max number of UserVMs and public IPs from server-setup.xml,
        // and set them in the right places
        _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
        _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
        _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);

        _directAttachNetworkExternalIpAllocator =
        										Boolean.parseBoolean(_configs.get("direct.attach.network.externalIpAllocator.enabled"));
        
        _statsCollector = StatsCollector.getInstance(_configs);
        _executor.scheduleAtFixedRate(new AccountCleanupTask(), cleanup, cleanup, TimeUnit.SECONDS);

        _purgeDelay = NumbersUtil.parseInt(_configs.get("event.purge.delay"), 0);
        if(_purgeDelay != 0){
            _eventExecutor.scheduleAtFixedRate(new EventPurgeTask(), cleanup, cleanup, TimeUnit.SECONDS);
        }
        
        String[] availableIds = TimeZone.getAvailableIDs();
        _availableIdsMap = new HashMap(availableIds.length);
        for (String id: availableIds) {
            _availableIdsMap.put(id, true);
        }
        String enabled =_configDao.getValue("direct.attach.network.groups.enabled");
		if ("true".equalsIgnoreCase(enabled)) {
			_networkGroupsEnabled = true;
		}
 		
		String hypervisorType = _configDao.getValue("hypervisor.type");
        _isHypervisorSnapshotCapable  = hypervisorType.equals(Hypervisor.Type.XenServer.name());
    }

    protected Map getConfigs() {
        return _configs;
    }

    @Override
    public StorageStats getStorageStatistics(long hostId) {
        return _statsCollector.getStorageStats(hostId);
    }
    
    @Override
    public PreallocatedLunVO registerPreallocatedLun(RegisterPreallocatedLunCmd cmd) {
        Long zoneId = cmd.getZoneId();
        String portal = cmd.getPortal();
        String targetIqn = cmd.getTargetIqn();
        Integer lun = cmd.getLun();
        Long size = cmd.getDiskSize();
        String t = cmd.getTags();

        String[] tags = null;
        if (t != null) {
            tags = t.split(",");
            for (int i = 0; i < tags.length; i++) {
                tags[i] = tags[i].trim();
            }
        } else {
            tags = new String[0];
        }
        
        PreallocatedLunVO vo = new PreallocatedLunVO(zoneId, portal, targetIqn, lun, size);
        return _lunDao.persist(vo, tags);
    }
    
    @Override
    public boolean unregisterPreallocatedLun(DeletePreallocatedLunCmd cmd) throws IllegalArgumentException {
        Long id = cmd.getId();
    	PreallocatedLunVO lun = null;
    	if ((lun = _lunDao.findById(id)) == null) {
    		throw new IllegalArgumentException("Unable to find a LUN with ID " + id);
    	}
    	
    	if (lun.getTaken() != null) {
    		throw new IllegalArgumentException("The LUN is currently in use and cannot be deleted.");
    	}
    	
        return _lunDao.delete(id);
    }

    @Override
    public VolumeStats[] getVolumeStatistics(long[] volIds) {
        return _statsCollector.getVolumeStats(volIds);
    }

    @Override
    public UserAccount createUser(CreateUserCmd cmd) {
        Long accountId = null;
        String username = cmd.getUsername();
        String password = cmd.getPassword();
        String firstName = cmd.getFirstname();
        String lastName = cmd.getLastname();
        Long domainId = cmd.getDomainId();
        String email = cmd.getEmail();
        String timezone = cmd.getTimezone();
        String accountName = cmd.getAccountName();
        short userType = cmd.getAccountType().shortValue();
        try {
            if (accountName == null) {
                accountName = username;
            }
            if (domainId == null) {
                domainId = DomainVO.ROOT_DOMAIN;
            }

            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account != null) {
                if (account.getType() != userType) {
                    throw new CloudRuntimeException("Account " + accountName + " is not the correct account type for user " + username);
                }
                accountId = account.getId();
            }

            if (!_userAccountDao.validateUsernameInDomain(username, domainId)) {
                throw new CloudRuntimeException("The user " + username + " already exists in domain " + domainId);
            }

            if (accountId == null) {
                if ((userType < Account.ACCOUNT_TYPE_NORMAL) || (userType > Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given; unable to create user");
                }

                // create a new account for the user
                AccountVO newAccount = new AccountVO();
                if (domainId == null) {
                    // root domain is default
                    domainId = DomainVO.ROOT_DOMAIN;
                }

                if ((domainId != DomainVO.ROOT_DOMAIN) && (userType == Account.ACCOUNT_TYPE_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given for an account in domain " + domainId + "; unable to create user.");
                }

                newAccount.setAccountName(accountName);
                newAccount.setDomainId(domainId);
                newAccount.setType(userType);
                newAccount.setState("enabled");
                newAccount = _accountDao.persist(newAccount);
                accountId = newAccount.getId();
            }

            if (accountId == null) {
                throw new CloudRuntimeException("Failed to create account for user: " + username + "; unable to create user");
            }

            UserVO user = new UserVO();
            user.setUsername(username);
            user.setPassword(password);
            user.setState("enabled");
            user.setFirstname(firstName);
            user.setLastname(lastName);
            user.setAccountId(accountId.longValue());
            user.setEmail(email);
            user.setTimezone(timezone);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Creating user: " + username + ", account: " + accountName + " (id:" + accountId + "), domain: " + domainId + " timezone:"+ timezone);
            }

            UserVO dbUser = _userDao.persist(user);
            
            _networkGroupMgr.createDefaultNetworkGroup(accountId);

            if (!user.getPassword().equals(dbUser.getPassword())) {
                throw new CloudRuntimeException("The user " + username + " being creating is using a password that is different than what's in the db");
            }

            EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_CREATE, "User, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId + " was created.");
            return _userAccountDao.findById(dbUser.getId());
        } catch (Exception e) {
        	EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_CREATE, "Error creating user, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId);
            if (e instanceof CloudRuntimeException) {
                s_logger.info("unable to create user: " + e);
            } else {
                s_logger.warn("unknown exception creating user", e);
            }
            throw new CloudRuntimeException(e.getMessage());
        }
    }

    @Override
    public String updateAdminPassword(long userId, String oldPassword, String newPassword) {
        // String old = StringToMD5(oldPassword);
        // User user = getUser(userId);
        // if (old.equals(user.getPassword())) {
        UserVO userVO = _userDao.createForUpdate(userId);
        userVO.setPassword(StringToMD5(newPassword));
        _userDao.update(userId, userVO);
        return newPassword;
        // } else {
        // return null;
        // }

    private String StringToMD5(String string) {
        MessageDigest md5;

        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new CloudRuntimeException("Error", e);
        }

        md5.reset();
        BigInteger pwInt = new BigInteger(1, md5.digest(string.getBytes()));

        // make sure our MD5 hash value is 32 digits long...
        StringBuffer sb = new StringBuffer();
        String pwStr = pwInt.toString(16);
        int padding = 32 - pwStr.length();
        for (int i = 0; i < padding; i++) {
            sb.append('0');
        }
        sb.append(pwStr);
        return sb.toString();
    }

    @Override
    public User getUser(long userId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId);
        }

        UserVO user = _userDao.getUser(userId);
        if (user == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with id " + userId);
            }
            return null;
        }

        return user;
    }

    @Override
    public User getUser(long userId, boolean active) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId + " and active = " + active);
        }

        if (active) {
            return _userDao.getUser(userId);
        } else {
            return _userDao.findById(userId);
        }
    }

    @Override
    public UserAccount getUserAccount(String username, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user: " + username + " in domain " + domainId);
        }

                domainId = userAccount.getDomainId();
        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        return userAccount;
    }

    private UserAccount getUserAccount(String username, String password, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
        }

        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        if (!userAccount.getState().equals("enabled") || !userAccount.getAccountState().equals("enabled")) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("user " + username + " in domain " + domainId + " is disabled/locked (or account is disabled/locked), returning null");
            }
            return null;
        }

        // We only use the first adapter even if multiple have been
        // configured
        Enumeration en = _userAuthenticators.enumeration();
        UserAuthenticator authenticator = en.nextElement();
        boolean authenticated = authenticator.authenticate(username, password, domainId);

        if (authenticated) {
        	return userAccount;
        } else {
        	return null;
        }
    }

    private boolean deleteUserInternal(long userId) {
        UserAccount userAccount = null;
        Long accountId = null;
        String username = null;
        try {
            UserVO user = _userDao.findById(userId);
            if (user == null || user.getRemoved() != null) {
                return true;
            }
            username = user.getUsername();
            boolean result = _userDao.remove(userId);
            if (!result) {
                s_logger.error("Unable to remove the user with id: " + userId + "; username: " + user.getUsername());
                return false;
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("User is removed, id: " + userId + "; username: " + user.getUsername());
            }

            accountId = user.getAccountId();
            userAccount = _userAccountDao.findById(userId);

            List users = _userDao.listByAccount(accountId);
            if (users.size() != 0) {
                s_logger.debug("User (" + userId + "/" + user.getUsername() + ") is deleted but there's still other users in the account so not deleting account.");
                return true;
            }

            result = _accountDao.remove(accountId);
            if (!result) {
                s_logger.error("Unable to delete account " + accountId);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Remove account " + accountId);
            }

            AccountVO account = _accountDao.findById(accountId);
            deleteAccount(account);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "User " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + userAccount.getDomainId() + " was deleted.");
            return true;
        } catch (Exception e) {
            s_logger.error("exception deleting user: " + userId, e);
            long domainId = 0L;
            if (userAccount != null)
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "Error deleting user " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + domainId);
            return false;
        }
    }

    public boolean deleteAccount(AccountVO account) {
        long accountId = account.getId();
        long userId = 1L; // only admins can delete users, pass in userId 1 XXX: Shouldn't it be userId 2.
        boolean accountCleanupNeeded = false;
        
        try {
        	//delete all vm groups belonging to accont
        	List groups = _vmGroupDao.listByAccountId(accountId);
            for (InstanceGroupVO group : groups) {
                if (!_vmMgr.deleteVmGroup(group.getId())) {
                    s_logger.error("Unable to delete group: " + group.getId());
                    accountCleanupNeeded = true;
                } 
            }
        	
            // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
            boolean success = _snapMgr.deleteSnapshotDirsForAccount(accountId);
            if (success) {
                s_logger.debug("Successfully deleted snapshots directories for all volumes under account " + accountId + " across all zones");
            }
            // else, there are no snapshots, hence no directory to delete.
            
            // Destroy the account's VMs
            List vms = _userVmDao.listByAccountId(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of vms (accountId=" + accountId + "): " + vms.size());
            }

            for (UserVmVO vm : vms) {
                if (!_vmMgr.destroyVirtualMachine(userId, vm.getId())) {
                    s_logger.error("Unable to destroy vm: " + vm.getId());
                    accountCleanupNeeded = true;
                } 
            }
            
            // Mark the account's volumes as destroyed
            List volumes = _volumeDao.findDetachedByAccount(accountId);
            for (VolumeVO volume : volumes) {
            	if(volume.getPoolId()==null){
            		accountCleanupNeeded = true;
            	}
            	_storageMgr.destroyVolume(volume);
            }

            // Destroy the account's routers
            List routers = _routerDao.listBy(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of routers (accountId=" + accountId + "): " + routers.size());
            }

            boolean routersCleanedUp = true;
            for (DomainRouterVO router : routers) {
                if (!_networkMgr.destroyRouter(router.getId())) {
                    s_logger.error("Unable to destroy router: " + router.getId());
                    routersCleanedUp = false;
                }
            }

            if (routersCleanedUp) {
            	List ips = _publicIpAddressDao.listByAccount(accountId);
            	
                if (s_logger.isDebugEnabled()) {
            		s_logger.debug("Found " + ips.size() + " public IP addresses for account with ID " + accountId);
                }

            	for (IPAddressVO ip : ips) {
            		Long podId = getPodIdForVlan(ip.getVlanDbId());
            		if (podId != null) {
            			continue;//bug 5561 do not release direct attach pod ips until vm is destroyed
            		}
            		if (!_networkMgr.releasePublicIpAddress(User.UID_SYSTEM, ip.getAddress())) {
            			s_logger.error("Unable to release IP: " + ip.getAddress());
                        accountCleanupNeeded = true;
                    } else {
                    	_accountMgr.decrementResourceCount(accountId, ResourceType.public_ip);
                    }
                }
            } else {
            	accountCleanupNeeded = true;
            }
            
            List securityGroups = _securityGroupDao.listByAccountId(accountId);
            if (securityGroups != null) {
                for (SecurityGroupVO securityGroup : securityGroups) {
                    // All vm instances have been destroyed, delete the security group -> instance_id mappings
                    SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();
                    sc.addAnd("securityGroupId", SearchCriteria.Op.EQ, securityGroup.getId());
                    _securityGroupVMMapDao.expunge(sc);

                    // now clean the network rules and security groups themselves
                    _networkRuleConfigDao.deleteBySecurityGroup(securityGroup.getId());
                    _securityGroupDao.remove(securityGroup.getId());
                }
            }
            
            // Delete the account's VLANs
            List accountVlans = _vlanDao.listVlansForAccountByType(null, accountId, VlanType.DirectAttached);
            boolean allVlansDeleted = true;
            for (VlanVO vlan : accountVlans) {
            	try {
            		allVlansDeleted = _configMgr.deleteVlanAndPublicIpRange(User.UID_SYSTEM, vlan.getId());
            	} catch (InvalidParameterValueException e) {
            		allVlansDeleted = false;
            	}
            }

            if (!allVlansDeleted) {
            	accountCleanupNeeded = true;
            }
            
            // clean up templates
            List userTemplates = _templateDao.listByAccountId(accountId);
            boolean allTemplatesDeleted = true;
            for (VMTemplateVO template : userTemplates) {
            	try {
            		allTemplatesDeleted = _tmpltMgr.delete(userId, template.getId(), null);
            	} catch (InternalErrorException e) {
            		s_logger.warn("Failed to delete template while removing account: " + template.getName() + " due to: " + e.getMessage());
            		allTemplatesDeleted = false;
            	}
            }
            
            if (!allTemplatesDeleted) {
            	accountCleanupNeeded = true;
            }

            return true;
        } finally {
            s_logger.info("Cleanup for account " + account.getId() + (accountCleanupNeeded ? " is needed." : " is not needed."));
            
            if (accountCleanupNeeded) {
            	_accountDao.markForCleanup(accountId);
            }
        }
    }

    @Override
    public boolean disableUser(long userId) {
        if (userId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableUser -- invalid user id: " + userId);
            }
            return false;
        }

        return doSetUserStatus(userId, Account.ACCOUNT_STATE_DISABLED);
    }

    @Override
    public boolean enableUser(EnableUserCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long userId = cmd.getId();
    	Account adminAccount = (Account)UserContext.current().getAccountObject();
        boolean success = false;
        
        //Check if user exists in the system
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);
        
        // If the user is a System user, return an error
        Account account = findAccountById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed");
        }

        if ((adminAccount != null) && !isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
        	throw new PermissionDeniedException("Failed to enable user " + userId + ", permission denied.");
        }
        
        success = doSetUserStatus(userId, Account.ACCOUNT_STATE_ENABLED);

        // make sure the account is enabled too
        success = (success && enableAccount(user.getAccountId()));
        
        return success;
    }

    @Override
    public boolean lockUser(LockUserCmd cmd) {
        boolean success = false;
        
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long id = cmd.getId();

        // Check if user with id exists in the system
        User user = _userDao.findById(id);
        if (user == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        } else if (user.getRemoved() != null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        }

        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is a system user, locking is not allowed");
        }

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock user " + id + ", permission denied.");
        }

        // make sure the account is enabled too
        // if the user is either locked already or disabled already, don't change state...only lock currently enabled users
        if (user.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
            // already locked...no-op
            return true;
        } else if (user.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
            success = doSetUserStatus(user.getId(), Account.ACCOUNT_STATE_LOCKED);

            boolean lockAccount = true;
            List allUsersByAccount = _userDao.listByAccount(user.getAccountId());
            for (UserVO oneUser : allUsersByAccount) {
                if (oneUser.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                    lockAccount = false;
                    break;
                }
            }

            if (lockAccount) {
                success = (success && lockAccountInternal(user.getAccountId()));
            }
        } else {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Attempting to lock a non-enabled user, current state is " + user.getState() + " (userId: " + user.getId() + "), locking failed.");
            }
        }
        return success;
    }

    private boolean doSetUserStatus(long userId, String state) {
        UserVO userForUpdate = _userDao.createForUpdate();
        userForUpdate.setState(state);
        return _userDao.update(Long.valueOf(userId), userForUpdate);
    }

    @Override
    public boolean disableAccount(long accountId) {
        boolean success = false;
        if (accountId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableAccount -- invalid account id: " + accountId);
            }
            return false;
        }

        AccountVO account = _accountDao.findById(accountId);
        if ((account == null) || account.getState().equals(Account.ACCOUNT_STATE_DISABLED)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setState(Account.ACCOUNT_STATE_DISABLED);
            success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);

            success = (success && doDisableAccount(accountId));
        }
        return success;
    }

    @Override
    public boolean updateAccount(UpdateAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getDomainId();
    	String accountName = cmd.getAccountName();
    	String newAccountName = cmd.getNewName();
    	
    	if (newAccountName == null) {
    		newAccountName = accountName;
    	}
    	
        boolean success = false;
        Account account = _accountDao.findAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        if (account.getAccountName().equals(accountName)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setAccountName(newAccountName);
            success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate);
        }
        return success;
    }

    private boolean doDisableAccount(long accountId) {
        List vms = _userVmDao.listByAccountId(accountId);
        boolean success = true;
        for (UserVmVO vm : vms) {
            try {
                success = (success && _vmMgr.stop(vm, 0));
            } catch (AgentUnavailableException aue) {
                s_logger.warn("Agent running on host " + vm.getHostId() + " is unavailable, unable to stop vm " + vm.getName());
                success = false;
            }
        }

        List routers = _routerDao.listBy(accountId);
        for (DomainRouterVO router : routers) {
            success = (success && _networkMgr.stopRouter(router.getId(), 0));
        }

        return success;
    }

    public boolean enableAccount(long accountId) {
        boolean success = false;
        AccountVO acctForUpdate = _accountDao.createForUpdate();
        acctForUpdate.setState(Account.ACCOUNT_STATE_ENABLED);
        success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
        return success;
    }
    	
    
    @Override
    public boolean enableAccount(EnableAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String accountName = cmd.getAccountName();
    	Long domainId = cmd.getDomainId();
        boolean success = false;
        Account account = _accountDao.findActiveAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        	if (apiKey != null && secretKey != null) {
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        success = enableAccount(account.getId());
        return success;
    }

    private boolean lockAccountInternal(long accountId) {
        boolean success = false;
        Account account = _accountDao.findById(accountId);
        if (account != null) {
            if (account.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
                return true; // already locked, no-op
            } else if (account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                AccountVO acctForUpdate = _accountDao.createForUpdate();
                acctForUpdate.setState(Account.ACCOUNT_STATE_LOCKED);
                success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
            } else {
                if (s_logger.isInfoEnabled()) {
                    s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
                }
            }
        } else {
            s_logger.warn("Failed to lock account " + accountId + ", account not found.");
        }
        return success;
    }

    @Override
    public boolean updateUser(UpdateUserCmd cmd) throws InvalidParameterValueException {
        Long id = cmd.getId();
        String apiKey = cmd.getApiKey();
        String firstName = cmd.getFirstname();
    	String email = cmd.getEmail();
    	String lastName = cmd.getLastname();
    	String password = cmd.getPassword();
    	String secretKey = cmd.getSecretKey();
    	String timeZone = cmd.getTimezone();
    	String userName = cmd.getUsername();
    	
        //Input validation
    	UserVO user = _userDao.getUser(id);
    	
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user by id");
        }

        if((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide an api key/secret key pair");
        }
        
        // If the account is an admin type, return an error.  We do not allow this
        Account account = (Account)UserContext.current().getAccountObject();
        
        if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is system account, update is not allowed");
        }

        if (firstName == null) { 
        	firstName = user.getFirstname();
        }
        if (lastName == null) { 
        	lastName = user.getLastname(); 
        }
        if (userName == null) { 
        	userName = user.getUsername();  
        }
        if (password == null) { 
        	password = user.getPassword();
        }
        if (email == null) {
        	email = user.getEmail();
        }
        if (timeZone == null) {
        	timeZone = user.getTimezone();
        }
        if (apiKey == null) {
        	apiKey = user.getApiKey();
        }
        if (secretKey == null) {
        	secretKey = user.getSecretKey();
        }

        Long accountId = user.getAccountId();

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("updating user with id: " + id);
        }
        UserAccount userAccount = _userAccountDao.findById(id);
        try {
        	//check if the apiKey and secretKey are globally unique
        		Pair apiKeyOwner = findUserByApiKey(apiKey);

        		if(apiKeyOwner != null) {
        			User usr = apiKeyOwner.first();
        			if (usr.getId() != id) {
            			throw new InvalidParameterValueException("The api key:"+apiKey+" exists in the system for user id:"+id+" ,please provide a unique key");
        			} else {
        				//allow the updation to take place
        			}
        		}
        	}

            _userDao.update(id, userName, password, firstName, lastName, email, accountId, timeZone, apiKey, secretKey);
            EventUtils.saveEvent(new Long(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_UPDATE, "User, " + userName + " for accountId = "
                    + accountId + " domainId = " + userAccount.getDomainId() + " and timezone = "+timeZone + " was updated.");
        } catch (Throwable th) {
            s_logger.error("error updating user", th);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_UPDATE, "Error updating user, " + userName
                    + " for accountId = " + accountId + " and domainId = " + userAccount.getDomainId());
            return false;
        }
        return true;
    }
    
    @Override
    public Pair findUserByApiKey(String apiKey) {
        return _accountDao.findUserAccountByApiKey(apiKey);
    }

    @Override
    public Account getAccount(long accountId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving account with id: " + accountId);
        }

        AccountVO account = _accountDao.findById(Long.valueOf(accountId));
        if (account == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find account with id " + accountId);
            }
            return null;
        }

        return account;
    }
    
    @Override
    public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
    	Long userId = cmd.getId();
    	User user = _userDao.findById(userId);

    	if (user == null) {
           throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find user for id : " + userId);
    	}

    	// generate both an api key and a secret key, update the user table with the keys, return the keys to the user
    	String[] keys = new String[2];
    	keys[0] = createApiKey(userId);
    	keys[1] = createSecretKey(userId);

    	return keys;
    }

    private String createApiKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            Pair userAcct = null;
            int retryLimit = 10;
            do {
                // FIXME: what algorithm should we use for API keys?
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userAcct = _accountDao.findUserAccountByApiKey(encodedKey);
                retryLimit--;
            } while ((userAcct != null) && (retryLimit >= 0));

            if (userAcct != null) {
                return null;
            }
            updatedUser.setApiKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    private String createSecretKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            int retryLimit = 10;
            UserVO userBySecretKey = null;
            do {
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userBySecretKey = _userDao.findUserBySecretKey(encodedKey);
                retryLimit--;
            } while ((userBySecretKey != null) && (retryLimit >= 0));

            if (userBySecretKey != null) {
                return null;
            }

            updatedUser.setSecretKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }

    @Override
        if (template == null) {
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
        SearchCriteria sc = _publicIpAddressDao.createSearchCriteria();

        if (accountId != null)
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        if (zoneId != null)
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        if (vlanDbId != null)
            sc.addAnd("vlanDbId", SearchCriteria.Op.EQ, vlanDbId);
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

        return _publicIpAddressDao.search(sc, null);
    }

    @Override
    public List listPrivateIpAddressesBy(Long podId, Long zoneId) {
        if (podId != null && zoneId != null)
            return _privateIpAddressDao.listByPodIdDcId(podId.longValue(), zoneId.longValue());
        else
            return new ArrayList();
    }

    @Override
    public String generateRandomPassword() {
    	return PasswordGenerator.generateRandomPassword();
    }

    @Override
    public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
    	UserVmVO vm = _userVmDao.findById(vmId);
    	VMTemplateVO iso = _templateDao.findById(isoId);
    	if(attach){
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_ATTACH, "Attaching ISO: "+isoId+" to Vm: "+vmId, startEventId);
    	} else {
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_DETACH, "Detaching ISO: "+isoId+" from Vm: "+vmId, startEventId);
    	}
        boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach);

        if (success) {
            if (attach) {
                vm.setIsoId(iso.getId().longValue());
            } else {
                vm.setIsoId(null);
            }
            _userVmDao.update(vmId, vm);

            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_ATTACH, "Successfully attached ISO: " + iso.getName() + " to VM with ID: " + vmId,
                        null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_DETACH, "Successfully detached ISO from VM with ID: " + vmId, null, startEventId);
            }
            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_ATTACH, "Failed to attach ISO: " + iso.getName() + " to VM with ID: " + vmId, null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_DETACH, "Failed to detach ISO from VM with ID: " + vmId, null, startEventId);
            }
        }
        return success;
    }

    private boolean validPassword(String password) {
        for (int i = 0; i < password.length(); i++) {
            if (password.charAt(i) == ' ') {
                return false;
            }
        }
        return true;
    }

    private UserVm deployVirtualMachineImpl(long userId, long accountId, long dataCenterId, long serviceOfferingId, long templateId, Long diskOfferingId,
            String domain, String password, String displayName, String group, String userData, String [] networkGroups, long startEventId, long size) throws ResourceAllocationException, InvalidParameterValueException, InternalErrorException,
            InsufficientStorageCapacityException, PermissionDeniedException, ExecutionException, StorageUnavailableException, ConcurrentOperationException {

    	EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "Deploying Vm", startEventId);
        
        AccountVO account = _accountDao.findById(accountId);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        VMTemplateVO template = _templateDao.findById(templateId);

        // Make sure a valid template ID was specified
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }
        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
			
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        
        // TODO: Checks such as is the user allowed to use the template and purchase the service offering id.

        if (domain == null) {
            domain = "v" + Long.toHexString(accountId) + _domain;
        }

        // Check that the password was passed in and is valid
        if (!template.getEnablePassword()) {
            password = "saved_password";
        }

        if (password == null || password.equals("") || (!validPassword(password))) {
            throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
        }
        List networkGroupVOs = new ArrayList();
        if (networkGroups != null) {
        	for (String groupName: networkGroups) {
        		NetworkGroupVO networkGroupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
        		if (networkGroupVO == null) {
        			throw new InvalidParameterValueException("Network Group " + groupName + " does not exist");
        		}
        		networkGroupVOs.add(networkGroupVO);
        	}
        }
        
        UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dataCenterId);
        if (stats == null) {
            stats = new UserStatisticsVO(account.getId(), dataCenterId);
            _userStatsDao.persist(stats);
        }
        
    	Long vmId = _vmDao.getNextInSequence(Long.class, "id");
    	
        // check if we are within context of async-execution
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("DeployVM acquired a new instance " + vmId + ", update async job-" + job.getId() + " progress status");

            _asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", vmId);
            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, vmId);
        }

        HashMap avoids = new HashMap();

        // Pod allocator now allocate VM based on a reservation style allocation, disable retry here for now
        for (int retry = 0; retry < 1; retry++) {
            String externalIp = null;
            UserVmVO created = null;

            ArrayList a = new ArrayList(avoids.values());
            if (_directAttachNetworkExternalIpAllocator) {
            	try {
            		created = _vmMgr.createDirectlyAttachedVMExternal(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            	} catch (ResourceAllocationException rae) {
            		throw rae;
            	}
            } else {
            	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
            		try {
            			externalIp = _networkMgr.assignSourceNatIpAddress(account, dc, domain, offering, startEventId);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}

            		if (externalIp == null) {
            			throw new InternalErrorException("Unable to allocate a source nat ip address");
            		}

            		if (s_logger.isDebugEnabled()) {
            			s_logger.debug("Source Nat acquired: " + externalIp);
            		}

            		try {
            			created = _vmMgr.createVirtualMachine(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	} else {
            		try {
            			created = _vmMgr.createDirectlyAttachedVM(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	}
            }

            //assign vm to the group
            try{
            	if (group != null) {
            	boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
            	if (!addToGroup) {
            		throw new InternalErrorException("Unable to assing Vm to the group " + group);
            	}
                }
            } catch (Exception ex) {
            	throw new InternalErrorException("Unable to assing Vm to the group " + group);
            }
            
            
            if (created == null) {
                throw new InternalErrorException("Unable to create VM for account (" + accountId + "): " + account.getAccountName());
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM created: " + created.getId() + "-" + created.getName());
            }
            boolean executionExceptionFlag = false;
            boolean storageUnavailableExceptionFlag = false;
            boolean concurrentOperationExceptionFlag = false;
            String executionExceptionMsg= "";
            String storageUnavailableExceptionMsg = "";
            String concurrentOperationExceptionMsg = "";
            UserVmVO started = null;
            if (isIso) {
                String isoPath = _storageMgr.getAbsoluteIsoPath(templateId, dataCenterId);
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, isoPath, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }
            } else {
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, null, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }

            }

            if (started == null) {
                List> disks = _storageMgr.isStoredOn(created);
                // NOTE: We now destroy a VM if the deploy process fails at any step. We now
                // have a lazy delete so there is still some time to figure out what's wrong.
                _vmMgr.destroyVirtualMachine(userId, created.getId());

                boolean retryCreate = true;
                for (Pair disk : disks) {
                    if (disk.second().isLocal()) {
                        avoids.put(disk.second().getId(), disk.second());
                    } else {
                        retryCreate = false;
                    }
                }

                if (retryCreate) {
                    continue;
                } else if(executionExceptionFlag){
                    throw new ExecutionException(executionExceptionMsg);
                } else if (storageUnavailableExceptionFlag){
                	throw new StorageUnavailableException(storageUnavailableExceptionMsg);
                }else if (concurrentOperationExceptionFlag){
                	throw new ConcurrentOperationException(concurrentOperationExceptionMsg);
                }
                else{
                    throw new InternalErrorException("Unable to start the VM " + created.getId() + "-" + created.getName());
                }
                
            } else {
                if (isIso) {
                    started.setIsoId(templateId);
                    _userVmDao.update(started.getId(), started);
                    started = _userVmDao.findById(started.getId());
                }

                try {
					_configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null);															
				} catch (InsufficientAddressCapacityException e) {
					s_logger.debug("Unable to assign public IP address pool: " +e.getMessage());					
				}
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM started: " + started.getId() + "-" + started.getName());
            }
            return started;
        }

        return null;
    }

    @Override
    public UserVm deployVirtualMachine(DeployVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException,
                                                               InternalErrorException, InsufficientStorageCapacityException, ExecutionException,
                                                               StorageUnavailableException, ConcurrentOperationException {
        Account ctxAccount = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        long dataCenterId = cmd.getZoneId();
        long serviceOfferingId = cmd.getServiceOfferingId();
        long templateId = cmd.getTemplateId();
        Long diskOfferingId = cmd.getDiskOfferingId();
        String domain = null; // FIXME:  this was hardcoded to null in DeployVMCmd in the old framework, do we need it?
        String password = generateRandomPassword();
        String displayName = cmd.getDisplayName();
        String group = cmd.getGroup();
        String userData = cmd.getUserData();
        String[] networkGroups = null;
        Long sizeObj = cmd.getSize();
        long size = (sizeObj == null) ? 0 : sizeObj;

        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {
                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }

        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for deploying a virtual machine.");
        }

        List netGrpList = cmd.getNetworkGroupList();
        if ((netGrpList != null) && !netGrpList.isEmpty()) {
            networkGroups = netGrpList.toArray(new String[netGrpList.size()]);
        }

    	AccountVO account = _accountDao.findById(accountId);
        if (account == null) {
            throw new InvalidParameterValueException("Unable to find account: " + accountId);
        }

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        if (dc == null) {
            throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
        }

        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        if (offering == null) {
            throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
        }

        VMTemplateVO template = _templateDao.findById(templateId);
        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        
        if (isIso && !template.isBootable()) {
        	throw new InvalidParameterValueException("Please specify a bootable ISO.");
        }

        // If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
        // Else, a disk offering is optional, and if present will be used to create the data disk
        DiskOfferingVO diskOffering = null;

        if (diskOfferingId != null) {
        	diskOffering = _diskOfferingDao.findById(diskOfferingId);
        }

        if (isIso && diskOffering == null) {
        	throw new InvalidParameterValueException("Please specify a valid disk offering ID.");
        }

        // validate that the template is usable by the account
        if (!template.isPublicTemplate()) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType()) && ((templateOwner == null) || (templateOwner.longValue() != accountId))) {
                // since the current account is not the owner of the template, check the launch permissions table to see if the
                // account can launch a VM from this template
                LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(templateId, account.getId());
                if (permission == null) {
                    throw new PermissionDeniedException("Account " + account.getAccountName() + " does not have permission to launch instances from template " + template.getName());
                }
            }
        }

        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	if (decodedUserData.length < 1) {
        		throw new InvalidParameterValueException("User data is too short");
        	}
			
        }
        if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized) {
        	_networkGroupMgr.createDefaultNetworkGroup(accountId);
    	}
        
        if (networkGroups != null) {
        	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
        		throw new InvalidParameterValueException("Network groups are not compatible with service offering " + offering.getName());
        	}
        	Set nameSet = new HashSet(); //handle duplicate names -- allowed
        	nameSet.addAll(Arrays.asList(networkGroups));
        	nameSet.add(NetworkGroupManager.DEFAULT_GROUP_NAME);
        	networkGroups = nameSet.toArray(new String[nameSet.size()]);
        	List networkGroupVOs = _networkSecurityGroupDao.findByAccountAndNames(accountId, networkGroups);
        	if (networkGroupVOs.size() != nameSet.size()) {
        		throw new InvalidParameterValueException("Some network group names do not exist");
        	}
        } else { //create a default group if necessary
        	if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized && _networkGroupsEnabled) {
        		networkGroups = new String[]{NetworkGroupManager.DEFAULT_GROUP_NAME};
        	}
        }

        // FIXME:  this really needs to be invoked when the job is scheduled by the framework, so commands need a callback for
        //         specifying event details that they are tracking...
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "deploying Vm");

        try {
            return deployVirtualMachineImpl(userId, accountId, dataCenterId, serviceOfferingId, templateId, diskOfferingId, domain, password, displayName, group, userData, networkGroups, eventId, size);
        } catch (ResourceAllocationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (ExecutionException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_HOST_LICENSE_EXPIRED", null, eventId);
            throw e;
        } catch (InvalidParameterValueException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INVALID_PARAM_ERROR", null, eventId);
            throw e;
        } catch (InternalErrorException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch (InsufficientStorageCapacityException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            NetworkRuleConflictException, InvalidParameterValueException, InternalErrorException {
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (PermissionDeniedException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: ACCOUNT_ERROR", null, eventId);
            throw e;
        } catch (ConcurrentOperationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch(Exception e) {
            s_logger.warn("Unable to deploy VM : " + e.getMessage(), e);
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw new CloudRuntimeException("Unable to deploy VM : " + e.getMessage());
        }
    }

    @Override
    public DomainRouterVO findDomainRouterBy(long accountId, long dataCenterId) {
        return _routerDao.findBy(accountId, dataCenterId);
    }

    @Override
    public DomainRouterVO findDomainRouterById(long domainRouterId) {
        return _routerDao.findById(domainRouterId);
    }

    @Override
    public List listDataCenters(ListZonesByCmd cmd) {
        List dcs = _dcDao.listAll();

        Account account = (Account)UserContext.current().getAccountObject();
        Boolean available = cmd.isAvailable();
        if (account != null) {
            if ((available != null) && Boolean.FALSE.equals(available)) {
                List routers = _routerDao.listBy(account.getId());
                for (Iterator iter = dcs.iterator(); iter.hasNext();) {
                    DataCenterVO dc = iter.next();
                    boolean found = false;
                    for (DomainRouterVO router : routers) {
                        if (dc.getId() == router.getDataCenterId()) {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        iter.remove();
                }
            }
        }

        return dcs;
    }

    @Override
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }

    @Override
    public long getId() {
        return MacAddress.getMacAddress().toLong();
    }

    protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {

        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("publicPort is an invalid value");
        }
        if (!NetUtils.isValidPort(privatePort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");
        }

//        s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
//        if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//            throw new InvalidParameterValueException("Invalid private ip address");
//        }
        if (!NetUtils.isValidProto(proto)) {
            throw new InvalidParameterValueException("Invalid protocol");
        }
    }

    @Override
    @DB
    public void assignSecurityGroup(AssignPortForwardingServiceCmd cmd) throws PermissionDeniedException,
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	Long securityGroupId = cmd.getId();
    	List sgIdList = cmd.getIds();
    	String publicIp = cmd.getPublicIp();
    	Long vmId = cmd.getVirtualMachineId();
    	
    	//Verify input parameters
        if ((securityGroupId == null) && (sgIdList == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }


        if (userId == null) {
            userId = Long.valueOf(1);
        }

        List validateSGList = null;
        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = findAccountById(validatedAccountId);
                if (!isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }
    	
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            s_logger.warn("Unable to find virtual machine with id " + vmId);
            throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
        }
        long startEventId = EventUtils.saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "applying port forwarding service for Vm with Id: "+vmId);
    	
        boolean locked = false;
        Transaction txn = Transaction.currentTxn();
        try {
            EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "Applying port forwarding service for Vm with Id: "+vmId, startEventId);
            State vmState = userVm.getState();
            switch (vmState) {
            case Destroyed:
            case Error:
            case Expunging:
            case Unknown:
                throw new InvalidParameterValueException("Unable to assign port forwarding service(s) '"
                        + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "' to virtual machine " + vmId
                        + " due to virtual machine being in an invalid state for assigning a port forwarding service (" + vmState + ")");
            }

            // sanity check that the vm can be applied to the load balancer
            ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
            if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                }

                throw new InvalidParameterValueException("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }
            
            DomainRouterVO router = null;
            if (userVm.getDomainRouterId() != null)
            	router = _routerDao.findById(userVm.getDomainRouterId());
            if (router == null) {
                s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine " + userVm.toString());
                throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + vmId);
            }

            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;

            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User does not own supplied address");
            }

            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new InvalidParameterValueException("Invalid IP address " + publicIp + " for applying port forwarding services, the IP address is not in a 'virtual network' vlan.");
            }

            txn.start();

            if (securityGroupId == null) {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on list passed in
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                {
                    // Save and create the event
                    String description;
                    String type = EventTypes.EVENT_NET_RULE_DELETE;
                    String level = EventVO.LEVEL_INFO;

                    for (FirewallRuleVO fwRule : fwRulesToRemove) {
                        fwRule.setEnabled(false); // disable rule for sending to the agent
                        _firewallRulesDao.remove(fwRule.getId()); // remove the rule from the database

                        description = "deleted ip forwarding rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                                + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                        EventUtils.saveEvent(userId, userVm.getAccountId(), level, type, description);
                    }
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);
                if ((updatedRules != null) && (updatedRules.size() != fwRulesToRemove.size())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to clean up all port forwarding service rules for public IP " + publicIp + " and guest vm " + userVm.getName()
                                + " while applying port forwarding service(s) '" + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "'"
                                + " -- intended to remove " + fwRulesToRemove.size() + " rules, removd " + ((updatedRules == null) ? "null" : updatedRules.size()) + " rules.");
                    }
                }

                List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    boolean success = _securityGroupVMMapDao.remove(sgVmMapping.getId());

                    SecurityGroupVO securityGroup = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());

                    // save off an event for removing the security group
                    EventVO event = new EventVO();
                    event.setUserId(userId);
                    event.setAccountId(userVm.getAccountId());
                    event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
                    String sgRemoveLevel = EventVO.LEVEL_INFO;
                    String sgRemoveDesc = "Successfully removed ";
                    if (!success) {
                        sgRemoveLevel = EventVO.LEVEL_ERROR;
                        sgRemoveDesc = "Failed to remove ";
                    }
                    String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
                    event.setParameters(params);
                    event.setDescription(sgRemoveDesc + "port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
                    event.setLevel(sgRemoveLevel);
                    _eventDao.persist(event);
                }
            } else {
                List existingVMMaps = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId.longValue());
                if ((existingVMMaps != null) && !existingVMMaps.isEmpty()) {
                    for (SecurityGroupVMMapVO existingVMMap : existingVMMaps) {
                        if (existingVMMap.getInstanceId() == userVm.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("port forwarding service " + securityGroupId + " is already applied to virtual machine " + userVm.toString() + ", skipping assignment.");
                            }
                            return;
                        }
                    }
                }
            }

            List finalSecurityGroupIdList = new ArrayList();
            if (securityGroupId != null) {
                finalSecurityGroupIdList.add(securityGroupId);
            } else {
                finalSecurityGroupIdList.addAll(sgIdList);
            }

            for (Long sgId : finalSecurityGroupIdList) {
                if (sgId.longValue() == 0) {
                    // group id of 0 means to remove all groups, which we just did above
                    break;
                }

                SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(sgId));
                if (securityGroup == null) {
                    s_logger.warn("Unable to find port forwarding service with id " + sgId);
                    throw new InvalidParameterValueException("Unable to find port forwarding service with id " + sgId);
                }

                if (!_domainDao.isChildDomain(securityGroup.getDomainId(), userVm.getDomainId())) {
                    s_logger.warn("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                    throw new InvalidParameterValueException("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(publicIp);
                Map> mappedPublicPorts = new HashMap>();

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
                    }
                }

                List loadBalancers = _loadBalancerDao.listByIpAddress(publicIp);
                if (loadBalancers != null) {
                    for (LoadBalancerVO loadBalancer : loadBalancers) {
                        // load balancers don't have to be applied to an
                        // instance for there to be a conflict on the load
                        // balancers ip/port, so just
                        // map the public port to a pair of empty strings
                        mappedPublicPorts.put(loadBalancer.getPublicPort(), new Pair("", ""));
                    }
                }

                List firewallRulesToApply = new ArrayList();
                List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgId);
                for (NetworkRuleConfigVO netRule : netRules) {
                    Pair privateIpPort = mappedPublicPorts.get(netRule.getPublicPort());
                    if (privateIpPort != null) {
                        if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(netRule.getPrivatePort())) {
                            continue; // already mapped
                        } else {
                            throw new NetworkRuleConflictException("An existing service rule for " + publicIp + ":" + netRule.getPublicPort()
        	router = _routerDao.findById(userVm.getDomainRouterId());
                                    + " already exists, found while trying to apply service rule " + netRule.getId() + " from port forwarding service " + securityGroup.getName() + ".");
                        }
                    }

                    FirewallRuleVO newFwRule = new FirewallRuleVO();
                    newFwRule.setEnabled(true);
                    newFwRule.setForwarding(true);
                    newFwRule.setPrivatePort(netRule.getPrivatePort());
                    newFwRule.setProtocol(netRule.getProtocol());
                    newFwRule.setPublicPort(netRule.getPublicPort());
                    newFwRule.setPublicIpAddress(publicIp);
                    newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                    newFwRule.setGroupId(netRule.getSecurityGroupId());

                    firewallRulesToApply.add(newFwRule);
                    _firewallRulesDao.persist(newFwRule);

                    String description = "created new ip forwarding rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                            + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
                }

                // now that individual rules have been created from the security group, save the security group mapping for this ip/vm instance
                SecurityGroupVMMapVO sgVmMap = new SecurityGroupVMMapVO(sgId, publicIp, vmId);
                _securityGroupVMMapDao.persist(sgVmMap);

                // Save off information for the event that the security group was applied
                EventVO event = new EventVO();
                event.setUserId(userId);
                event.setAccountId(userVm.getAccountId());
                event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY);
                event.setStartId(startEventId);
                event.setDescription("Successfully applied port forwarding service " + securityGroup.getName() + " to virtual machine " + userVm.getName());
                String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId+"\nnumRules="+firewallRulesToApply.size()+"\ndcId="+userVm.getDataCenterId();
                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
                _eventDao.persist(event);

                _networkMgr.updateFirewallRules(publicIp, firewallRulesToApply, router);
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public void removeSecurityGroup(RemovePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	
    	Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long securityGroupId = cmd.getId();
        String publicIp = cmd.getPublicIp();
        Long vmId = cmd.getVirtualMachineId();
        
        //verify input parameters
        SecurityGroupVO securityG = _securityGroupDao.findById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
        if (router == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
            }
        }
        
        UserVmVO vmInstance = findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
    @Override
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing port forwarding services for Vm with Id: "+vmId);

        /*TODO : ASK KRIS AS TO WHAT DO WE DO WITH THIS PART IN THE EXECUTOR CODE
        UserVmVO userVm = userVmDao.findById(param.getInstanceId());
        if(userVm == null)
        	return null;
        
        if (userVm.getDomainRouterId() == null) {
        	return null;
        } else
        	return routerDao.findById(userVm.getDomainRouterId());
	    */
        removeSecurityGroup(userId, securityGroupId, publicIp, vmId, eventId);
    }
    
    @Override
    @DB
    public void removeSecurityGroup(long userId, long securityGroupId, String publicIp, long vmId, long startEventId) throws InvalidParameterValueException, PermissionDeniedException {
        // This gets complicated with overlapping rules. As an example:
        // security group 1 has the following port mappings: 22->22 on TCP,
        // 23->23 on TCP, 80->8080 on TCP
        // security group 2 has the following port mappings: 22->22 on TCP,
        // 7891->7891 on TCP
        // User assigns group 1 & 2 on 192.168.10.120 to vm 1
        // Later, user removed group 1 from 192.168.10.120 and vm 1
        // Final valid port mappings should be 22->22 and 7891->7891 which both
        // come from security group 2. The mapping
        // for port 22 should not be removed.
        boolean locked = false;
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Unable to find vm: " + vmId);
        }
        EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "Removing port forwarding services for Vm with Id: "+vmId, startEventId);
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
            throw new InvalidParameterValueException("Unable to find port forwarding service: " + securityGroupId);
        }

        DomainRouterVO router = null;
        if (userVm.getDomainRouterId() != null)
            throw new InvalidParameterValueException("Unable to find router for ip address: " + publicIp);
        }

        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe
                // for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }

            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User/account does not own supplied address");
            }

            txn.start();

            // get the account for writing events
            Account account = _accountDao.findById(userVm.getAccountId());
            {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on existing SG mappings
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                for (FirewallRuleVO fwRule : fwRulesToRemove) {
                    fwRule.setEnabled(false);
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "ip forwarding";
                String level = EventVO.LEVEL_INFO;

                for (FirewallRuleVO fwRule : updatedRules) {
                    _firewallRulesDao.remove(fwRule.getId());

                    description = "deleted " + ruleName + " rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                            + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), level, type, description);
                }
            }

            // since we know these groups all pass muster, just keep track
            // of the public ports we are mapping on this public IP and
            // don't duplicate
            List alreadyMappedPorts = new ArrayList();
            List fwRulesToAdd = new ArrayList();
            List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                if (sgVmMapping.getSecurityGroupId() == securityGroupId) {
                    _securityGroupVMMapDao.remove(sgVmMapping.getId());
                } else {
                    List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgVmMapping.getSecurityGroupId());
                    for (NetworkRuleConfigVO netRule : netRules) {
                        if (!alreadyMappedPorts.contains(netRule.getPublicPort())) {
                            FirewallRuleVO newFwRule = new FirewallRuleVO();
                            newFwRule.setEnabled(true);
                            newFwRule.setForwarding(true);
                            newFwRule.setPrivatePort(netRule.getPrivatePort());
                            newFwRule.setProtocol(netRule.getProtocol());
                            newFwRule.setPublicPort(netRule.getPublicPort());
                            newFwRule.setPublicIpAddress(publicIp);
                            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                            newFwRule.setGroupId(netRule.getSecurityGroupId());

                            fwRulesToAdd.add(newFwRule);

                            alreadyMappedPorts.add(netRule.getPublicPort());
                        }
                    }
                }
            }

            for (FirewallRuleVO addedRule : fwRulesToAdd) {
                _firewallRulesDao.persist(addedRule);

                String description = "created new ip forwarding rule [" + addedRule.getPublicIpAddress() + ":" + addedRule.getPublicPort() + "]->["
                        + addedRule.getPrivateIpAddress() + ":" + addedRule.getPrivatePort() + "]" + " " + addedRule.getProtocol();

                EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
            }

            // save off an event for removing the security group
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(userVm.getAccountId());
            event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
            event.setDescription("Successfully removed port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
            event.setLevel(EventVO.LEVEL_INFO);
            String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
            event.setParameters(params);
            _eventDao.persist(event);

            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
            } else {
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }
        if (domainId != null) {
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
        Object accountName = cmd.getAccountName();
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            }
        } else if (domainId != null) {
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object name = cmd.getServiceOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    @Override
    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object name = cmd.getClusterName();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (state != null) {
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _hostPodDao.search(sc, searchFilter);
    }

    @Override
    public List searchForZones(Criteria c) {
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        if (accountName != null && domainId != null) {
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

        return _vlanDao.search(sc, searchFilter);
    }
    
    @Override
    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
        }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);

        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
        }
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        } else {
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
        return _launchPermissionDao.listPermittedTemplates(accountId);
    }

    @Override
    public List listPods(long dataCenterId) {
        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }

    @Override
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
        if (isPublic != null) {
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {
        return _vmInstanceDao.findById(vmId);
    }

    @Override
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        }
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {

            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();

    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
        } else {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }
    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	else
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
        }
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override

    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
        
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
    @Override
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

    	Long userId = cmd.getUserId();
        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
    	
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        return groupVO;
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
    }

    /**
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
	{
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
        
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
            }
            accountId = account.getId();
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Break statement
Cast expression
For statement
If statement
Method declaration
Method invocation
Method signature
Variable
Chunk
Conflicting content
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }
<<<<<<< HEAD
    
=======

    @Override
    public void updateHost(long hostId, long guestOSCategoryId) throws InvalidParameterValueException {
    	// Verify that the guest OS Category exists
    	if (guestOSCategoryId > 0) {
    		if (_guestOSCategoryDao.findById(guestOSCategoryId) == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS category.");
    		}
    	}
    	
    	_agentMgr.updateHost(hostId, guestOSCategoryId);
    }
    
    @Override
    public boolean deleteHost(long hostId) {
        return _agentMgr.deleteHost(hostId);
    }

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    @Override
    public long getId() {
        return MacAddress.getMacAddress().toLong();
Solution content
/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */
package com.cloud.server;

import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.alert.AlertVO;
import com.cloud.alert.dao.AlertDao;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AssignPortForwardingServiceCmd;
import com.cloud.api.commands.CreateDomainCmd;
import com.cloud.api.commands.CreatePortForwardingServiceCmd;
import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd;
import com.cloud.api.commands.CreateUserCmd;
import com.cloud.api.commands.DeleteDomainCmd;
import com.cloud.api.commands.DeletePortForwardingServiceCmd;
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeleteUserCmd;
import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.EnableAccountCmd;
import com.cloud.api.commands.EnableUserCmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapabilitiesCmd;
import com.cloud.api.commands.ListCapacityCmd;
import com.cloud.api.commands.ListCfgsByCmd;
import com.cloud.api.commands.ListClustersCmd;
import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListIsosCmd;
import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPortForwardingServiceRulesCmd;
import com.cloud.api.commands.ListPortForwardingServicesByVmCmd;
import com.cloud.api.commands.ListPortForwardingServicesCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListStoragePoolsAndHostsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMGroupsCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.LockAccountCmd;
import com.cloud.api.commands.LockUserCmd;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.RemovePortForwardingServiceCmd;
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateAccountCmd;
import com.cloud.api.commands.UpdateDomainCmd;
import com.cloud.api.commands.UpdateIPForwardingRuleCmd;
import com.cloud.api.commands.UpdateIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplatePermissionsCmd;
import com.cloud.api.commands.UpdateUserCmd;
import com.cloud.api.commands.UpdateVMGroupCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.network.FirewallRuleVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVMMapVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkRuleConfigVO;
import com.cloud.network.SecurityGroupVMMapVO;
import com.cloud.network.SecurityGroupVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.security.NetworkGroupManager;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.network.security.dao.NetworkGroupDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.DiskTemplateVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Snapshot.SnapshotType;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.DiskTemplateDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.LaunchPermissionDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVMMapVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.InstanceGroupVMMapDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

public class ManagementServerImpl implements ManagementServer {	
    public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());

    private final AccountManager _accountMgr;
    private final AgentManager _agentMgr;
    private final ConfigurationManager _configMgr;
    private final FirewallRulesDao _firewallRulesDao;
    private final SecurityGroupDao _securityGroupDao;
	private final NetworkGroupDao _networkSecurityGroupDao;
    private final LoadBalancerDao _loadBalancerDao;
    private final NetworkRuleConfigDao _networkRuleConfigDao;
    private final SecurityGroupVMMapDao _securityGroupVMMapDao;
    private final IPAddressDao _publicIpAddressDao;
    private final DataCenterIpAddressDaoImpl _privateIpAddressDao;
    private final LoadBalancerVMMapDao _loadBalancerVMMapDao;
    private final DomainRouterDao _routerDao;
    private final ConsoleProxyDao _consoleProxyDao;
    private final ClusterDao _clusterDao;
    private final SecondaryStorageVmDao _secStorageVmDao;
    private final EventDao _eventDao;
    private final DataCenterDao _dcDao;
    private final VlanDao _vlanDao;
    private final AccountVlanMapDao _accountVlanMapDao;
    private final PodVlanMapDao _podVlanMapDao;
    private final HostDao _hostDao;
    private final UserDao _userDao;
    private final UserVmDao _userVmDao;
    private final ConfigurationDao _configDao;
    private final NetworkManager _networkMgr;
    private final UserVmManager _vmMgr;
    private final ConsoleProxyManager _consoleProxyMgr;
    private final SecondaryStorageVmManager _secStorageVmMgr;
    private final ServiceOfferingDao _offeringsDao;
    private final DiskOfferingDao _diskOfferingDao;
    private final VMTemplateDao _templateDao;
    private final LaunchPermissionDao _launchPermissionDao;
    private final DomainDao _domainDao;
    private final AccountDao _accountDao;
    private final ResourceLimitDao _resourceLimitDao;
    private final UserAccountDao _userAccountDao;
    private final AlertDao _alertDao;
    private final CapacityDao _capacityDao;
    private final SnapshotDao _snapshotDao;
    private final SnapshotPolicyDao _snapshotPolicyDao;
    private final GuestOSDao _guestOSDao;
    private final GuestOSCategoryDao _guestOSCategoryDao;
    private final StoragePoolDao _poolDao;
    private final StoragePoolHostDao _poolHostDao;
    private final StorageManager _storageMgr;
    private final UserVmDao _vmDao;

    private final Adapters _userAuthenticators;
    private final HostPodDao _hostPodDao;
    private final UserStatisticsDao _userStatsDao;
    private final VMInstanceDao _vmInstanceDao;
    private final VolumeDao _volumeDao;
    private final DiskTemplateDao _diskTemplateDao;
    private final AlertManager _alertMgr;
    private final AsyncJobDao _jobDao;
    private final AsyncJobManager _asyncMgr;
    private final TemplateManager _tmpltMgr;
    private final SnapshotManager _snapMgr;
    private final NetworkGroupManager _networkGroupMgr;
    private final int _purgeDelay;
    private final boolean _directAttachNetworkExternalIpAllocator;
    private final PreallocatedLunDao _lunDao;
    private final InstanceGroupDao _vmGroupDao;
    private final InstanceGroupVMMapDao _groupVMMapDao;
    private final UploadMonitor _uploadMonitor;
    private final UploadDao _uploadDao;

    private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
    private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));

    private final StatsCollector _statsCollector;

    private final Map _configs;

    private String _domain;

    private final int _routerRamSize;
    private final int _proxyRamSize;
    private final int _ssRamSize;

    private final Map _availableIdsMap;

	private boolean _networkGroupsEnabled = false;

    private boolean _isHypervisorSnapshotCapable = false;

    protected ManagementServerImpl() {
        ComponentLocator locator = ComponentLocator.getLocator(Name);
        _lunDao = locator.getDao(PreallocatedLunDao.class);
        _configDao = locator.getDao(ConfigurationDao.class);
        _routerDao = locator.getDao(DomainRouterDao.class);
        _eventDao = locator.getDao(EventDao.class);
        _dcDao = locator.getDao(DataCenterDao.class);
        _vlanDao = locator.getDao(VlanDao.class);
        _accountVlanMapDao = locator.getDao(AccountVlanMapDao.class);
        _podVlanMapDao = locator.getDao(PodVlanMapDao.class);
        _hostDao = locator.getDao(HostDao.class);
        _hostPodDao = locator.getDao(HostPodDao.class);
        _jobDao = locator.getDao(AsyncJobDao.class);
        _clusterDao = locator.getDao(ClusterDao.class);

        _accountMgr = locator.getManager(AccountManager.class);
        _agentMgr = locator.getManager(AgentManager.class);
        _configMgr = locator.getManager(ConfigurationManager.class);
        _networkMgr = locator.getManager(NetworkManager.class);
        _vmMgr = locator.getManager(UserVmManager.class);
        _consoleProxyMgr = locator.getManager(ConsoleProxyManager.class);
        _secStorageVmMgr = locator.getManager(SecondaryStorageVmManager.class);
        _storageMgr = locator.getManager(StorageManager.class);
        _firewallRulesDao = locator.getDao(FirewallRulesDao.class);
        _securityGroupDao = locator.getDao(SecurityGroupDao.class);
        _networkSecurityGroupDao  = locator.getDao(NetworkGroupDao.class);
        _loadBalancerDao = locator.getDao(LoadBalancerDao.class);
        _networkRuleConfigDao = locator.getDao(NetworkRuleConfigDao.class);
        _securityGroupVMMapDao = locator.getDao(SecurityGroupVMMapDao.class);
        _publicIpAddressDao = locator.getDao(IPAddressDao.class);
        _privateIpAddressDao = locator.getDao(DataCenterIpAddressDaoImpl.class);
        _loadBalancerVMMapDao = locator.getDao(LoadBalancerVMMapDao.class);
        _consoleProxyDao = locator.getDao(ConsoleProxyDao.class);
        _secStorageVmDao = locator.getDao(SecondaryStorageVmDao.class);
        _userDao = locator.getDao(UserDao.class);
        _userVmDao = locator.getDao(UserVmDao.class);
        _offeringsDao = locator.getDao(ServiceOfferingDao.class);
        _diskOfferingDao = locator.getDao(DiskOfferingDao.class);
        _templateDao = locator.getDao(VMTemplateDao.class);
        _launchPermissionDao = locator.getDao(LaunchPermissionDao.class);
        _domainDao = locator.getDao(DomainDao.class);
        _accountDao = locator.getDao(AccountDao.class);
                newAccount.setState("enabled");
        _resourceLimitDao = locator.getDao(ResourceLimitDao.class);
        _userAccountDao = locator.getDao(UserAccountDao.class);
        _alertDao = locator.getDao(AlertDao.class);
        _capacityDao = locator.getDao(CapacityDao.class);
        _snapshotDao = locator.getDao(SnapshotDao.class);
        _snapshotPolicyDao = locator.getDao(SnapshotPolicyDao.class);
        _guestOSDao = locator.getDao(GuestOSDao.class);
        _guestOSCategoryDao = locator.getDao(GuestOSCategoryDao.class);
        _poolDao = locator.getDao(StoragePoolDao.class);
        _poolHostDao = locator.getDao(StoragePoolHostDao.class);
        _vmDao = locator.getDao(UserVmDao.class);
        _vmGroupDao = locator.getDao(InstanceGroupDao.class);
        _groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class);
        _uploadDao = locator.getDao(UploadDao.class);

        _configs = _configDao.getConfiguration();
        _userStatsDao = locator.getDao(UserStatisticsDao.class);
        _vmInstanceDao = locator.getDao(VMInstanceDao.class);
        _volumeDao = locator.getDao(VolumeDao.class);
        _diskTemplateDao = locator.getDao(DiskTemplateDao.class);
        _alertMgr = locator.getManager(AlertManager.class);
        _asyncMgr = locator.getManager(AsyncJobManager.class);
        _tmpltMgr = locator.getManager(TemplateManager.class);
        _snapMgr = locator.getManager(SnapshotManager.class);
        _networkGroupMgr = locator.getManager(NetworkGroupManager.class);
        _uploadMonitor = locator.getManager(UploadMonitor.class);                
        
        _userAuthenticators = locator.getAdapters(UserAuthenticator.class);
        if (_userAuthenticators == null || !_userAuthenticators.isSet()) {

            s_logger.error("Unable to find an user authenticator.");
        }

        _domain = _configs.get("domain");
        if (_domain == null) {
            _domain = ".myvm.com";
        }
        if (!_domain.startsWith(".")) {
            _domain = "." + _domain;
        }

        String value = _configs.get("account.cleanup.interval");
        int cleanup = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour.

        // Parse the max number of UserVMs and public IPs from server-setup.xml,
        // and set them in the right places
        _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
        _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
        _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);

        _directAttachNetworkExternalIpAllocator =
        										Boolean.parseBoolean(_configs.get("direct.attach.network.externalIpAllocator.enabled"));
        
        _statsCollector = StatsCollector.getInstance(_configs);
        _executor.scheduleAtFixedRate(new AccountCleanupTask(), cleanup, cleanup, TimeUnit.SECONDS);

        _purgeDelay = NumbersUtil.parseInt(_configs.get("event.purge.delay"), 0);
        if(_purgeDelay != 0){
            _eventExecutor.scheduleAtFixedRate(new EventPurgeTask(), cleanup, cleanup, TimeUnit.SECONDS);
        }
        
        String[] availableIds = TimeZone.getAvailableIDs();
        _availableIdsMap = new HashMap(availableIds.length);
        for (String id: availableIds) {
            _availableIdsMap.put(id, true);
        }
        String enabled =_configDao.getValue("direct.attach.network.groups.enabled");
		if ("true".equalsIgnoreCase(enabled)) {
			_networkGroupsEnabled = true;
		}
 		
		String hypervisorType = _configDao.getValue("hypervisor.type");
        _isHypervisorSnapshotCapable  = hypervisorType.equals(Hypervisor.Type.XenServer.name());
    }

    protected Map getConfigs() {
        return _configs;
    }

    @Override
    public StorageStats getStorageStatistics(long hostId) {
        return _statsCollector.getStorageStats(hostId);
    }
    
    @Override
        }
    public PreallocatedLunVO registerPreallocatedLun(RegisterPreallocatedLunCmd cmd) {
        Long zoneId = cmd.getZoneId();
        String portal = cmd.getPortal();
        String targetIqn = cmd.getTargetIqn();
        Integer lun = cmd.getLun();
        Long size = cmd.getDiskSize();
        String t = cmd.getTags();

        String[] tags = null;
        if (t != null) {
            tags = t.split(",");
            for (int i = 0; i < tags.length; i++) {
                tags[i] = tags[i].trim();
            }
        } else {
            tags = new String[0];
        }
        
        PreallocatedLunVO vo = new PreallocatedLunVO(zoneId, portal, targetIqn, lun, size);
        return _lunDao.persist(vo, tags);
    }
    
    @Override
    public boolean unregisterPreallocatedLun(DeletePreallocatedLunCmd cmd) throws IllegalArgumentException {
        Long id = cmd.getId();
    	PreallocatedLunVO lun = null;
    	if ((lun = _lunDao.findById(id)) == null) {
    		throw new IllegalArgumentException("Unable to find a LUN with ID " + id);
    	}
    	
    	if (lun.getTaken() != null) {
    		throw new IllegalArgumentException("The LUN is currently in use and cannot be deleted.");
    	}
    	
        return _lunDao.delete(id);
    }

    @Override
    public VolumeStats[] getVolumeStatistics(long[] volIds) {
        return _statsCollector.getVolumeStats(volIds);
    }

    @Override
    public UserAccount createUser(CreateUserCmd cmd) {
        Long accountId = null;
        String username = cmd.getUsername();
        String password = cmd.getPassword();
        String firstName = cmd.getFirstname();
        String lastName = cmd.getLastname();
        Long domainId = cmd.getDomainId();
        String email = cmd.getEmail();
        String timezone = cmd.getTimezone();
        String accountName = cmd.getAccountName();
        short userType = cmd.getAccountType().shortValue();
        try {
            if (accountName == null) {
                accountName = username;
            }
            if (domainId == null) {
                domainId = DomainVO.ROOT_DOMAIN;
            }

            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account != null) {
                if (account.getType() != userType) {
                    throw new CloudRuntimeException("Account " + accountName + " is not the correct account type for user " + username);
                }
                accountId = account.getId();
            }

            if (!_userAccountDao.validateUsernameInDomain(username, domainId)) {
                throw new CloudRuntimeException("The user " + username + " already exists in domain " + domainId);
            }

            if (accountId == null) {
                if ((userType < Account.ACCOUNT_TYPE_NORMAL) || (userType > Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given; unable to create user");
                }

                // create a new account for the user
                AccountVO newAccount = new AccountVO();
                if (domainId == null) {
                    // root domain is default
                    domainId = DomainVO.ROOT_DOMAIN;
                }

                if ((domainId != DomainVO.ROOT_DOMAIN) && (userType == Account.ACCOUNT_TYPE_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given for an account in domain " + domainId + "; unable to create user.");
                }

                newAccount.setAccountName(accountName);
                newAccount.setDomainId(domainId);
                newAccount.setType(userType);
                newAccount = _accountDao.persist(newAccount);
                accountId = newAccount.getId();
            }

            if (accountId == null) {
                throw new CloudRuntimeException("Failed to create account for user: " + username + "; unable to create user");
            }

            UserVO user = new UserVO();
            user.setUsername(username);
            user.setPassword(password);
            user.setState("enabled");
            user.setFirstname(firstName);
            user.setLastname(lastName);
            user.setAccountId(accountId.longValue());
            user.setEmail(email);
            user.setTimezone(timezone);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Creating user: " + username + ", account: " + accountName + " (id:" + accountId + "), domain: " + domainId + " timezone:"+ timezone);
            }

            UserVO dbUser = _userDao.persist(user);
            
            _networkGroupMgr.createDefaultNetworkGroup(accountId);

            if (!user.getPassword().equals(dbUser.getPassword())) {
                throw new CloudRuntimeException("The user " + username + " being creating is using a password that is different than what's in the db");
            }

            EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_CREATE, "User, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId + " was created.");
            return _userAccountDao.findById(dbUser.getId());
        } catch (Exception e) {
        	EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_CREATE, "Error creating user, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId);
            if (e instanceof CloudRuntimeException) {
                s_logger.info("unable to create user: " + e);
            } else {
                s_logger.warn("unknown exception creating user", e);
            }
            throw new CloudRuntimeException(e.getMessage());
        }
    }

    @Override
    public String updateAdminPassword(long userId, String oldPassword, String newPassword) {
        // String old = StringToMD5(oldPassword);
        // User user = getUser(userId);
        // if (old.equals(user.getPassword())) {
        UserVO userVO = _userDao.createForUpdate(userId);
        userVO.setPassword(StringToMD5(newPassword));
        _userDao.update(userId, userVO);
        return newPassword;
        // } else {
        // return null;
        // }
    }

    private String StringToMD5(String string) {
        MessageDigest md5;

        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new CloudRuntimeException("Error", e);
        }

        md5.reset();
        BigInteger pwInt = new BigInteger(1, md5.digest(string.getBytes()));

        // make sure our MD5 hash value is 32 digits long...
        StringBuffer sb = new StringBuffer();
        String pwStr = pwInt.toString(16);
        int padding = 32 - pwStr.length();
        for (int i = 0; i < padding; i++) {
            sb.append('0');
        }
        sb.append(pwStr);
        return sb.toString();
    }

    @Override
    public User getUser(long userId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId);
        }

        UserVO user = _userDao.getUser(userId);
        if (user == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with id " + userId);
            }
            return null;

        return user;
    }

    @Override
    public User getUser(long userId, boolean active) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId + " and active = " + active);
        }

        if (active) {
            return _userDao.getUser(userId);
        } else {
            return _userDao.findById(userId);
        }
    }

    @Override
    public UserAccount getUserAccount(String username, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user: " + username + " in domain " + domainId);
        }

        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        return userAccount;
    }

    private UserAccount getUserAccount(String username, String password, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
        }
        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        if (!userAccount.getState().equals("enabled") || !userAccount.getAccountState().equals("enabled")) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("user " + username + " in domain " + domainId + " is disabled/locked (or account is disabled/locked), returning null");
            }
            return null;
        }

        // We only use the first adapter even if multiple have been
        // configured
        Enumeration en = _userAuthenticators.enumeration();
        UserAuthenticator authenticator = en.nextElement();
        boolean authenticated = authenticator.authenticate(username, password, domainId);

        if (authenticated) {
        	return userAccount;
        } else {
        	return null;
        }
    }

    private boolean deleteUserInternal(long userId) {
        UserAccount userAccount = null;
        Long accountId = null;
        String username = null;
        try {
            UserVO user = _userDao.findById(userId);
            if (user == null || user.getRemoved() != null) {
                return true;
            }
            username = user.getUsername();
            boolean result = _userDao.remove(userId);
            if (!result) {
                s_logger.error("Unable to remove the user with id: " + userId + "; username: " + user.getUsername());
                return false;
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("User is removed, id: " + userId + "; username: " + user.getUsername());
            }

            accountId = user.getAccountId();
            userAccount = _userAccountDao.findById(userId);

            List users = _userDao.listByAccount(accountId);
            if (users.size() != 0) {
                s_logger.debug("User (" + userId + "/" + user.getUsername() + ") is deleted but there's still other users in the account so not deleting account.");
                return true;
            }

            result = _accountDao.remove(accountId);
            if (!result) {
                s_logger.error("Unable to delete account " + accountId);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Remove account " + accountId);
            }

            AccountVO account = _accountDao.findById(accountId);
            deleteAccount(account);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "User " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + userAccount.getDomainId() + " was deleted.");
            return true;
        } catch (Exception e) {
            s_logger.error("exception deleting user: " + userId, e);
            long domainId = 0L;
            if (userAccount != null)
                domainId = userAccount.getDomainId();
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "Error deleting user " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + domainId);
            return false;
        }
    }

    public boolean deleteAccount(AccountVO account) {
        long accountId = account.getId();
        long userId = 1L; // only admins can delete users, pass in userId 1 XXX: Shouldn't it be userId 2.
        boolean accountCleanupNeeded = false;
        
        try {
        	//delete all vm groups belonging to accont
        	List groups = _vmGroupDao.listByAccountId(accountId);
            for (InstanceGroupVO group : groups) {
                if (!_vmMgr.deleteVmGroup(group.getId())) {
                    s_logger.error("Unable to delete group: " + group.getId());
                    accountCleanupNeeded = true;
                } 
            }
        	
            // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
            boolean success = _snapMgr.deleteSnapshotDirsForAccount(accountId);
            if (success) {
                s_logger.debug("Successfully deleted snapshots directories for all volumes under account " + accountId + " across all zones");
            }
            // else, there are no snapshots, hence no directory to delete.
            
            // Destroy the account's VMs
            List vms = _userVmDao.listByAccountId(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of vms (accountId=" + accountId + "): " + vms.size());
            }

            for (UserVmVO vm : vms) {
                if (!_vmMgr.destroyVirtualMachine(userId, vm.getId())) {
                    s_logger.error("Unable to destroy vm: " + vm.getId());
                    accountCleanupNeeded = true;
                } 
            }
            
            // Mark the account's volumes as destroyed
            List volumes = _volumeDao.findDetachedByAccount(accountId);
            for (VolumeVO volume : volumes) {
            	if(volume.getPoolId()==null){
            		accountCleanupNeeded = true;
            	}
            	_storageMgr.destroyVolume(volume);
            }

            // Destroy the account's routers
            List routers = _routerDao.listBy(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of routers (accountId=" + accountId + "): " + routers.size());
            }

            boolean routersCleanedUp = true;
            for (DomainRouterVO router : routers) {
                if (!_networkMgr.destroyRouter(router.getId())) {
                    s_logger.error("Unable to destroy router: " + router.getId());
                    routersCleanedUp = false;
                }
            }

            if (routersCleanedUp) {
            	List ips = _publicIpAddressDao.listByAccount(accountId);
            	
                if (s_logger.isDebugEnabled()) {
            		s_logger.debug("Found " + ips.size() + " public IP addresses for account with ID " + accountId);
                }

            	for (IPAddressVO ip : ips) {
            		Long podId = getPodIdForVlan(ip.getVlanDbId());
            		if (podId != null) {
            			continue;//bug 5561 do not release direct attach pod ips until vm is destroyed
            		}
            		if (!_networkMgr.releasePublicIpAddress(User.UID_SYSTEM, ip.getAddress())) {
            			s_logger.error("Unable to release IP: " + ip.getAddress());
                        accountCleanupNeeded = true;
                    } else {
                    	_accountMgr.decrementResourceCount(accountId, ResourceType.public_ip);
                    }
                }
            } else {
            	accountCleanupNeeded = true;
            }
            
            List securityGroups = _securityGroupDao.listByAccountId(accountId);
            if (securityGroups != null) {
                for (SecurityGroupVO securityGroup : securityGroups) {
                    // All vm instances have been destroyed, delete the security group -> instance_id mappings
                    SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();
                    sc.addAnd("securityGroupId", SearchCriteria.Op.EQ, securityGroup.getId());
                    _securityGroupVMMapDao.expunge(sc);

                    // now clean the network rules and security groups themselves
                    _networkRuleConfigDao.deleteBySecurityGroup(securityGroup.getId());
                    _securityGroupDao.remove(securityGroup.getId());
                }
            }
            
            // Delete the account's VLANs
            List accountVlans = _vlanDao.listVlansForAccountByType(null, accountId, VlanType.DirectAttached);
            boolean allVlansDeleted = true;
            for (VlanVO vlan : accountVlans) {
            	try {
            		allVlansDeleted = _configMgr.deleteVlanAndPublicIpRange(User.UID_SYSTEM, vlan.getId());
            	} catch (InvalidParameterValueException e) {
            		allVlansDeleted = false;
            	}
            }

            if (!allVlansDeleted) {
            	accountCleanupNeeded = true;
            }
            
            // clean up templates
            List userTemplates = _templateDao.listByAccountId(accountId);
            boolean allTemplatesDeleted = true;
            for (VMTemplateVO template : userTemplates) {
            	try {
            		allTemplatesDeleted = _tmpltMgr.delete(userId, template.getId(), null);
            	} catch (InternalErrorException e) {
            		s_logger.warn("Failed to delete template while removing account: " + template.getName() + " due to: " + e.getMessage());
            		allTemplatesDeleted = false;
            	}
            }
            
            if (!allTemplatesDeleted) {
            	accountCleanupNeeded = true;
            }

            return true;
        } finally {
            s_logger.info("Cleanup for account " + account.getId() + (accountCleanupNeeded ? " is needed." : " is not needed."));
            
            if (accountCleanupNeeded) {
            	_accountDao.markForCleanup(accountId);
            }
        }
    }

    @Override
    public boolean disableUser(long userId) {
        if (userId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableUser -- invalid user id: " + userId);
            }
            return false;
        }

        return doSetUserStatus(userId, Account.ACCOUNT_STATE_DISABLED);
    }

    @Override
    public boolean enableUser(EnableUserCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long userId = cmd.getId();
    	Account adminAccount = (Account)UserContext.current().getAccountObject();
        boolean success = false;
        
        //Check if user exists in the system
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);
        
        // If the user is a System user, return an error
        Account account = findAccountById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed");
        }

        if ((adminAccount != null) && !isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
        	throw new PermissionDeniedException("Failed to enable user " + userId + ", permission denied.");
        }
        
        success = doSetUserStatus(userId, Account.ACCOUNT_STATE_ENABLED);

        // make sure the account is enabled too
        success = (success && enableAccount(user.getAccountId()));
        
        return success;
    }

    @Override
    public boolean lockUser(LockUserCmd cmd) {
        boolean success = false;
        
        Account adminAccount = (Account)UserContext.current().getAccountObject();

        Long id = cmd.getId();

        // Check if user with id exists in the system
        User user = _userDao.findById(id);
        if (user == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        } else if (user.getRemoved() != null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        }

        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is a system user, locking is not allowed");
        }

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock user " + id + ", permission denied.");
        }

        // make sure the account is enabled too
        // if the user is either locked already or disabled already, don't change state...only lock currently enabled users
        if (user.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
            // already locked...no-op
            return true;
        } else if (user.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
            success = doSetUserStatus(user.getId(), Account.ACCOUNT_STATE_LOCKED);

            boolean lockAccount = true;
            List allUsersByAccount = _userDao.listByAccount(user.getAccountId());
            for (UserVO oneUser : allUsersByAccount) {
                if (oneUser.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                    lockAccount = false;
                    break;
                }
            }

            if (lockAccount) {
                success = (success && lockAccountInternal(user.getAccountId()));
            }
        } else {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Attempting to lock a non-enabled user, current state is " + user.getState() + " (userId: " + user.getId() + "), locking failed.");
            }
        }
        return success;
    }

    private boolean doSetUserStatus(long userId, String state) {
        UserVO userForUpdate = _userDao.createForUpdate();
        userForUpdate.setState(state);
        return _userDao.update(Long.valueOf(userId), userForUpdate);
    }

    @Override
    public boolean disableAccount(long accountId) {
        boolean success = false;
        if (accountId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableAccount -- invalid account id: " + accountId);
            }
            return false;
        }

        AccountVO account = _accountDao.findById(accountId);
        if ((account == null) || account.getState().equals(Account.ACCOUNT_STATE_DISABLED)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setState(Account.ACCOUNT_STATE_DISABLED);
            success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);

            success = (success && doDisableAccount(accountId));
        }
        return success;
    }

    @Override
    public boolean updateAccount(UpdateAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getDomainId();
    	String accountName = cmd.getAccountName();
    	String newAccountName = cmd.getNewName();
    	
    	if (newAccountName == null) {
    		newAccountName = accountName;
    	}
    	
        boolean success = false;
        Account account = _accountDao.findAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        if (account.getAccountName().equals(accountName)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setAccountName(newAccountName);
            success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate);
        }
        return success;
    }

    private boolean doDisableAccount(long accountId) {
        List vms = _userVmDao.listByAccountId(accountId);
        boolean success = true;
        for (UserVmVO vm : vms) {
            try {
                success = (success && _vmMgr.stop(vm, 0));
            } catch (AgentUnavailableException aue) {
                s_logger.warn("Agent running on host " + vm.getHostId() + " is unavailable, unable to stop vm " + vm.getName());
                success = false;
            }
        }

        List routers = _routerDao.listBy(accountId);
        for (DomainRouterVO router : routers) {
            success = (success && _networkMgr.stopRouter(router.getId(), 0));
        }

        return success;
    }

    public boolean enableAccount(long accountId) {
        boolean success = false;
        AccountVO acctForUpdate = _accountDao.createForUpdate();
        acctForUpdate.setState(Account.ACCOUNT_STATE_ENABLED);
        success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
        return success;
    }
    	
    
    @Override
    public boolean enableAccount(EnableAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String accountName = cmd.getAccountName();
    	Long domainId = cmd.getDomainId();
        boolean success = false;
        Account account = _accountDao.findActiveAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        success = enableAccount(account.getId());
        return success;
    }

    private boolean lockAccountInternal(long accountId) {
        boolean success = false;
        Account account = _accountDao.findById(accountId);
        if (account != null) {
            if (account.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
                return true; // already locked, no-op
            } else if (account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                AccountVO acctForUpdate = _accountDao.createForUpdate();
                acctForUpdate.setState(Account.ACCOUNT_STATE_LOCKED);
                success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
            } else {
                if (s_logger.isInfoEnabled()) {
                    s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
                }
            }
        } else {
            s_logger.warn("Failed to lock account " + accountId + ", account not found.");
        }
        return success;
    }

    @Override
    public boolean updateUser(UpdateUserCmd cmd) throws InvalidParameterValueException {
        Long id = cmd.getId();
        String apiKey = cmd.getApiKey();
        String firstName = cmd.getFirstname();
    	String email = cmd.getEmail();
    	String lastName = cmd.getLastname();
    	String password = cmd.getPassword();
    	String secretKey = cmd.getSecretKey();
    	String timeZone = cmd.getTimezone();
    	String userName = cmd.getUsername();
    	
        //Input validation
    	UserVO user = _userDao.getUser(id);
    	
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user by id");
        }

        if((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide an api key/secret key pair");
        }
        
        // If the account is an admin type, return an error.  We do not allow this
        Account account = (Account)UserContext.current().getAccountObject();
        
        if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is system account, update is not allowed");
        }

        if (firstName == null) { 
        	firstName = user.getFirstname();
        }
        if (lastName == null) { 
        	lastName = user.getLastname(); 
        }
        if (userName == null) { 
        	userName = user.getUsername();  
        }
        if (password == null) { 
        	password = user.getPassword();
                userBySecretKey = _userDao.findUserBySecretKey(encodedKey);
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_DETACH, "Detaching ISO: "+isoId+" from Vm: "+vmId, startEventId);
        }
        if (email == null) {
        	email = user.getEmail();
        }
        if (timeZone == null) {
        	timeZone = user.getTimezone();
        }
        if (apiKey == null) {
        	apiKey = user.getApiKey();
        }
        if (secretKey == null) {
        	secretKey = user.getSecretKey();
        }

        Long accountId = user.getAccountId();

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("updating user with id: " + id);
        }
        UserAccount userAccount = _userAccountDao.findById(id);
        try {
        	//check if the apiKey and secretKey are globally unique
        	if (apiKey != null && secretKey != null) {
        		Pair apiKeyOwner = findUserByApiKey(apiKey);

        		if(apiKeyOwner != null) {
        			User usr = apiKeyOwner.first();
        			if (usr.getId() != id) {
            			throw new InvalidParameterValueException("The api key:"+apiKey+" exists in the system for user id:"+id+" ,please provide a unique key");
        			} else {
        				//allow the updation to take place
        			}
        		}
        	}
            _userDao.update(id, userName, password, firstName, lastName, email, accountId, timeZone, apiKey, secretKey);
            EventUtils.saveEvent(new Long(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_UPDATE, "User, " + userName + " for accountId = "
                    + accountId + " domainId = " + userAccount.getDomainId() + " and timezone = "+timeZone + " was updated.");
        } catch (Throwable th) {
            s_logger.error("error updating user", th);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_UPDATE, "Error updating user, " + userName
                    + " for accountId = " + accountId + " and domainId = " + userAccount.getDomainId());
            return false;
        }
        return true;
    }
    
    @Override
    public Pair findUserByApiKey(String apiKey) {
        return _accountDao.findUserAccountByApiKey(apiKey);
    }

    @Override
    public Account getAccount(long accountId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving account with id: " + accountId);
        }

        AccountVO account = _accountDao.findById(Long.valueOf(accountId));
        if (account == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find account with id " + accountId);
            }
            return null;
        }

        return account;
    }
    
    @Override
    public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
    	Long userId = cmd.getId();
    	User user = _userDao.findById(userId);

    	if (user == null) {
           throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find user for id : " + userId);
    	}

    	// generate both an api key and a secret key, update the user table with the keys, return the keys to the user
    	String[] keys = new String[2];
    	keys[0] = createApiKey(userId);
    	keys[1] = createSecretKey(userId);

    	return keys;
    }

    private String createApiKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            Pair userAcct = null;
            int retryLimit = 10;
            do {
                // FIXME: what algorithm should we use for API keys?
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userAcct = _accountDao.findUserAccountByApiKey(encodedKey);
                retryLimit--;
            } while ((userAcct != null) && (retryLimit >= 0));

            if (userAcct != null) {
                return null;
            }
            updatedUser.setApiKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    private String createSecretKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            int retryLimit = 10;
            UserVO userBySecretKey = null;
            do {
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                retryLimit--;
            } while ((userBySecretKey != null) && (retryLimit >= 0));

            if (userBySecretKey != null) {
                return null;
            }

            updatedUser.setSecretKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }

    @Override
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
        SearchCriteria sc = _publicIpAddressDao.createSearchCriteria();

        if (accountId != null)
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        if (zoneId != null)
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        if (vlanDbId != null)
            sc.addAnd("vlanDbId", SearchCriteria.Op.EQ, vlanDbId);
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

        return _publicIpAddressDao.search(sc, null);
    }

    @Override
    public List listPrivateIpAddressesBy(Long podId, Long zoneId) {
        if (podId != null && zoneId != null)
            return _privateIpAddressDao.listByPodIdDcId(podId.longValue(), zoneId.longValue());
        else
            return new ArrayList();
    }

    @Override
    public String generateRandomPassword() {
    	return PasswordGenerator.generateRandomPassword();
    }

    @Override
    public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
    	UserVmVO vm = _userVmDao.findById(vmId);
    	VMTemplateVO iso = _templateDao.findById(isoId);
    	if(attach){
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_ATTACH, "Attaching ISO: "+isoId+" to Vm: "+vmId, startEventId);
    	} else {
    	}
        boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach);

        if (success) {
            if (attach) {
                vm.setIsoId(iso.getId().longValue());
            } else {
                vm.setIsoId(null);
            }
            _userVmDao.update(vmId, vm);

            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_ATTACH, "Successfully attached ISO: " + iso.getName() + " to VM with ID: " + vmId,
                        null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_DETACH, "Successfully detached ISO from VM with ID: " + vmId, null, startEventId);
            }
        } else {
            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_ATTACH, "Failed to attach ISO: " + iso.getName() + " to VM with ID: " + vmId, null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_DETACH, "Failed to detach ISO from VM with ID: " + vmId, null, startEventId);
            }
        }
        return success;
    }

    private boolean validPassword(String password) {
        for (int i = 0; i < password.length(); i++) {
            if (password.charAt(i) == ' ') {
                return false;
            }
        }
        return true;
    }

    private UserVm deployVirtualMachineImpl(long userId, long accountId, long dataCenterId, long serviceOfferingId, long templateId, Long diskOfferingId,
            String domain, String password, String displayName, String group, String userData, String [] networkGroups, long startEventId, long size) throws ResourceAllocationException, InvalidParameterValueException, InternalErrorException,
            InsufficientStorageCapacityException, PermissionDeniedException, ExecutionException, StorageUnavailableException, ConcurrentOperationException {

    	EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "Deploying Vm", startEventId);
        
        AccountVO account = _accountDao.findById(accountId);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        VMTemplateVO template = _templateDao.findById(templateId);

        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }
        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
			
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        
        // TODO: Checks such as is the user allowed to use the template and purchase the service offering id.

        if (domain == null) {
            domain = "v" + Long.toHexString(accountId) + _domain;
        }

        // Check that the password was passed in and is valid
        if (!template.getEnablePassword()) {
            password = "saved_password";
        }

        if (password == null || password.equals("") || (!validPassword(password))) {
            throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
        }
        List networkGroupVOs = new ArrayList();
        if (networkGroups != null) {
        	for (String groupName: networkGroups) {
        		NetworkGroupVO networkGroupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
        		if (networkGroupVO == null) {
        			throw new InvalidParameterValueException("Network Group " + groupName + " does not exist");
        		}
        		networkGroupVOs.add(networkGroupVO);
        	}
        }
        
        UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dataCenterId);
        if (stats == null) {
            stats = new UserStatisticsVO(account.getId(), dataCenterId);
            _userStatsDao.persist(stats);
        }
        
    	Long vmId = _vmDao.getNextInSequence(Long.class, "id");
    	
        // check if we are within context of async-execution
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("DeployVM acquired a new instance " + vmId + ", update async job-" + job.getId() + " progress status");

            _asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", vmId);
            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, vmId);
        }

        HashMap avoids = new HashMap();

        // Pod allocator now allocate VM based on a reservation style allocation, disable retry here for now
        for (int retry = 0; retry < 1; retry++) {
            String externalIp = null;
            UserVmVO created = null;

            ArrayList a = new ArrayList(avoids.values());
            if (_directAttachNetworkExternalIpAllocator) {
            	try {
            		created = _vmMgr.createDirectlyAttachedVMExternal(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            	} catch (ResourceAllocationException rae) {
            		throw rae;
            	}
            } else {
            	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
            		try {
            			externalIp = _networkMgr.assignSourceNatIpAddress(account, dc, domain, offering, startEventId);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}

            		if (externalIp == null) {
            			throw new InternalErrorException("Unable to allocate a source nat ip address");
            		}

            		if (s_logger.isDebugEnabled()) {
            			s_logger.debug("Source Nat acquired: " + externalIp);
            		}

            		try {
            			created = _vmMgr.createVirtualMachine(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	} else {
            		try {
            			created = _vmMgr.createDirectlyAttachedVM(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	}
            }

            //assign vm to the group
            try{
            	if (group != null) {
            	boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
            	if (!addToGroup) {
            		throw new InternalErrorException("Unable to assing Vm to the group " + group);
            	}
                }
            } catch (Exception ex) {
            	throw new InternalErrorException("Unable to assing Vm to the group " + group);
            }
            
            
            if (created == null) {
                throw new InternalErrorException("Unable to create VM for account (" + accountId + "): " + account.getAccountName());
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM created: " + created.getId() + "-" + created.getName());
            }
            boolean executionExceptionFlag = false;
            boolean storageUnavailableExceptionFlag = false;
            boolean concurrentOperationExceptionFlag = false;
            String executionExceptionMsg= "";
            String storageUnavailableExceptionMsg = "";
            String concurrentOperationExceptionMsg = "";
            UserVmVO started = null;
            if (isIso) {
                String isoPath = _storageMgr.getAbsoluteIsoPath(templateId, dataCenterId);
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, isoPath, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }
            } else {
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, null, startEventId);

                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }

            }

            if (started == null) {
                List> disks = _storageMgr.isStoredOn(created);
                // NOTE: We now destroy a VM if the deploy process fails at any step. We now
                // have a lazy delete so there is still some time to figure out what's wrong.
                _vmMgr.destroyVirtualMachine(userId, created.getId());

                boolean retryCreate = true;
                for (Pair disk : disks) {
                    if (disk.second().isLocal()) {
                        avoids.put(disk.second().getId(), disk.second());
                    } else {
                        retryCreate = false;
                    }
                }

                if (retryCreate) {
                    continue;
                } else if(executionExceptionFlag){
                    throw new ExecutionException(executionExceptionMsg);
                } else if (storageUnavailableExceptionFlag){
                	throw new StorageUnavailableException(storageUnavailableExceptionMsg);
                }else if (concurrentOperationExceptionFlag){
                	throw new ConcurrentOperationException(concurrentOperationExceptionMsg);
                }
                else{
                    throw new InternalErrorException("Unable to start the VM " + created.getId() + "-" + created.getName());
                }
                
            } else {
                if (isIso) {
                    started.setIsoId(templateId);
                    _userVmDao.update(started.getId(), started);
                    started = _userVmDao.findById(started.getId());
                }

                try {
					_configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null);															
				} catch (InsufficientAddressCapacityException e) {
					s_logger.debug("Unable to assign public IP address pool: " +e.getMessage());					
				}
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM started: " + started.getId() + "-" + started.getName());
            }
            return started;
        }

        return null;
    }

    @Override
    public UserVm deployVirtualMachine(DeployVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException,
                                                               InternalErrorException, InsufficientStorageCapacityException, ExecutionException,
                                                               StorageUnavailableException, ConcurrentOperationException {
        Account ctxAccount = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        long dataCenterId = cmd.getZoneId();
        long serviceOfferingId = cmd.getServiceOfferingId();
        long templateId = cmd.getTemplateId();
        Long diskOfferingId = cmd.getDiskOfferingId();
        String domain = null; // FIXME:  this was hardcoded to null in DeployVMCmd in the old framework, do we need it?
        String password = generateRandomPassword();
        String displayName = cmd.getDisplayName();
        String group = cmd.getGroup();
        String userData = cmd.getUserData();
        String[] networkGroups = null;
        Long sizeObj = cmd.getSize();
        long size = (sizeObj == null) ? 0 : sizeObj;
        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {
                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }

        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for deploying a virtual machine.");
        }

        List netGrpList = cmd.getNetworkGroupList();
        if ((netGrpList != null) && !netGrpList.isEmpty()) {
            networkGroups = netGrpList.toArray(new String[netGrpList.size()]);
        }

    	AccountVO account = _accountDao.findById(accountId);
        if (account == null) {
            throw new InvalidParameterValueException("Unable to find account: " + accountId);
        }

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        if (dc == null) {
            throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
        }

        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        if (offering == null) {
            throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
        }

        VMTemplateVO template = _templateDao.findById(templateId);
        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        
        if (isIso && !template.isBootable()) {
        	throw new InvalidParameterValueException("Please specify a bootable ISO.");
        }

            throw new InvalidParameterValueException("publicPort is an invalid value");
        // If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
        // Else, a disk offering is optional, and if present will be used to create the data disk
        DiskOfferingVO diskOffering = null;

        if (diskOfferingId != null) {
        	diskOffering = _diskOfferingDao.findById(diskOfferingId);
        }

        if (isIso && diskOffering == null) {
        	throw new InvalidParameterValueException("Please specify a valid disk offering ID.");
        }

        // validate that the template is usable by the account
        if (!template.isPublicTemplate()) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType()) && ((templateOwner == null) || (templateOwner.longValue() != accountId))) {
                // since the current account is not the owner of the template, check the launch permissions table to see if the
                // account can launch a VM from this template
                LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(templateId, account.getId());
                if (permission == null) {
                    throw new PermissionDeniedException("Account " + account.getAccountName() + " does not have permission to launch instances from template " + template.getName());
                }
            }
        }

        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	if (decodedUserData.length < 1) {
        		throw new InvalidParameterValueException("User data is too short");
        	}
			
        }
        if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized) {
        	_networkGroupMgr.createDefaultNetworkGroup(accountId);
    	}
        
        if (networkGroups != null) {
        	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
        		throw new InvalidParameterValueException("Network groups are not compatible with service offering " + offering.getName());
        	}
        	Set nameSet = new HashSet(); //handle duplicate names -- allowed
        	nameSet.addAll(Arrays.asList(networkGroups));
        	nameSet.add(NetworkGroupManager.DEFAULT_GROUP_NAME);
        	networkGroups = nameSet.toArray(new String[nameSet.size()]);
        	List networkGroupVOs = _networkSecurityGroupDao.findByAccountAndNames(accountId, networkGroups);
        	if (networkGroupVOs.size() != nameSet.size()) {
        		throw new InvalidParameterValueException("Some network group names do not exist");
        	}
        } else { //create a default group if necessary
        	if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized && _networkGroupsEnabled) {
        		networkGroups = new String[]{NetworkGroupManager.DEFAULT_GROUP_NAME};
        	}
        }

        // FIXME:  this really needs to be invoked when the job is scheduled by the framework, so commands need a callback for
        //         specifying event details that they are tracking...
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "deploying Vm");

        try {
            return deployVirtualMachineImpl(userId, accountId, dataCenterId, serviceOfferingId, templateId, diskOfferingId, domain, password, displayName, group, userData, networkGroups, eventId, size);
        } catch (ResourceAllocationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (ExecutionException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
        }
        if (!NetUtils.isValidPort(privatePort)) {
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_HOST_LICENSE_EXPIRED", null, eventId);
            throw e;
        } catch (InvalidParameterValueException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INVALID_PARAM_ERROR", null, eventId);
            throw e;
        } catch (InternalErrorException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch (InsufficientStorageCapacityException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (PermissionDeniedException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: ACCOUNT_ERROR", null, eventId);
            throw e;
        } catch (ConcurrentOperationException e) {
            if(s_logger.isDebugEnabled())
            userId = Long.valueOf(1);
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch(Exception e) {
            s_logger.warn("Unable to deploy VM : " + e.getMessage(), e);
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw new CloudRuntimeException("Unable to deploy VM : " + e.getMessage());
        }
    }

    @Override
    public DomainRouterVO findDomainRouterBy(long accountId, long dataCenterId) {
        return _routerDao.findBy(accountId, dataCenterId);
    }

    @Override
    public DomainRouterVO findDomainRouterById(long domainRouterId) {
        return _routerDao.findById(domainRouterId);
    }

    @Override
    public List listDataCenters(ListZonesByCmd cmd) {
        List dcs = _dcDao.listAll();

        Account account = (Account)UserContext.current().getAccountObject();
        Boolean available = cmd.isAvailable();
        if (account != null) {
            if ((available != null) && Boolean.FALSE.equals(available)) {
                List routers = _routerDao.listBy(account.getId());
                for (Iterator iter = dcs.iterator(); iter.hasNext();) {
                    DataCenterVO dc = iter.next();
                    boolean found = false;
                    for (DomainRouterVO router : routers) {
                        if (dc.getId() == router.getDataCenterId()) {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        iter.remove();
                }
            }
        }

        return dcs;
    }

    @Override
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }

    @Override
    public long getId() {
        return MacAddress.getMacAddress().toLong();
    }

    protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {

        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");
        }

//        s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
//        if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//            throw new InvalidParameterValueException("Invalid private ip address");
//        }
        if (!NetUtils.isValidProto(proto)) {
            throw new InvalidParameterValueException("Invalid protocol");
        }
    }

    @Override
    @DB
    public void assignSecurityGroup(AssignPortForwardingServiceCmd cmd) throws PermissionDeniedException,
            NetworkRuleConflictException, InvalidParameterValueException, InternalErrorException {
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	Long securityGroupId = cmd.getId();
    	List sgIdList = cmd.getIds();
    	String publicIp = cmd.getPublicIp();
    	Long vmId = cmd.getVirtualMachineId();
    	
    	//Verify input parameters
        if ((securityGroupId == null) && (sgIdList == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }


        if (userId == null) {
        }

        List validateSGList = null;
        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = findAccountById(validatedAccountId);
                if (!isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }
    	
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            s_logger.warn("Unable to find virtual machine with id " + vmId);
            throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
        }
        long startEventId = EventUtils.saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "applying port forwarding service for Vm with Id: "+vmId);
    	
        boolean locked = false;
        Transaction txn = Transaction.currentTxn();
        try {
            EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "Applying port forwarding service for Vm with Id: "+vmId, startEventId);
            State vmState = userVm.getState();
            switch (vmState) {
            case Destroyed:
            case Error:
            case Expunging:
            case Unknown:
                throw new InvalidParameterValueException("Unable to assign port forwarding service(s) '"
                        + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "' to virtual machine " + vmId
                        + " due to virtual machine being in an invalid state for assigning a port forwarding service (" + vmState + ")");
            }

            // sanity check that the vm can be applied to the load balancer
            ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
            if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                }

                throw new InvalidParameterValueException("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }
            
            DomainRouterVO router = null;
            if (userVm.getDomainRouterId() != null)
            	router = _routerDao.findById(userVm.getDomainRouterId());
            if (router == null) {
                s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine " + userVm.toString());
                throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + vmId);
            }

            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;

            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User does not own supplied address");
            }

            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new InvalidParameterValueException("Invalid IP address " + publicIp + " for applying port forwarding services, the IP address is not in a 'virtual network' vlan.");
            }

            txn.start();

            if (securityGroupId == null) {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on list passed in
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                {
                    // Save and create the event
                    String description;
                    String type = EventTypes.EVENT_NET_RULE_DELETE;
                    String level = EventVO.LEVEL_INFO;

                    for (FirewallRuleVO fwRule : fwRulesToRemove) {
                        fwRule.setEnabled(false); // disable rule for sending to the agent
                        _firewallRulesDao.remove(fwRule.getId()); // remove the rule from the database

                        description = "deleted ip forwarding rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                                + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                        EventUtils.saveEvent(userId, userVm.getAccountId(), level, type, description);
                    }
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);
                if ((updatedRules != null) && (updatedRules.size() != fwRulesToRemove.size())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to clean up all port forwarding service rules for public IP " + publicIp + " and guest vm " + userVm.getName()
                                + " while applying port forwarding service(s) '" + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "'"
                                + " -- intended to remove " + fwRulesToRemove.size() + " rules, removd " + ((updatedRules == null) ? "null" : updatedRules.size()) + " rules.");
                    }
                }

                List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    boolean success = _securityGroupVMMapDao.remove(sgVmMapping.getId());

                    SecurityGroupVO securityGroup = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());

        // for port 22 should not be removed.
                    // save off an event for removing the security group
                    EventVO event = new EventVO();
                    event.setUserId(userId);
                    event.setAccountId(userVm.getAccountId());
                    event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
                    String sgRemoveLevel = EventVO.LEVEL_INFO;
                    String sgRemoveDesc = "Successfully removed ";
                    if (!success) {
                        sgRemoveLevel = EventVO.LEVEL_ERROR;
                        sgRemoveDesc = "Failed to remove ";
                    }
                    String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
                    event.setParameters(params);
                    event.setDescription(sgRemoveDesc + "port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
                    event.setLevel(sgRemoveLevel);
                    _eventDao.persist(event);
                }
            } else {
                List existingVMMaps = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId.longValue());
                if ((existingVMMaps != null) && !existingVMMaps.isEmpty()) {
                    for (SecurityGroupVMMapVO existingVMMap : existingVMMaps) {
                        if (existingVMMap.getInstanceId() == userVm.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("port forwarding service " + securityGroupId + " is already applied to virtual machine " + userVm.toString() + ", skipping assignment.");
                            }
                            return;
                        }
                    }
                }
            }

            List finalSecurityGroupIdList = new ArrayList();
            if (securityGroupId != null) {
                finalSecurityGroupIdList.add(securityGroupId);
            } else {
                finalSecurityGroupIdList.addAll(sgIdList);
            }

            for (Long sgId : finalSecurityGroupIdList) {
                if (sgId.longValue() == 0) {
                    // group id of 0 means to remove all groups, which we just did above
                    break;
                }

                SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(sgId));
                if (securityGroup == null) {
                    s_logger.warn("Unable to find port forwarding service with id " + sgId);
                    throw new InvalidParameterValueException("Unable to find port forwarding service with id " + sgId);
                }

                if (!_domainDao.isChildDomain(securityGroup.getDomainId(), userVm.getDomainId())) {
                    s_logger.warn("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                    throw new InvalidParameterValueException("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(publicIp);
                Map> mappedPublicPorts = new HashMap>();

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
                    }
                }

                List loadBalancers = _loadBalancerDao.listByIpAddress(publicIp);
                if (loadBalancers != null) {
                    for (LoadBalancerVO loadBalancer : loadBalancers) {
                        // load balancers don't have to be applied to an
                        // instance for there to be a conflict on the load
                        // balancers ip/port, so just
                        // map the public port to a pair of empty strings
                        mappedPublicPorts.put(loadBalancer.getPublicPort(), new Pair("", ""));
                    }
                }

                List firewallRulesToApply = new ArrayList();
                List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgId);
                for (NetworkRuleConfigVO netRule : netRules) {
                    Pair privateIpPort = mappedPublicPorts.get(netRule.getPublicPort());
                    if (privateIpPort != null) {
                        if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(netRule.getPrivatePort())) {
                            continue; // already mapped
                        } else {
                            throw new NetworkRuleConflictException("An existing service rule for " + publicIp + ":" + netRule.getPublicPort()
                                    + " already exists, found while trying to apply service rule " + netRule.getId() + " from port forwarding service " + securityGroup.getName() + ".");
                        }
                    }

                    FirewallRuleVO newFwRule = new FirewallRuleVO();
                    newFwRule.setEnabled(true);
                    newFwRule.setForwarding(true);
                    newFwRule.setPrivatePort(netRule.getPrivatePort());
                    newFwRule.setProtocol(netRule.getProtocol());
                    newFwRule.setPublicPort(netRule.getPublicPort());
                    newFwRule.setPublicIpAddress(publicIp);
                    newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                    newFwRule.setGroupId(netRule.getSecurityGroupId());

                    firewallRulesToApply.add(newFwRule);
                    _firewallRulesDao.persist(newFwRule);

                    String description = "created new ip forwarding rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                            + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
                }

                // now that individual rules have been created from the security group, save the security group mapping for this ip/vm instance
                SecurityGroupVMMapVO sgVmMap = new SecurityGroupVMMapVO(sgId, publicIp, vmId);
                _securityGroupVMMapDao.persist(sgVmMap);

                // Save off information for the event that the security group was applied
                EventVO event = new EventVO();
                event.setUserId(userId);
                event.setAccountId(userVm.getAccountId());
                event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY);
                event.setStartId(startEventId);
                event.setDescription("Successfully applied port forwarding service " + securityGroup.getName() + " to virtual machine " + userVm.getName());
                String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId+"\nnumRules="+firewallRulesToApply.size()+"\ndcId="+userVm.getDataCenterId();
                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
                _eventDao.persist(event);

                _networkMgr.updateFirewallRules(publicIp, firewallRulesToApply, router);
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public void removeSecurityGroup(RemovePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	
    	Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long securityGroupId = cmd.getId();
        String publicIp = cmd.getPublicIp();
        Long vmId = cmd.getVirtualMachineId();
        
        //verify input parameters
        SecurityGroupVO securityG = _securityGroupDao.findById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
            }
        }
        
        UserVmVO vmInstance = findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing port forwarding services for Vm with Id: "+vmId);

        /*TODO : ASK KRIS AS TO WHAT DO WE DO WITH THIS PART IN THE EXECUTOR CODE
        UserVmVO userVm = userVmDao.findById(param.getInstanceId());
        if(userVm == null)
        	return null;
        
        if (userVm.getDomainRouterId() == null) {
        	return null;
        } else
        	return routerDao.findById(userVm.getDomainRouterId());
	    */
        removeSecurityGroup(userId, securityGroupId, publicIp, vmId, eventId);
    }
    
    @Override
    @DB
    public void removeSecurityGroup(long userId, long securityGroupId, String publicIp, long vmId, long startEventId) throws InvalidParameterValueException, PermissionDeniedException {
        // This gets complicated with overlapping rules. As an example:
        // security group 1 has the following port mappings: 22->22 on TCP,
        // 23->23 on TCP, 80->8080 on TCP
        // security group 2 has the following port mappings: 22->22 on TCP,
        // 7891->7891 on TCP
        // User assigns group 1 & 2 on 192.168.10.120 to vm 1
        // Later, user removed group 1 from 192.168.10.120 and vm 1
        // Final valid port mappings should be 22->22 and 7891->7891 which both
        // come from security group 2. The mapping
        boolean locked = false;
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Unable to find vm: " + vmId);
        }
        EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "Removing port forwarding services for Vm with Id: "+vmId, startEventId);
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
            throw new InvalidParameterValueException("Unable to find port forwarding service: " + securityGroupId);
        }

        DomainRouterVO router = null;
        if (userVm.getDomainRouterId() != null)
        	router = _routerDao.findById(userVm.getDomainRouterId());
        if (router == null) {
            throw new InvalidParameterValueException("Unable to find router for ip address: " + publicIp);
        }

        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe
                // for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }

            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User/account does not own supplied address");
            }

            txn.start();

            // get the account for writing events
            Account account = _accountDao.findById(userVm.getAccountId());
            {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on existing SG mappings
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                for (FirewallRuleVO fwRule : fwRulesToRemove) {
                    fwRule.setEnabled(false);
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "ip forwarding";
                String level = EventVO.LEVEL_INFO;

                for (FirewallRuleVO fwRule : updatedRules) {
                    _firewallRulesDao.remove(fwRule.getId());

                    description = "deleted " + ruleName + " rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                            + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), level, type, description);
                }
            }

            // since we know these groups all pass muster, just keep track
            // of the public ports we are mapping on this public IP and
            // don't duplicate
            List alreadyMappedPorts = new ArrayList();
            List fwRulesToAdd = new ArrayList();
            List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                if (sgVmMapping.getSecurityGroupId() == securityGroupId) {
                    _securityGroupVMMapDao.remove(sgVmMapping.getId());
                } else {
                    List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgVmMapping.getSecurityGroupId());
                    for (NetworkRuleConfigVO netRule : netRules) {
                        if (!alreadyMappedPorts.contains(netRule.getPublicPort())) {
                            FirewallRuleVO newFwRule = new FirewallRuleVO();
                            newFwRule.setEnabled(true);
                            newFwRule.setForwarding(true);
                            newFwRule.setPrivatePort(netRule.getPrivatePort());
                            newFwRule.setProtocol(netRule.getProtocol());
                            newFwRule.setPublicPort(netRule.getPublicPort());
                            newFwRule.setPublicIpAddress(publicIp);
                            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                            newFwRule.setGroupId(netRule.getSecurityGroupId());

                            fwRulesToAdd.add(newFwRule);

                            alreadyMappedPorts.add(netRule.getPublicPort());
                        }
                    }
                }
            }

            for (FirewallRuleVO addedRule : fwRulesToAdd) {
                _firewallRulesDao.persist(addedRule);

                String description = "created new ip forwarding rule [" + addedRule.getPublicIpAddress() + ":" + addedRule.getPublicPort() + "]->["
                        + addedRule.getPrivateIpAddress() + ":" + addedRule.getPrivatePort() + "]" + " " + addedRule.getProtocol();

                EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
            }

            // save off an event for removing the security group
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(userVm.getAccountId());
            event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
            event.setDescription("Successfully removed port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
            event.setLevel(EventVO.LEVEL_INFO);
            String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
            event.setParameters(params);
            _eventDao.persist(event);

            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
        }
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
            } else {
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        if (domainId != null) {
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object accountName = cmd.getAccountName();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        Object name = cmd.getServiceOfferingName();
        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            }
        } else if (domainId != null) {
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    @Override
    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object name = cmd.getClusterName();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
        Long accountId = null;
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (state != null) {
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        if (accountName != null && domainId != null) {
        }

        return _hostPodDao.search(sc, searchFilter);
    }

    @Override
    public List searchForZones(Criteria c) {
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

        return _vlanDao.search(sc, searchFilter);
    }
    
    @Override
    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);

        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        }
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        Account account = (Account)UserContext.current().getAccountObject();
        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        } else {
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
        return _launchPermissionDao.listPermittedTemplates(accountId);
    }

    @Override
    public List listPods(long dataCenterId) {
        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }

    @Override
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
        if (isPublic != null) {
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {
        return _vmInstanceDao.findById(vmId);
    }

    @Override
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    @Override
    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
                    }
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                    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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            if (domainId != null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);

        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }


        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }


        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	else
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
                mac.update(unsignedRequest.getBytes());

    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
            }
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
        if (type != null) {
            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();
        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
            if (domain != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}
    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {

                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {

            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
        Long instanceId = cmd.getVirtualMachineId();
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

    @Override
        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
        if (systemVm == null) {
            
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
		if(rootVolume!=null){
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        return vmGroup;
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

<<<<<<< HEAD
=======
            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

            	else{
    @Override
    	job.setUserId(UserContext.current().getUserId());
    public long removeSecurityGroupAsync(Long userId, long securityGroupId, String publicIp, long vmId) {
        UserVm userVm = _userVmDao.findById(vmId);
        long eventId = saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing security groups for Vm with Id: "+vmId);
        SecurityGroupParam param = new SecurityGroupParam(userId, securityGroupId, null, publicIp, vmId, eventId);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
    	job.setUserId(UserContext.current().getUserId());
    	job.setAccountId(userVm.getAccountId());
        job.setCmd("RemoveSecurityGroup");
        job.setCmdInfo(gson.toJson(param));
        return _asyncMgr.submitAsyncJob(job);
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map mappedPublicPorts = new HashMap();
        Map publicPortToProtocolMapping=new HashMap();
        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
            	
                //mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            	if(mappedPublicPorts.containsKey(fwRule.getPublicPort())){
            		mappedPublicPorts.put(fwRule.getPublicPort(), mappedPublicPorts.get(fwRule.getPublicPort()).append(";").append(fwRule.getPrivateIpAddress().concat(",").concat(fwRule.getPrivatePort())));
            	}
            	else{
            		mappedPublicPorts.put(fwRule.getPublicPort(), new StringBuilder(fwRule.getPrivateIpAddress()+","+fwRule.getPrivatePort()));
            	}
            	
            	if(publicPortToProtocolMapping.containsKey(fwRule.getPublicPort())){
            		publicPortToProtocolMapping.put(fwRule.getPublicPort(), publicPortToProtocolMapping.get(fwRule.getPublicPort()).append(";").append(fwRule.getProtocol()));
            	}
            		publicPortToProtocolMapping.put(fwRule.getPublicPort(),new StringBuilder(fwRule.getProtocol()));
            	}
            }
        }

        if (userVm != null) 
        {
        	if(mappedPublicPorts.size()>0)
        	{
        		StringBuilder privateIpPortIntermediate = mappedPublicPorts.get(publicPort);
	            String privateIpPort = null;
	            if(privateIpPortIntermediate != null && privateIpPortIntermediate.length()>0)
	            	privateIpPort = privateIpPortIntermediate.toString();//eg: 10.1.1.2,30 ; 10.1.1.2,34
	            
	            if (privateIpPort != null && privateIpPort.length()>0) 
	            {
	                String publicPortProtocol = publicPortToProtocolMapping.get(publicPort).toString();
	                String[] privateIpPortPairs = privateIpPort.toString().split(";"); //eg. 10.1.1.2,30
	                String[] privateIpAndPortStr;
	                boolean errFlag = false;
	
	            	for(String pair: privateIpPortPairs)
	            	{
	            		privateIpAndPortStr = pair.split(",");//split into 10.1.1.2 & 30
	            	
		                if (privateIpAndPortStr[0].equals(userVm.getGuestIpAddress()) && privateIpAndPortStr[1].equals(privatePort)) {
		                    if (s_logger.isDebugEnabled()) {
		                        s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
		                    }
		                    return null; // already mapped
		                }
		                //at this point protocol string looks like: eg. tcp;udp || tcp || udp || udp;tcp 
		                else if(!publicPortProtocol.contains(protocol))//check if this public port is mapped to the protocol or not
		                {
		                	//this is the case eg:
		                	//pub:1 pri:2 pro: tcp
		                	//pub 1 pri:3 pro: udp
		                	break; //we break here out of the loop, for the record to be created
		                }
		                else
		                {
		                	errFlag = true;
	//	                    throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
	//	                            + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
	//	                            + securityGroupId.toString() + "."));
		                }
	            	}
	            	
	            	if(errFlag)
	                    throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
	                            + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
	                            + securityGroupId.toString() + "."));
	            }
        	}
            FirewallRuleVO newFwRule = new FirewallRuleVO();
            newFwRule.setEnabled(true);
            newFwRule.setForwarding(true);
            newFwRule.setPrivatePort(privatePort);
            newFwRule.setProtocol(protocol);
            newFwRule.setPublicPort(publicPort);
            newFwRule.setPublicIpAddress(ipAddress);
            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
            newFwRule.setGroupId(securityGroupId);

            // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
            // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
            // behavior is preserved here by persisting the rule before sending it to the agent.
            _firewallRulesDao.persist(newFwRule);

            boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

            // Save and create the event
            String description;
            String ruleName = "ip forwarding";
            String level = EventVO.LEVEL_INFO;
            Account account = _accountDao.findById(userVm.getAccountId());

            if (success == true) {
                description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                        + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
            } else {
                level = EventVO.LEVEL_ERROR;
                description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                        + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
            }

            saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

            return newFwRule;
        }
        return null;
    }

    @DB
    protected NetworkRuleConfigVO createNetworkRuleConfig(long userId, long securityGroupId, String port, String privatePort, String protocol, String algorithm)
            throws NetworkRuleConflictException {
        if (protocol == null) {
            protocol = "TCP";
        }

        Long ruleId = null;
        Transaction txn = Transaction.currentTxn();
        try {
            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            txn.start();
            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            netRule = _networkRuleConfigDao.persist(netRule);
            ruleId = netRule.getId();
            txn.commit();

            // check if we are within context of async-execution
            AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
            if (asyncExecutor != null) {
                AsyncJobVO job = asyncExecutor.getJob();

                if (s_logger.isInfoEnabled())
                    s_logger.info("Created a new port forwarding service rule instance " + ruleId + ", update async job-" + job.getId() + " progress status");

                _asyncMgr.updateAsyncJobAttachment(job.getId(), "network_rule_config", ruleId);
                _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, ruleId);
            }

            txn.start();
            if (ruleId != null) {
                List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
                if ((sgMappings != null) && !sgMappings.isEmpty()) {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), Long.valueOf(securityGroupId));
                    }
                }

                NetworkRuleConfigVO rule = _networkRuleConfigDao.findById(ruleId);
                rule.setCreateStatus(AsyncInstanceCreateStatus.Created);
                _networkRuleConfigDao.update(ruleId, rule);
            }

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();

            if (ruleId != null) {
                txn.start();
                NetworkRuleConfigVO rule = _networkRuleConfigDao.findById(ruleId);
                rule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                _networkRuleConfigDao.update(ruleId, rule);
                txn.commit();
            }

            if (ex instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) ex;
            }
        AsyncJobVO job = new AsyncJobVO();
            s_logger.error("Unexpected exception creating port forwarding service rule (pfServiceId:" + securityGroupId + ",port:" + port + ",privatePort:" + privatePort + ",protocol:" + protocol + ")",
                    ex);
        }

        return _networkRuleConfigDao.findById(ruleId);
    }

    @Override
    public boolean deleteNetworkRuleConfig(long userId, long networkRuleId) {
        try {
            NetworkRuleConfigVO netRule = _networkRuleConfigDao.findById(networkRuleId);
            if (netRule != null) {
                List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
                if ((sgMappings != null) && !sgMappings.isEmpty()) {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        if (userVm != null) {
                            List fwRules = _firewallRulesDao.listIPForwarding(sgMapping.getIpAddress(), netRule.getPublicPort(), true);
                            FirewallRuleVO rule = null;
                            for (FirewallRuleVO fwRule : fwRules) {
                                if (fwRule.getPrivatePort().equals(netRule.getPrivatePort()) && fwRule.getPrivateIpAddress().equals(userVm.getGuestIpAddress())) {
                                    rule = fwRule;
                                    break;
                                }
                            }

                            if (rule != null) {
                                rule.setEnabled(false);
                                _networkMgr.updateFirewallRule(rule, null, null);

                                // Save and create the event
                                Account account = _accountDao.findById(userVm.getAccountId());

                                _firewallRulesDao.remove(rule.getId());
                                String description = "deleted ip forwarding rule [" + rule.getPublicIpAddress() + ":" + rule.getPublicPort() + "]->[" + rule.getPrivateIpAddress()
                                                     + ":" + rule.getPrivatePort() + "]" + " " + rule.getProtocol();

                                saveEvent(Long.valueOf(userId), account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_DELETE, description);
                            }
                        }
                    }
                }
                _networkRuleConfigDao.remove(netRule.getId());
            }
        } catch (Exception ex) {
            s_logger.error("Unexpected exception deleting port forwarding service rule " + networkRuleId, ex);
            return false;
        }

        return true;
    }

    @Override
    public long deleteNetworkRuleConfigAsync(long userId, Account account, Long networkRuleId) throws PermissionDeniedException {
        // do a quick permissions check to make sure the account is either an
        // admin or the owner of the security group to which the network rule
        // belongs
        NetworkRuleConfigVO netRule = _networkRuleConfigDao.findById(networkRuleId);
        long accountId = Account.ACCOUNT_ID_SYSTEM;
        if (netRule != null) {
            SecurityGroupVO sg = _securityGroupDao.findById(netRule.getSecurityGroupId());
            if (account != null) {
                if (!BaseCmd.isAdmin(account.getType())) {
                    if ((sg.getAccountId() != account.getId())) {
                        throw new PermissionDeniedException("Unable to delete port forwarding service rule " + networkRuleId + "; account: " + account.getAccountName() + " is not the owner");
                    }
                } else if (!isChildDomain(account.getDomainId(), sg.getDomainId())) {
                    throw new PermissionDeniedException("Unable to delete port forwarding service rule " + networkRuleId + "; account: " + account.getAccountName() + " is not an admin in the domain hierarchy.");
                }
            }
            if (sg != null) {
                accountId = sg.getAccountId();
            }
        } else {
            return 0L;  // failed to delete due to netRule not found
        }

        Gson gson = GsonHelper.getBuilder().create();

    	job.setAccountId(accountId);
        job.setCmd("DeleteNetworkRuleConfig");
        job.setCmdInfo(gson.toJson(networkRuleId));
        
        return _asyncMgr.submitAsyncJob(job);
    }

    @DB
    protected boolean deleteIpForwardingRule(long userId, long accountId, String publicIp, String publicPort, String privateIp, String privatePort, String proto)
            throws PermissionDeniedException, InvalidParameterValueException, InternalErrorException {

        Transaction txn = Transaction.currentTxn();
        boolean locked = false;
        try {
            AccountVO accountVO = _accountDao.findById(accountId);
            if (accountVO == null) {
                // throw this exception because hackers can use the api to probe
                // for existing user ids
                throw new PermissionDeniedException("Account does not own supplied address");
            }
            // although we are not writing these values to the DB, we will check
            // them out of an abundance
            // of caution (may not be warranted)
            if (!NetUtils.isValidPort(publicPort) || !NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("Invalid value for port");
            }
//            if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//                throw new InvalidParameterValueException("Invalid private ip address");
//            }
            if (!NetUtils.isValidProto(proto)) {
                throw new InvalidParameterValueException("Invalid protocol");
            }
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }

            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != accountId)) {
                // FIXME: if admin account, make sure the user is visible in the
                // admin's domain, or has that checking been done by this point?
                if (!BaseCmd.isAdmin(accountVO.getType())) {
                    throw new PermissionDeniedException("User/account does not own supplied address");
                }
            }

            txn.start();

            List fwdings = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, proto);
            FirewallRuleVO fwRule = null;
            if (fwdings.size() == 0) {
                throw new InvalidParameterValueException("No such rule");
            } else if (fwdings.size() == 1) {
                fwRule = fwdings.get(0);
                if (fwRule.getPrivateIpAddress().equalsIgnoreCase(privateIp) && fwRule.getPrivatePort().equals(privatePort)) {
                    _firewallRulesDao.expunge(fwRule.getId());
                } else {
                    throw new InvalidParameterValueException("No such rule");
                }
            } else {
                throw new InternalErrorException("Multiple matches. Please contact support");
            }
            fwRule.setEnabled(false);
            boolean success = _networkMgr.updateFirewallRule(fwRule, null, null);
            if (!success) {
                throw new InternalErrorException("Failed to update router");
            }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
Solution content
            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

            }
        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
            } else {
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        }
        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }
        if (domainId != null) {
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
        } else if (domainId != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

    @Override
        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object accountName = cmd.getAccountName();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object name = cmd.getServiceOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
        if (state != null) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    @Override
    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object name = cmd.getClusterName();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _hostPodDao.search(sc, searchFilter);
    }

    @Override
    public List searchForZones(Criteria c) {
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        if (accountName != null && domainId != null) {
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

        return _vlanDao.search(sc, searchFilter);
    }
    
    @Override
    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

            
        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);

        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        }
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        } else {
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
        return _launchPermissionDao.listPermittedTemplates(accountId);
    }

    @Override
    public List listPods(long dataCenterId) {

        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }

    @Override
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();
		
        }

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        }
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
        if (isPublic != null) {
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {
        return _vmInstanceDao.findById(vmId);
    }
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    @Override
    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {

                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
                }
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            }
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
            } else {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	else
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate

                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
        }

                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
        
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {

                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
    @Override
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
        } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        }
        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
            } else if (account.getId() != lbAcctId) {
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
        return null;
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

            } else if (ipAddressOwner != null) {
        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
    }
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
        
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
        }
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Catch clause
Comment
If statement
Method declaration
Method invocation
Method signature
Try statement
Variable
Chunk
Conflicting content
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
<<<<<<< HEAD
        }
=======
            _firewallRulesDao.expunge(fwRule.getId());
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
Solution content
        return success;
    }


        return user;

/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */
package com.cloud.server;

import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.manager.AgentManager;
import com.cloud.alert.AlertManager;
import com.cloud.alert.AlertVO;
import com.cloud.alert.dao.AlertDao;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AssignPortForwardingServiceCmd;
import com.cloud.api.commands.CreateDomainCmd;
import com.cloud.api.commands.CreatePortForwardingServiceCmd;
import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd;
import com.cloud.api.commands.CreateUserCmd;
import com.cloud.api.commands.DeleteDomainCmd;
import com.cloud.api.commands.DeletePortForwardingServiceCmd;
import com.cloud.api.commands.DeletePreallocatedLunCmd;
import com.cloud.api.commands.DeleteUserCmd;
import com.cloud.api.commands.DeployVMCmd;
import com.cloud.api.commands.EnableAccountCmd;
import com.cloud.api.commands.EnableUserCmd;
import com.cloud.api.commands.ExtractVolumeCmd;
import com.cloud.api.commands.GetCloudIdentifierCmd;
import com.cloud.api.commands.ListAccountsCmd;
import com.cloud.api.commands.ListAlertsCmd;
import com.cloud.api.commands.ListAsyncJobsCmd;
import com.cloud.api.commands.ListCapabilitiesCmd;
import com.cloud.api.commands.ListCapacityCmd;
import com.cloud.api.commands.ListCfgsByCmd;
import com.cloud.api.commands.ListClustersCmd;
import com.cloud.api.commands.ListDiskOfferingsCmd;
import com.cloud.api.commands.ListDomainChildrenCmd;
import com.cloud.api.commands.ListDomainsCmd;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.api.commands.ListGuestOsCategoriesCmd;
import com.cloud.api.commands.ListGuestOsCmd;
import com.cloud.api.commands.ListHostsCmd;
import com.cloud.api.commands.ListIsosCmd;

import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd;
import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPortForwardingServiceRulesCmd;
import com.cloud.api.commands.ListPortForwardingServicesByVmCmd;
import com.cloud.api.commands.ListPortForwardingServicesCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListStoragePoolsAndHostsCmd;
import com.cloud.api.commands.ListStoragePoolsCmd;
import com.cloud.api.commands.ListSystemVMsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListTemplatesCmd;
import com.cloud.api.commands.ListUsersCmd;
import com.cloud.api.commands.ListVMGroupsCmd;
import com.cloud.api.commands.ListVMsCmd;
import com.cloud.api.commands.ListVlanIpRangesCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.ListZonesByCmd;
import com.cloud.api.commands.LockAccountCmd;
import com.cloud.api.commands.LockUserCmd;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.commands.RebootSystemVmCmd;
import com.cloud.api.commands.RegisterCmd;
import com.cloud.api.commands.RegisterPreallocatedLunCmd;
import com.cloud.api.commands.RemovePortForwardingServiceCmd;
import com.cloud.api.commands.StartSystemVMCmd;
import com.cloud.api.commands.StopSystemVmCmd;
import com.cloud.api.commands.UpdateAccountCmd;
import com.cloud.api.commands.UpdateDomainCmd;
import com.cloud.api.commands.UpdateIPForwardingRuleCmd;
import com.cloud.api.commands.UpdateIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.UpdateTemplatePermissionsCmd;
import com.cloud.api.commands.UpdateUserCmd;
import com.cloud.api.commands.UpdateVMGroupCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobResult;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.async.dao.AsyncJobDao;
import com.cloud.async.executor.ExtractJobResultObject;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventTypes;
import com.cloud.event.EventUtils;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.info.ConsoleProxyInfo;
import com.cloud.network.FirewallRuleVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVMMapVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkRuleConfigVO;
import com.cloud.network.SecurityGroupVMMapVO;
import com.cloud.network.SecurityGroupVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.security.NetworkGroupManager;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.network.security.dao.NetworkGroupDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.auth.UserAuthenticator;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.DiskTemplateVO;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Snapshot.SnapshotType;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload.Type;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.VolumeStats;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.DiskTemplateDao;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.LaunchPermissionDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotPolicyDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.UploadDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDao.TemplateFilter;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.preallocatedlun.PreallocatedLunVO;
import com.cloud.storage.preallocatedlun.dao.PreallocatedLunDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.upload.UploadMonitor;
import com.cloud.template.TemplateManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserAccountVO;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserAccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.DateUtil;
import com.cloud.utils.DateUtil.IntervalType;
import com.cloud.utils.EnumUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVMMapVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.InstanceGroupVMMapDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

public class ManagementServerImpl implements ManagementServer {	
    public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());

    private final AccountManager _accountMgr;
    private final AgentManager _agentMgr;
    private final ConfigurationManager _configMgr;
    private final FirewallRulesDao _firewallRulesDao;
    private final SecurityGroupDao _securityGroupDao;
	private final NetworkGroupDao _networkSecurityGroupDao;
    private final LoadBalancerDao _loadBalancerDao;
    private final NetworkRuleConfigDao _networkRuleConfigDao;
    private final SecurityGroupVMMapDao _securityGroupVMMapDao;
    private final IPAddressDao _publicIpAddressDao;
    private final DataCenterIpAddressDaoImpl _privateIpAddressDao;
    private final LoadBalancerVMMapDao _loadBalancerVMMapDao;
    private final DomainRouterDao _routerDao;
    private final ConsoleProxyDao _consoleProxyDao;
    private final ClusterDao _clusterDao;
    private final SecondaryStorageVmDao _secStorageVmDao;
    private final EventDao _eventDao;
    private final DataCenterDao _dcDao;
    private final VlanDao _vlanDao;
    private final AccountVlanMapDao _accountVlanMapDao;
    private final PodVlanMapDao _podVlanMapDao;
    private final HostDao _hostDao;
    private final UserDao _userDao;
    private final UserVmDao _userVmDao;
    private final ConfigurationDao _configDao;
    private final NetworkManager _networkMgr;
    private final UserVmManager _vmMgr;
    private final ConsoleProxyManager _consoleProxyMgr;
    private final SecondaryStorageVmManager _secStorageVmMgr;
    private final ServiceOfferingDao _offeringsDao;
    private final DiskOfferingDao _diskOfferingDao;
    private final VMTemplateDao _templateDao;
    private final LaunchPermissionDao _launchPermissionDao;
    private final DomainDao _domainDao;
    private final AccountDao _accountDao;
    private final ResourceLimitDao _resourceLimitDao;
    private final UserAccountDao _userAccountDao;
    private final AlertDao _alertDao;
    private final CapacityDao _capacityDao;
    private final SnapshotDao _snapshotDao;
    private final SnapshotPolicyDao _snapshotPolicyDao;
    private final GuestOSDao _guestOSDao;
    private final GuestOSCategoryDao _guestOSCategoryDao;
    private final StoragePoolDao _poolDao;
    private final StoragePoolHostDao _poolHostDao;
    private final StorageManager _storageMgr;
    private final UserVmDao _vmDao;

    }
    private final Adapters _userAuthenticators;
    private final HostPodDao _hostPodDao;
    private final UserStatisticsDao _userStatsDao;
    private final VMInstanceDao _vmInstanceDao;
    private final VolumeDao _volumeDao;
    private final DiskTemplateDao _diskTemplateDao;
    private final AlertManager _alertMgr;
    private final AsyncJobDao _jobDao;
    private final AsyncJobManager _asyncMgr;
    private final TemplateManager _tmpltMgr;
    private final SnapshotManager _snapMgr;
    private final NetworkGroupManager _networkGroupMgr;
    private final int _purgeDelay;
    private final boolean _directAttachNetworkExternalIpAllocator;
    private final PreallocatedLunDao _lunDao;
    private final InstanceGroupDao _vmGroupDao;
    private final InstanceGroupVMMapDao _groupVMMapDao;
    private final UploadMonitor _uploadMonitor;
    private final UploadDao _uploadDao;

    private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
    private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));

    private final StatsCollector _statsCollector;

    private final Map _configs;

    private String _domain;
    private final int _routerRamSize;
    private final int _proxyRamSize;
    private final int _ssRamSize;

    private final Map _availableIdsMap;

	private boolean _networkGroupsEnabled = false;

    private boolean _isHypervisorSnapshotCapable = false;

    protected ManagementServerImpl() {
        ComponentLocator locator = ComponentLocator.getLocator(Name);
        _lunDao = locator.getDao(PreallocatedLunDao.class);
        _configDao = locator.getDao(ConfigurationDao.class);
        _routerDao = locator.getDao(DomainRouterDao.class);
        _eventDao = locator.getDao(EventDao.class);
        _dcDao = locator.getDao(DataCenterDao.class);
        _vlanDao = locator.getDao(VlanDao.class);
        _accountVlanMapDao = locator.getDao(AccountVlanMapDao.class);
        _podVlanMapDao = locator.getDao(PodVlanMapDao.class);
        _hostDao = locator.getDao(HostDao.class);
        _hostPodDao = locator.getDao(HostPodDao.class);
        _jobDao = locator.getDao(AsyncJobDao.class);
        _clusterDao = locator.getDao(ClusterDao.class);

        _accountMgr = locator.getManager(AccountManager.class);
        _agentMgr = locator.getManager(AgentManager.class);
        _configMgr = locator.getManager(ConfigurationManager.class);
        _networkMgr = locator.getManager(NetworkManager.class);
        _vmMgr = locator.getManager(UserVmManager.class);
        _consoleProxyMgr = locator.getManager(ConsoleProxyManager.class);
        _secStorageVmMgr = locator.getManager(SecondaryStorageVmManager.class);
        _storageMgr = locator.getManager(StorageManager.class);
        _firewallRulesDao = locator.getDao(FirewallRulesDao.class);
        _securityGroupDao = locator.getDao(SecurityGroupDao.class);
        _networkSecurityGroupDao  = locator.getDao(NetworkGroupDao.class);
        _loadBalancerDao = locator.getDao(LoadBalancerDao.class);
        _networkRuleConfigDao = locator.getDao(NetworkRuleConfigDao.class);
        _securityGroupVMMapDao = locator.getDao(SecurityGroupVMMapDao.class);
        _publicIpAddressDao = locator.getDao(IPAddressDao.class);
        _privateIpAddressDao = locator.getDao(DataCenterIpAddressDaoImpl.class);
        _loadBalancerVMMapDao = locator.getDao(LoadBalancerVMMapDao.class);
        _consoleProxyDao = locator.getDao(ConsoleProxyDao.class);
        _secStorageVmDao = locator.getDao(SecondaryStorageVmDao.class);
        _userDao = locator.getDao(UserDao.class);
        _userVmDao = locator.getDao(UserVmDao.class);
        _offeringsDao = locator.getDao(ServiceOfferingDao.class);
        _diskOfferingDao = locator.getDao(DiskOfferingDao.class);
        _templateDao = locator.getDao(VMTemplateDao.class);
        _launchPermissionDao = locator.getDao(LaunchPermissionDao.class);
        _domainDao = locator.getDao(DomainDao.class);
        _accountDao = locator.getDao(AccountDao.class);
                newAccount.setState("enabled");
        _resourceLimitDao = locator.getDao(ResourceLimitDao.class);
        _userAccountDao = locator.getDao(UserAccountDao.class);
        _alertDao = locator.getDao(AlertDao.class);
        _capacityDao = locator.getDao(CapacityDao.class);
        _snapshotDao = locator.getDao(SnapshotDao.class);
        _snapshotPolicyDao = locator.getDao(SnapshotPolicyDao.class);
        _guestOSDao = locator.getDao(GuestOSDao.class);
        _guestOSCategoryDao = locator.getDao(GuestOSCategoryDao.class);
        _poolDao = locator.getDao(StoragePoolDao.class);
        _poolHostDao = locator.getDao(StoragePoolHostDao.class);
        _vmDao = locator.getDao(UserVmDao.class);
        _vmGroupDao = locator.getDao(InstanceGroupDao.class);
        _groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class);
        _uploadDao = locator.getDao(UploadDao.class);

        _configs = _configDao.getConfiguration();
        _userStatsDao = locator.getDao(UserStatisticsDao.class);
        _vmInstanceDao = locator.getDao(VMInstanceDao.class);
        _volumeDao = locator.getDao(VolumeDao.class);
        _diskTemplateDao = locator.getDao(DiskTemplateDao.class);
        _alertMgr = locator.getManager(AlertManager.class);
        _asyncMgr = locator.getManager(AsyncJobManager.class);
        _tmpltMgr = locator.getManager(TemplateManager.class);
        _snapMgr = locator.getManager(SnapshotManager.class);
        _networkGroupMgr = locator.getManager(NetworkGroupManager.class);
        _uploadMonitor = locator.getManager(UploadMonitor.class);                
        
        _userAuthenticators = locator.getAdapters(UserAuthenticator.class);
        if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
            s_logger.error("Unable to find an user authenticator.");
        }

        _domain = _configs.get("domain");
        if (_domain == null) {
            _domain = ".myvm.com";
        }
        if (!_domain.startsWith(".")) {
            _domain = "." + _domain;
        }

        String value = _configs.get("account.cleanup.interval");
        int cleanup = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour.

        // Parse the max number of UserVMs and public IPs from server-setup.xml,
        // and set them in the right places
        _routerRamSize = NumbersUtil.parseInt(_configs.get("router.ram.size"),NetworkManager.DEFAULT_ROUTER_VM_RAMSIZE);
        _proxyRamSize = NumbersUtil.parseInt(_configs.get("consoleproxy.ram.size"), ConsoleProxyManager.DEFAULT_PROXY_VM_RAMSIZE);
        _ssRamSize = NumbersUtil.parseInt(_configs.get("secstorage.ram.size"), SecondaryStorageVmManager.DEFAULT_SS_VM_RAMSIZE);

        _directAttachNetworkExternalIpAllocator =
        										Boolean.parseBoolean(_configs.get("direct.attach.network.externalIpAllocator.enabled"));
        
        _statsCollector = StatsCollector.getInstance(_configs);
        _executor.scheduleAtFixedRate(new AccountCleanupTask(), cleanup, cleanup, TimeUnit.SECONDS);

        _purgeDelay = NumbersUtil.parseInt(_configs.get("event.purge.delay"), 0);
        if(_purgeDelay != 0){
            _eventExecutor.scheduleAtFixedRate(new EventPurgeTask(), cleanup, cleanup, TimeUnit.SECONDS);
        }
        
        String[] availableIds = TimeZone.getAvailableIDs();
        _availableIdsMap = new HashMap(availableIds.length);
        for (String id: availableIds) {
            _availableIdsMap.put(id, true);
        }
        String enabled =_configDao.getValue("direct.attach.network.groups.enabled");
		if ("true".equalsIgnoreCase(enabled)) {
			_networkGroupsEnabled = true;
		}
 		
		String hypervisorType = _configDao.getValue("hypervisor.type");
        _isHypervisorSnapshotCapable  = hypervisorType.equals(Hypervisor.Type.XenServer.name());
    }

    protected Map getConfigs() {
        return _configs;
    }

    @Override
    public StorageStats getStorageStatistics(long hostId) {
        return _statsCollector.getStorageStats(hostId);
    }
    
    @Override
        }
    public PreallocatedLunVO registerPreallocatedLun(RegisterPreallocatedLunCmd cmd) {
        Long zoneId = cmd.getZoneId();
        String portal = cmd.getPortal();
        String targetIqn = cmd.getTargetIqn();
        Integer lun = cmd.getLun();
        Long size = cmd.getDiskSize();
        String t = cmd.getTags();

        String[] tags = null;
        if (t != null) {
            tags = t.split(",");
            for (int i = 0; i < tags.length; i++) {
                tags[i] = tags[i].trim();
            }
        } else {
            tags = new String[0];
        }
        
        PreallocatedLunVO vo = new PreallocatedLunVO(zoneId, portal, targetIqn, lun, size);
        return _lunDao.persist(vo, tags);
    }
    
    @Override
    public boolean unregisterPreallocatedLun(DeletePreallocatedLunCmd cmd) throws IllegalArgumentException {
        Long id = cmd.getId();
    	PreallocatedLunVO lun = null;
    	if ((lun = _lunDao.findById(id)) == null) {
    		throw new IllegalArgumentException("Unable to find a LUN with ID " + id);
    	}
    	
    	if (lun.getTaken() != null) {
        			}
    		throw new IllegalArgumentException("The LUN is currently in use and cannot be deleted.");
    	}
    	
        return _lunDao.delete(id);
    }

    @Override
    public VolumeStats[] getVolumeStatistics(long[] volIds) {
        return _statsCollector.getVolumeStats(volIds);
    }

    @Override
    public UserAccount createUser(CreateUserCmd cmd) {
        Long accountId = null;
        String username = cmd.getUsername();
        String password = cmd.getPassword();
        String firstName = cmd.getFirstname();
        String lastName = cmd.getLastname();
        Long domainId = cmd.getDomainId();
        String email = cmd.getEmail();
        String timezone = cmd.getTimezone();
        String accountName = cmd.getAccountName();
        short userType = cmd.getAccountType().shortValue();
        try {
            if (accountName == null) {
                accountName = username;
            }
            if (domainId == null) {
                domainId = DomainVO.ROOT_DOMAIN;
            }

            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account != null) {
                if (account.getType() != userType) {
                    throw new CloudRuntimeException("Account " + accountName + " is not the correct account type for user " + username);
                }
                accountId = account.getId();
            }

            if (!_userAccountDao.validateUsernameInDomain(username, domainId)) {
                throw new CloudRuntimeException("The user " + username + " already exists in domain " + domainId);
            }

            if (accountId == null) {
                if ((userType < Account.ACCOUNT_TYPE_NORMAL) || (userType > Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given; unable to create user");
                }

                // create a new account for the user
                AccountVO newAccount = new AccountVO();
                if (domainId == null) {
                    // root domain is default
                    domainId = DomainVO.ROOT_DOMAIN;
                }

                if ((domainId != DomainVO.ROOT_DOMAIN) && (userType == Account.ACCOUNT_TYPE_ADMIN)) {
                    throw new CloudRuntimeException("Invalid account type " + userType + " given for an account in domain " + domainId + "; unable to create user.");
                }

                newAccount.setAccountName(accountName);
                newAccount.setDomainId(domainId);
                newAccount.setType(userType);
                newAccount = _accountDao.persist(newAccount);
                accountId = newAccount.getId();
            }

            if (accountId == null) {
                throw new CloudRuntimeException("Failed to create account for user: " + username + "; unable to create user");
            }

            UserVO user = new UserVO();
            user.setUsername(username);
            user.setPassword(password);
            user.setState("enabled");
            user.setFirstname(firstName);
            user.setLastname(lastName);
            user.setAccountId(accountId.longValue());
            user.setEmail(email);
            user.setTimezone(timezone);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Creating user: " + username + ", account: " + accountName + " (id:" + accountId + "), domain: " + domainId + " timezone:"+ timezone);
            }

            UserVO dbUser = _userDao.persist(user);
            
            _networkGroupMgr.createDefaultNetworkGroup(accountId);

            if (!user.getPassword().equals(dbUser.getPassword())) {
                throw new CloudRuntimeException("The user " + username + " being creating is using a password that is different than what's in the db");
            }
            EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_CREATE, "User, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId + " was created.");
            return _userAccountDao.findById(dbUser.getId());
        } catch (Exception e) {
        	EventUtils.saveEvent(new Long(1), new Long(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_CREATE, "Error creating user, " + username + " for accountId = " + accountId
                    + " and domainId = " + domainId);
            if (e instanceof CloudRuntimeException) {
                s_logger.info("unable to create user: " + e);
            } else {
                s_logger.warn("unknown exception creating user", e);
            }
            throw new CloudRuntimeException(e.getMessage());
        }
    }

    @Override
    public String updateAdminPassword(long userId, String oldPassword, String newPassword) {
        // String old = StringToMD5(oldPassword);
        // User user = getUser(userId);
        // if (old.equals(user.getPassword())) {
        UserVO userVO = _userDao.createForUpdate(userId);
        userVO.setPassword(StringToMD5(newPassword));
        _userDao.update(userId, userVO);
        return newPassword;
        // } else {
        // return null;
        // }
    }

    private String StringToMD5(String string) {
        MessageDigest md5;

        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new CloudRuntimeException("Error", e);
        }

        md5.reset();
        BigInteger pwInt = new BigInteger(1, md5.digest(string.getBytes()));

        // make sure our MD5 hash value is 32 digits long...
        StringBuffer sb = new StringBuffer();
        String pwStr = pwInt.toString(16);
        int padding = 32 - pwStr.length();
        for (int i = 0; i < padding; i++) {
            sb.append('0');
        }
        sb.append(pwStr);
        return sb.toString();
    }

    @Override
    public User getUser(long userId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId);
        }

        UserVO user = _userDao.getUser(userId);
        if (user == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with id " + userId);
            }
            return null;

    @Override
    public User getUser(long userId, boolean active) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user with id: " + userId + " and active = " + active);
        }

        if (active) {
            return _userDao.getUser(userId);
        } else {
            return _userDao.findById(userId);
        }
    }

    @Override
    public UserAccount getUserAccount(String username, Long domainId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving user: " + username + " in domain " + domainId);
        }

        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        return userAccount;
    }

    private UserAccount getUserAccount(String username, String password, Long domainId) {
        		}
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
        }

        UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
        if (userAccount == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find user with name " + username + " in domain " + domainId);
            }
            return null;
        }

        if (!userAccount.getState().equals("enabled") || !userAccount.getAccountState().equals("enabled")) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("user " + username + " in domain " + domainId + " is disabled/locked (or account is disabled/locked), returning null");
            }
            return null;
        }

        // We only use the first adapter even if multiple have been
        // configured
        Enumeration en = _userAuthenticators.enumeration();
        UserAuthenticator authenticator = en.nextElement();
        boolean authenticated = authenticator.authenticate(username, password, domainId);

        if (authenticated) {
        	return userAccount;
        } else {
        	return null;
        }
    }

    private boolean deleteUserInternal(long userId) {
        UserAccount userAccount = null;
        Long accountId = null;
        String username = null;
        try {
            UserVO user = _userDao.findById(userId);
            if (user == null || user.getRemoved() != null) {
                return true;
            }
            username = user.getUsername();
            boolean result = _userDao.remove(userId);
            if (!result) {
                s_logger.error("Unable to remove the user with id: " + userId + "; username: " + user.getUsername());
                return false;
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("User is removed, id: " + userId + "; username: " + user.getUsername());
            }

            accountId = user.getAccountId();
            userAccount = _userAccountDao.findById(userId);

            List users = _userDao.listByAccount(accountId);
            if (users.size() != 0) {
                s_logger.debug("User (" + userId + "/" + user.getUsername() + ") is deleted but there's still other users in the account so not deleting account.");
                return true;
            }

            result = _accountDao.remove(accountId);
            if (!result) {
            }
        }
                s_logger.error("Unable to delete account " + accountId);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Remove account " + accountId);
            }

            AccountVO account = _accountDao.findById(accountId);
            deleteAccount(account);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "User " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + userAccount.getDomainId() + " was deleted.");
            return true;
        } catch (Exception e) {
            s_logger.error("exception deleting user: " + userId, e);
            long domainId = 0L;
            if (userAccount != null)
                domainId = userAccount.getDomainId();
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_DELETE, "Error deleting user " + username + " (id: " + userId
                    + ") for accountId = " + accountId + " and domainId = " + domainId);
            return false;
        }
    }

    public boolean deleteAccount(AccountVO account) {
        long accountId = account.getId();
        long userId = 1L; // only admins can delete users, pass in userId 1 XXX: Shouldn't it be userId 2.
        boolean accountCleanupNeeded = false;
        
        try {
        	//delete all vm groups belonging to accont
        	List groups = _vmGroupDao.listByAccountId(accountId);
            for (InstanceGroupVO group : groups) {
                if (!_vmMgr.deleteVmGroup(group.getId())) {
                    s_logger.error("Unable to delete group: " + group.getId());
                    accountCleanupNeeded = true;
                } 
            }
        	
            // Delete the snapshots dir for the account. Have to do this before destroying the VMs.
            boolean success = _snapMgr.deleteSnapshotDirsForAccount(accountId);
            if (success) {
                s_logger.debug("Successfully deleted snapshots directories for all volumes under account " + accountId + " across all zones");
            }
            // else, there are no snapshots, hence no directory to delete.
            
            // Destroy the account's VMs
            List vms = _userVmDao.listByAccountId(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of vms (accountId=" + accountId + "): " + vms.size());
            }

            for (UserVmVO vm : vms) {
                if (!_vmMgr.destroyVirtualMachine(userId, vm.getId())) {
                    s_logger.error("Unable to destroy vm: " + vm.getId());
                    accountCleanupNeeded = true;
                } 
            }
            
            // Mark the account's volumes as destroyed
            List volumes = _volumeDao.findDetachedByAccount(accountId);
            for (VolumeVO volume : volumes) {
            	if(volume.getPoolId()==null){
            		accountCleanupNeeded = true;
            	}
            	_storageMgr.destroyVolume(volume);
            }

            // Destroy the account's routers
            List routers = _routerDao.listBy(accountId);
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Destroying # of routers (accountId=" + accountId + "): " + routers.size());
            }

            boolean routersCleanedUp = true;
            for (DomainRouterVO router : routers) {
                if (!_networkMgr.destroyRouter(router.getId())) {
                    s_logger.error("Unable to destroy router: " + router.getId());
                    routersCleanedUp = false;
                }
            }

            if (routersCleanedUp) {
            	List ips = _publicIpAddressDao.listByAccount(accountId);
            	
                if (s_logger.isDebugEnabled()) {
        boolean success = false;
            		s_logger.debug("Found " + ips.size() + " public IP addresses for account with ID " + accountId);
                }

            	for (IPAddressVO ip : ips) {
            		Long podId = getPodIdForVlan(ip.getVlanDbId());
            		if (podId != null) {
            			continue;//bug 5561 do not release direct attach pod ips until vm is destroyed
            		}
            		if (!_networkMgr.releasePublicIpAddress(User.UID_SYSTEM, ip.getAddress())) {
            			s_logger.error("Unable to release IP: " + ip.getAddress());
                        accountCleanupNeeded = true;
                    } else {
                    	_accountMgr.decrementResourceCount(accountId, ResourceType.public_ip);
                    }
                }
            } else {
            	accountCleanupNeeded = true;
            }
            
            List securityGroups = _securityGroupDao.listByAccountId(accountId);
            if (securityGroups != null) {
                for (SecurityGroupVO securityGroup : securityGroups) {
                    // All vm instances have been destroyed, delete the security group -> instance_id mappings
                    SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();
                    sc.addAnd("securityGroupId", SearchCriteria.Op.EQ, securityGroup.getId());
                    _securityGroupVMMapDao.expunge(sc);

                    // now clean the network rules and security groups themselves
                    _networkRuleConfigDao.deleteBySecurityGroup(securityGroup.getId());
                    _securityGroupDao.remove(securityGroup.getId());
                }
            }
            
            // Delete the account's VLANs
            List accountVlans = _vlanDao.listVlansForAccountByType(null, accountId, VlanType.DirectAttached);
            boolean allVlansDeleted = true;
            for (VlanVO vlan : accountVlans) {
            	try {
            		allVlansDeleted = _configMgr.deleteVlanAndPublicIpRange(User.UID_SYSTEM, vlan.getId());
            	} catch (InvalidParameterValueException e) {
            		allVlansDeleted = false;
            	}
            }

            if (!allVlansDeleted) {
            	accountCleanupNeeded = true;
            }
            
            // clean up templates
            List userTemplates = _templateDao.listByAccountId(accountId);
            boolean allTemplatesDeleted = true;
            for (VMTemplateVO template : userTemplates) {
            	try {
            		allTemplatesDeleted = _tmpltMgr.delete(userId, template.getId(), null);
            	} catch (InternalErrorException e) {
            		s_logger.warn("Failed to delete template while removing account: " + template.getName() + " due to: " + e.getMessage());
            		allTemplatesDeleted = false;
            	}
            }
            
            if (!allTemplatesDeleted) {
            	accountCleanupNeeded = true;
            }

            return true;
        } finally {
            s_logger.info("Cleanup for account " + account.getId() + (accountCleanupNeeded ? " is needed." : " is not needed."));
            
            if (accountCleanupNeeded) {
            	_accountDao.markForCleanup(accountId);
            }
        }
    }

    @Override
    public boolean disableUser(long userId) {
        if (userId <= 2) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableUser -- invalid user id: " + userId);
            }
            return false;
        }

        return doSetUserStatus(userId, Account.ACCOUNT_STATE_DISABLED);
    }

    @Override
    public boolean enableUser(EnableUserCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long userId = cmd.getId();
        if (accountId <= 2) {
    	Account adminAccount = (Account)UserContext.current().getAccountObject();
        boolean success = false;
        
        //Check if user exists in the system
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);
        
        // If the user is a System user, return an error
        Account account = findAccountById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed");
        }

        if ((adminAccount != null) && !isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
        	throw new PermissionDeniedException("Failed to enable user " + userId + ", permission denied.");
        }
        
        success = doSetUserStatus(userId, Account.ACCOUNT_STATE_ENABLED);

        // make sure the account is enabled too
        success = (success && enableAccount(user.getAccountId()));
        
        return success;
    }

    @Override
        	}
    public boolean lockUser(LockUserCmd cmd) {
        boolean success = false;
        
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long id = cmd.getId();

        // Check if user with id exists in the system
        User user = _userDao.findById(id);
        if (user == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        } else if (user.getRemoved() != null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find user by id");
        }

        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is a system user, locking is not allowed");
        }

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock user " + id + ", permission denied.");
        }

        // make sure the account is enabled too
        // if the user is either locked already or disabled already, don't change state...only lock currently enabled users
        if (user.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
            // already locked...no-op
            return true;
        } else if (user.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
            success = doSetUserStatus(user.getId(), Account.ACCOUNT_STATE_LOCKED);

            boolean lockAccount = true;
            List allUsersByAccount = _userDao.listByAccount(user.getAccountId());
            for (UserVO oneUser : allUsersByAccount) {
                if (oneUser.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                    lockAccount = false;
                    break;
                }
            }

            if (lockAccount) {
                success = (success && lockAccountInternal(user.getAccountId()));
            }
        } else {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Attempting to lock a non-enabled user, current state is " + user.getState() + " (userId: " + user.getId() + "), locking failed.");
            }
        }
        return success;
    }

    private boolean doSetUserStatus(long userId, String state) {
        UserVO userForUpdate = _userDao.createForUpdate();
        userForUpdate.setState(state);
        return _userDao.update(Long.valueOf(userId), userForUpdate);
    }

    @Override
    public boolean disableAccount(long accountId) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("disableAccount -- invalid account id: " + accountId);
            }
            return false;
        }

        AccountVO account = _accountDao.findById(accountId);
        if ((account == null) || account.getState().equals(Account.ACCOUNT_STATE_DISABLED)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setState(Account.ACCOUNT_STATE_DISABLED);
            success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);

            success = (success && doDisableAccount(accountId));
        }
        return success;
    }

    @Override
    public boolean updateAccount(UpdateAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getDomainId();
    	String accountName = cmd.getAccountName();
    	String newAccountName = cmd.getNewName();
    	
    	if (newAccountName == null) {
    		newAccountName = accountName;
    	}
    	
        boolean success = false;
        Account account = _accountDao.findAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        if (account.getAccountName().equals(accountName)) {
            success = true;
        } else {
            AccountVO acctForUpdate = _accountDao.createForUpdate();
            acctForUpdate.setAccountName(newAccountName);
            success = _accountDao.update(Long.valueOf(account.getId()), acctForUpdate);
        }
        return success;
    }

    private boolean doDisableAccount(long accountId) {
        List vms = _userVmDao.listByAccountId(accountId);
        boolean success = true;
        for (UserVmVO vm : vms) {
            try {
                success = (success && _vmMgr.stop(vm, 0));
            } catch (AgentUnavailableException aue) {
                s_logger.warn("Agent running on host " + vm.getHostId() + " is unavailable, unable to stop vm " + vm.getName());
                success = false;
            }
        }

        List routers = _routerDao.listBy(accountId);
        for (DomainRouterVO router : routers) {
            success = (success && _networkMgr.stopRouter(router.getId(), 0));
        }

        return success;
    }

    public boolean enableAccount(long accountId) {
        boolean success = false;
        AccountVO acctForUpdate = _accountDao.createForUpdate();
        acctForUpdate.setState(Account.ACCOUNT_STATE_ENABLED);
        success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
        return success;
    }
    	
    
    @Override
    public boolean enableAccount(EnableAccountCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String accountName = cmd.getAccountName();
    	Long domainId = cmd.getDomainId();
        boolean success = false;
        Account account = _accountDao.findActiveAccount(accountName, domainId);

        //Check if account exists
        if (account == null) {
        	s_logger.error("Unable to find account " + accountName + " in domain " + domainId);
    		throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
        }
        
        //Don't allow to modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
    		throw new InvalidParameterValueException ("Can not modify system account");
    	}
        
        //Check if user performing the action is allowed to modify this account
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        if ((adminAccount != null) && isChildDomain(adminAccount.getDomainId(), account.getDomainId())) {
          throw new PermissionDeniedException("Invalid account " + accountName + " in domain " + domainId + " given, permission denied");
        }
        
        success = enableAccount(account.getId());
        return success;
    }

    private boolean lockAccountInternal(long accountId) {
        boolean success = false;
        Account account = _accountDao.findById(accountId);
        if (account != null) {
            if (account.getState().equals(Account.ACCOUNT_STATE_LOCKED)) {
                return true; // already locked, no-op
            } else if (account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
                AccountVO acctForUpdate = _accountDao.createForUpdate();
                acctForUpdate.setState(Account.ACCOUNT_STATE_LOCKED);
                success = _accountDao.update(Long.valueOf(accountId), acctForUpdate);
            } else {
                if (s_logger.isInfoEnabled()) {
                    s_logger.info("Attempting to lock a non-enabled account, current state is " + account.getState() + " (accountId: " + accountId + "), locking failed.");
                }
            }
        } else {
            s_logger.warn("Failed to lock account " + accountId + ", account not found.");
        }
        return success;
    }

    @Override
    public boolean updateUser(UpdateUserCmd cmd) throws InvalidParameterValueException {
        Long id = cmd.getId();
        String apiKey = cmd.getApiKey();
        String firstName = cmd.getFirstname();
    	String email = cmd.getEmail();
    	String lastName = cmd.getLastname();
    	String password = cmd.getPassword();
    	String secretKey = cmd.getSecretKey();
    	String timeZone = cmd.getTimezone();
    	String userName = cmd.getUsername();
    	
        //Input validation
    	UserVO user = _userDao.getUser(id);
    	
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user by id");
        }

        if((apiKey == null && secretKey != null) || (apiKey != null && secretKey == null)) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Please provide an api key/secret key pair");
        }
        
        // If the account is an admin type, return an error.  We do not allow this
        Account account = (Account)UserContext.current().getAccountObject();
        
        if (account != null && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + id + " is system account, update is not allowed");
        }

        if (firstName == null) { 
        	firstName = user.getFirstname();
        }
        if (lastName == null) { 
        	lastName = user.getLastname(); 
        }
        if (userName == null) { 
        	userName = user.getUsername();  
        }
        if (password == null) { 
        	password = user.getPassword();
        }
        if (email == null) {

        	email = user.getEmail();
        }
        if (timeZone == null) {
        	timeZone = user.getTimezone();
        }
        if (apiKey == null) {
        	apiKey = user.getApiKey();
        }
        if (secretKey == null) {
        	secretKey = user.getSecretKey();
        }

        Long accountId = user.getAccountId();

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("updating user with id: " + id);
        }
        UserAccount userAccount = _userAccountDao.findById(id);
        try {
        	//check if the apiKey and secretKey are globally unique
        	if (apiKey != null && secretKey != null) {
        		Pair apiKeyOwner = findUserByApiKey(apiKey);

        		if(apiKeyOwner != null) {
        			User usr = apiKeyOwner.first();
        			if (usr.getId() != id) {
            			throw new InvalidParameterValueException("The api key:"+apiKey+" exists in the system for user id:"+id+" ,please provide a unique key");
        			} else {
        				//allow the updation to take place
            _userDao.update(id, userName, password, firstName, lastName, email, accountId, timeZone, apiKey, secretKey);
            EventUtils.saveEvent(new Long(1), Long.valueOf(1), EventVO.LEVEL_INFO, EventTypes.EVENT_USER_UPDATE, "User, " + userName + " for accountId = "
                    + accountId + " domainId = " + userAccount.getDomainId() + " and timezone = "+timeZone + " was updated.");
        } catch (Throwable th) {
            s_logger.error("error updating user", th);
            EventUtils.saveEvent(Long.valueOf(1), Long.valueOf(1), EventVO.LEVEL_ERROR, EventTypes.EVENT_USER_UPDATE, "Error updating user, " + userName
                    + " for accountId = " + accountId + " and domainId = " + userAccount.getDomainId());
            return false;
        }
        return true;
    }
    
    @Override
    public Pair findUserByApiKey(String apiKey) {
        return _accountDao.findUserAccountByApiKey(apiKey);
    }

    @Override
    public Account getAccount(long accountId) {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Retrieiving account with id: " + accountId);
        }

        AccountVO account = _accountDao.findById(Long.valueOf(accountId));
        if (account == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find account with id " + accountId);
            }
            return null;
        }

        return account;
    }
    
    @Override
    public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
    	Long userId = cmd.getId();
    	User user = _userDao.findById(userId);

    	if (user == null) {
           throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find user for id : " + userId);
    	}

    	// generate both an api key and a secret key, update the user table with the keys, return the keys to the user
    	String[] keys = new String[2];
    	keys[0] = createApiKey(userId);
    	keys[1] = createSecretKey(userId);

    	return keys;
    }

    private String createApiKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            Pair userAcct = null;
            int retryLimit = 10;
            do {
                // FIXME: what algorithm should we use for API keys?
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userAcct = _accountDao.findUserAccountByApiKey(encodedKey);
                retryLimit--;
            } while ((userAcct != null) && (retryLimit >= 0));

            if (userAcct != null) {
                return null;
            }
            updatedUser.setApiKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    private String createSecretKey(Long userId) {
        User user = findUserById(userId);
        try {
            UserVO updatedUser = _userDao.createForUpdate();

            String encodedKey = null;
            int retryLimit = 10;
            UserVO userBySecretKey = null;
            do {
                KeyGenerator generator = KeyGenerator.getInstance("HmacSHA1");
                SecretKey key = generator.generateKey();
                encodedKey = Base64.encodeBase64URLSafeString(key.getEncoded());
                userBySecretKey = _userDao.findUserBySecretKey(encodedKey);
                retryLimit--;
            } while ((userBySecretKey != null) && (retryLimit >= 0));

            if (userBySecretKey != null) {
                return null;
            }

            updatedUser.setSecretKey(encodedKey);
            _userDao.update(user.getId(), updatedUser);
            return encodedKey;
        } catch (NoSuchAlgorithmException ex) {
            s_logger.error("error generating secret key for user: " + user.getUsername(), ex);
        }
        return null;
    }

    @Override
    public VolumeVO findRootVolume(long vmId) {
        List volumes = _volumeDao.findByInstanceAndType(vmId, VolumeType.ROOT);
        if (volumes != null && volumes.size() == 1)
            return volumes.get(0);
        else
            return null;
    }

    @Override
    public List listPublicIpAddressesBy(Long accountId, boolean allocatedOnly, Long zoneId, Long vlanDbId) {
        SearchCriteria sc = _publicIpAddressDao.createSearchCriteria();

        if (accountId != null)
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        if (zoneId != null)
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        if (vlanDbId != null)
            sc.addAnd("vlanDbId", SearchCriteria.Op.EQ, vlanDbId);
        if (allocatedOnly)
            sc.addAnd("allocated", SearchCriteria.Op.NNULL);

        return _publicIpAddressDao.search(sc, null);
    }

    @Override
    public List listPrivateIpAddressesBy(Long podId, Long zoneId) {
        if (podId != null && zoneId != null)
            return _privateIpAddressDao.listByPodIdDcId(podId.longValue(), zoneId.longValue());
        else
            return new ArrayList();
    }

    @Override
    public String generateRandomPassword() {
    	return PasswordGenerator.generateRandomPassword();
    }

    @Override
    public boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach, long startEventId) {
    	UserVmVO vm = _userVmDao.findById(vmId);
    	VMTemplateVO iso = _templateDao.findById(isoId);
    	if(attach){
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_ATTACH, "Attaching ISO: "+isoId+" to Vm: "+vmId, startEventId);
    	} else {
        if (networkGroups != null) {
        	for (String groupName: networkGroups) {
    		EventUtils.saveStartedEvent(userId, vm.getAccountId(), EventTypes.EVENT_ISO_DETACH, "Detaching ISO: "+isoId+" from Vm: "+vmId, startEventId);
    	}
        boolean success = _vmMgr.attachISOToVM(vmId, isoId, attach);

        if (success) {
            if (attach) {
                vm.setIsoId(iso.getId().longValue());
            } else {
                vm.setIsoId(null);
            }
            _userVmDao.update(vmId, vm);

            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_ATTACH, "Successfully attached ISO: " + iso.getName() + " to VM with ID: " + vmId,
                        null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ISO_DETACH, "Successfully detached ISO from VM with ID: " + vmId, null, startEventId);
            }
        } else {
            if (attach) {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_ATTACH, "Failed to attach ISO: " + iso.getName() + " to VM with ID: " + vmId, null, startEventId);
            } else {
            	EventUtils.saveEvent(userId, vm.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_ISO_DETACH, "Failed to detach ISO from VM with ID: " + vmId, null, startEventId);
            }
        }
    private boolean validPassword(String password) {
        for (int i = 0; i < password.length(); i++) {
            if (password.charAt(i) == ' ') {
                return false;
            }
        }
        return true;
    }

    private UserVm deployVirtualMachineImpl(long userId, long accountId, long dataCenterId, long serviceOfferingId, long templateId, Long diskOfferingId,
            String domain, String password, String displayName, String group, String userData, String [] networkGroups, long startEventId, long size) throws ResourceAllocationException, InvalidParameterValueException, InternalErrorException,
            InsufficientStorageCapacityException, PermissionDeniedException, ExecutionException, StorageUnavailableException, ConcurrentOperationException {

    	EventUtils.saveStartedEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "Deploying Vm", startEventId);
        
        AccountVO account = _accountDao.findById(accountId);
        DataCenterVO dc = _dcDao.findById(dataCenterId);
        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        VMTemplateVO template = _templateDao.findById(templateId);

        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }
        byte [] decodedUserData = null;
        if (userData != null) {
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
			
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
        
        // TODO: Checks such as is the user allowed to use the template and purchase the service offering id.

        if (domain == null) {
            domain = "v" + Long.toHexString(accountId) + _domain;
        }

        // Check that the password was passed in and is valid
        if (!template.getEnablePassword()) {
            password = "saved_password";
        }

        if (password == null || password.equals("") || (!validPassword(password))) {
            throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
        }
        List networkGroupVOs = new ArrayList();
        		NetworkGroupVO networkGroupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
        		if (networkGroupVO == null) {
        			throw new InvalidParameterValueException("Network Group " + groupName + " does not exist");
        		}
        		networkGroupVOs.add(networkGroupVO);
        	}
        }
        
        UserStatisticsVO stats = _userStatsDao.findBy(account.getId(), dataCenterId);
        if (stats == null) {
            stats = new UserStatisticsVO(account.getId(), dataCenterId);
            _userStatsDao.persist(stats);
        }
        
    	Long vmId = _vmDao.getNextInSequence(Long.class, "id");
    	
        // check if we are within context of async-execution
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if (asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if (s_logger.isInfoEnabled())
                s_logger.info("DeployVM acquired a new instance " + vmId + ", update async job-" + job.getId() + " progress status");

            _asyncMgr.updateAsyncJobAttachment(job.getId(), "vm_instance", vmId);
            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, vmId);
        }

        HashMap avoids = new HashMap();

        // Pod allocator now allocate VM based on a reservation style allocation, disable retry here for now
        for (int retry = 0; retry < 1; retry++) {
            String externalIp = null;
            UserVmVO created = null;

            ArrayList a = new ArrayList(avoids.values());
            if (_directAttachNetworkExternalIpAllocator) {
            	try {
            		created = _vmMgr.createDirectlyAttachedVMExternal(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            	} catch (ResourceAllocationException rae) {
            		throw rae;
            	}
            } else {
            	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
            		try {
            			externalIp = _networkMgr.assignSourceNatIpAddress(account, dc, domain, offering, startEventId);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}

            		if (externalIp == null) {
            			throw new InternalErrorException("Unable to allocate a source nat ip address");
            		}

            		if (s_logger.isDebugEnabled()) {
            			s_logger.debug("Source Nat acquired: " + externalIp);
            		}

            		try {
            			created = _vmMgr.createVirtualMachine(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	} else {
            		try {
            			created = _vmMgr.createDirectlyAttachedVM(vmId, userId, account, dc, offering, template, diskOffering, displayName, userData, a, networkGroupVOs, startEventId, size);
            		} catch (ResourceAllocationException rae) {
            			throw rae;
            		}
            	}
            }

            //assign vm to the group
            try{
            	if (group != null) {
            	boolean addToGroup = _vmMgr.addInstanceToGroup(Long.valueOf(vmId), group);
            	if (!addToGroup) {
            		throw new InternalErrorException("Unable to assing Vm to the group " + group);
            	}
                }
            } catch (Exception ex) {
            	throw new InternalErrorException("Unable to assing Vm to the group " + group);
            }
            
            
            if (created == null) {
                throw new InternalErrorException("Unable to create VM for account (" + accountId + "): " + account.getAccountName());
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM created: " + created.getId() + "-" + created.getName());
            }
            boolean executionExceptionFlag = false;
            boolean storageUnavailableExceptionFlag = false;
            boolean concurrentOperationExceptionFlag = false;
            String executionExceptionMsg= "";
            String storageUnavailableExceptionMsg = "";
            String concurrentOperationExceptionMsg = "";
            UserVmVO started = null;
            if (isIso) {
                String isoPath = _storageMgr.getAbsoluteIsoPath(templateId, dataCenterId);
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, isoPath, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }
            } else {
                try {
                    started = _vmMgr.startVirtualMachine(userId, created.getId(), password, null, startEventId);
                } catch (ExecutionException e) {
                    executionExceptionFlag = true;
                    executionExceptionMsg = e.getMessage();
                } catch (StorageUnavailableException e) {
                    storageUnavailableExceptionFlag = true;
                    storageUnavailableExceptionMsg = e.getMessage();
                } catch (ConcurrentOperationException e) {
                    concurrentOperationExceptionFlag = true;
                    concurrentOperationExceptionMsg = e.getMessage();
                }

            }

            if (started == null) {
                List> disks = _storageMgr.isStoredOn(created);
                // NOTE: We now destroy a VM if the deploy process fails at any step. We now
                // have a lazy delete so there is still some time to figure out what's wrong.
                _vmMgr.destroyVirtualMachine(userId, created.getId());

                boolean retryCreate = true;
                for (Pair disk : disks) {
                    if (disk.second().isLocal()) {
                        avoids.put(disk.second().getId(), disk.second());
                    } else {
                        retryCreate = false;
                    }
                }

                if (retryCreate) {
                    continue;
                } else if(executionExceptionFlag){
                    throw new ExecutionException(executionExceptionMsg);
                } else if (storageUnavailableExceptionFlag){
                	throw new StorageUnavailableException(storageUnavailableExceptionMsg);
                }else if (concurrentOperationExceptionFlag){
                	throw new ConcurrentOperationException(concurrentOperationExceptionMsg);
                }
                else{
                    throw new InternalErrorException("Unable to start the VM " + created.getId() + "-" + created.getName());
                }
                
            } else {
                if (isIso) {
                    started.setIsoId(templateId);
                    _userVmDao.update(started.getId(), started);
                    started = _userVmDao.findById(started.getId());
                }

                try {
					_configMgr.associateIpAddressListToAccount(userId, accountId, dc.getId(),null);															
				} catch (InsufficientAddressCapacityException e) {
					s_logger.debug("Unable to assign public IP address pool: " +e.getMessage());					
				}
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM started: " + started.getId() + "-" + started.getName());
            }
            return started;
        }

        return null;
    }

    @Override
    public UserVm deployVirtualMachine(DeployVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException,
                                                               InternalErrorException, InsufficientStorageCapacityException, ExecutionException,
                                                               StorageUnavailableException, ConcurrentOperationException {
        Account ctxAccount = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        long dataCenterId = cmd.getZoneId();
        long serviceOfferingId = cmd.getServiceOfferingId();
        long templateId = cmd.getTemplateId();
        Long diskOfferingId = cmd.getDiskOfferingId();
        String domain = null; // FIXME:  this was hardcoded to null in DeployVMCmd in the old framework, do we need it?
        String password = generateRandomPassword();
        String displayName = cmd.getDisplayName();
        String group = cmd.getGroup();
        String userData = cmd.getUserData();
        String[] networkGroups = null;
        Long sizeObj = cmd.getSize();
        long size = (sizeObj == null) ? 0 : sizeObj;

        if ((ctxAccount == null) || isAdmin(ctxAccount.getType())) {
            if (domainId != null) {
                if ((ctxAccount != null) && !_domainDao.isChildDomain(ctxAccount.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount == null) {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = userAccount.getId();
                }
            } else {
                accountId = ((ctxAccount != null) ? ctxAccount.getId() : null);
            }
        } else {
            accountId = ctxAccount.getId();
        }

        if (accountId == null) {
            throw new InvalidParameterValueException("No valid account specified for deploying a virtual machine.");
        }

        List netGrpList = cmd.getNetworkGroupList();
        if ((netGrpList != null) && !netGrpList.isEmpty()) {
            networkGroups = netGrpList.toArray(new String[netGrpList.size()]);
        }

    	AccountVO account = _accountDao.findById(accountId);
        if (account == null) {
            throw new InvalidParameterValueException("Unable to find account: " + accountId);
        }

        DataCenterVO dc = _dcDao.findById(dataCenterId);
        if (dc == null) {
            throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
        }

        ServiceOfferingVO offering = _offeringsDao.findById(serviceOfferingId);
        if (offering == null) {
            throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId);
        }

        VMTemplateVO template = _templateDao.findById(templateId);
        // Make sure a valid template ID was specified
        if (template == null) {
            throw new InvalidParameterValueException("Please specify a valid template or ISO ID.");
        }

        boolean isIso = Storage.ImageFormat.ISO.equals(template.getFormat());
        
        if (isIso && !template.isBootable()) {
        	throw new InvalidParameterValueException("Please specify a bootable ISO.");
        }

        // If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
        } catch (InvalidParameterValueException e) {
        if (userId == null) {
        // Else, a disk offering is optional, and if present will be used to create the data disk
        DiskOfferingVO diskOffering = null;

        if (diskOfferingId != null) {
        	diskOffering = _diskOfferingDao.findById(diskOfferingId);
        }

        if (isIso && diskOffering == null) {
        	throw new InvalidParameterValueException("Please specify a valid disk offering ID.");
        }

        // validate that the template is usable by the account
        if (!template.isPublicTemplate()) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType()) && ((templateOwner == null) || (templateOwner.longValue() != accountId))) {
                // since the current account is not the owner of the template, check the launch permissions table to see if the
                // account can launch a VM from this template
                LaunchPermissionVO permission = _launchPermissionDao.findByTemplateAndAccount(templateId, account.getId());
                if (permission == null) {
                    throw new PermissionDeniedException("Account " + account.getAccountName() + " does not have permission to launch instances from template " + template.getName());
                }
            }
        }

        byte [] decodedUserData = null;
        if (userData != null) {
        }
        	if (userData.length() >= 2* UserVmManager.MAX_USER_DATA_LENGTH_BYTES) {
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
        	if (decodedUserData.length > UserVmManager.MAX_USER_DATA_LENGTH_BYTES){
        		throw new InvalidParameterValueException("User data is too long");
        	}
        	if (decodedUserData.length < 1) {
        		throw new InvalidParameterValueException("User data is too short");
        	}
			
        }
        if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized) {
        	_networkGroupMgr.createDefaultNetworkGroup(accountId);
    	}
        
        if (networkGroups != null) {
        	if (offering.getGuestIpType() == NetworkOffering.GuestIpType.Virtualized) {
        		throw new InvalidParameterValueException("Network groups are not compatible with service offering " + offering.getName());
        	}
        	Set nameSet = new HashSet(); //handle duplicate names -- allowed
        	nameSet.addAll(Arrays.asList(networkGroups));
        	nameSet.add(NetworkGroupManager.DEFAULT_GROUP_NAME);
        	networkGroups = nameSet.toArray(new String[nameSet.size()]);
        	List networkGroupVOs = _networkSecurityGroupDao.findByAccountAndNames(accountId, networkGroups);
        	if (networkGroupVOs.size() != nameSet.size()) {
        		throw new InvalidParameterValueException("Some network group names do not exist");
        	}
        } else { //create a default group if necessary
        	if (offering.getGuestIpType() != NetworkOffering.GuestIpType.Virtualized && _networkGroupsEnabled) {
        		networkGroups = new String[]{NetworkGroupManager.DEFAULT_GROUP_NAME};
        	}
        }

        // FIXME:  this really needs to be invoked when the job is scheduled by the framework, so commands need a callback for
        //         specifying event details that they are tracking...
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VM_CREATE, "deploying Vm");

        try {
            return deployVirtualMachineImpl(userId, accountId, dataCenterId, serviceOfferingId, templateId, diskOfferingId, domain, password, displayName, group, userData, networkGroups, eventId, size);
        } catch (ResourceAllocationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (ExecutionException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_HOST_LICENSE_EXPIRED", null, eventId);
            throw e;
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INVALID_PARAM_ERROR", null, eventId);
            throw e;
        } catch (InternalErrorException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch (InsufficientStorageCapacityException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: VM_INSUFFICIENT_CAPACITY", null, eventId);
            throw e;
        } catch (PermissionDeniedException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: ACCOUNT_ERROR", null, eventId);
            throw e;
        } catch (ConcurrentOperationException e) {
            if(s_logger.isDebugEnabled())
                s_logger.debug("Unable to deploy VM: " + e.getMessage());
            userId = Long.valueOf(1);
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw e;
        } catch(Exception e) {
            s_logger.warn("Unable to deploy VM : " + e.getMessage(), e);
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_CREATE, "Unable to deploy VM: INTERNAL_ERROR", null, eventId);
            throw new CloudRuntimeException("Unable to deploy VM : " + e.getMessage());
        }
    }

    @Override
    public DomainRouterVO findDomainRouterBy(long accountId, long dataCenterId) {
        return _routerDao.findBy(accountId, dataCenterId);
    }

    @Override
    public DomainRouterVO findDomainRouterById(long domainRouterId) {
        return _routerDao.findById(domainRouterId);
    }

    @Override
    public List listDataCenters(ListZonesByCmd cmd) {
        List dcs = _dcDao.listAll();

        Account account = (Account)UserContext.current().getAccountObject();
        Boolean available = cmd.isAvailable();
        if (account != null) {
            if ((available != null) && Boolean.FALSE.equals(available)) {
                List routers = _routerDao.listBy(account.getId());
                for (Iterator iter = dcs.iterator(); iter.hasNext();) {
                    DataCenterVO dc = iter.next();
                    boolean found = false;
                    for (DomainRouterVO router : routers) {
                        if (dc.getId() == router.getDataCenterId()) {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        iter.remove();
                }
            }
        }

        return dcs;
    }

    @Override
    public HostVO getHostBy(long hostId) {
        return _hostDao.findById(hostId);
    }

    @Override
    public long getId() {
        return MacAddress.getMacAddress().toLong();
    }

    protected void checkPortParameters(String publicPort, String privatePort, String privateIp, String proto) throws InvalidParameterValueException {

        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("publicPort is an invalid value");
        }
        if (!NetUtils.isValidPort(privatePort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");

//        s_logger.debug("Checking if " + privateIp + " is a valid private IP address. Guest IP address is: " + _configs.get("guest.ip.network"));
//
//        if (!NetUtils.isValidPrivateIp(privateIp, _configs.get("guest.ip.network"))) {
//            throw new InvalidParameterValueException("Invalid private ip address");
//        }
        if (!NetUtils.isValidProto(proto)) {
            throw new InvalidParameterValueException("Invalid protocol");
        }
    }

    @Override
    @DB
    public void assignSecurityGroup(AssignPortForwardingServiceCmd cmd) throws PermissionDeniedException,
            NetworkRuleConflictException, InvalidParameterValueException, InternalErrorException {
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	Long securityGroupId = cmd.getId();
    	List sgIdList = cmd.getIds();
    	String publicIp = cmd.getPublicIp();
    	Long vmId = cmd.getVirtualMachineId();
    	
    	//Verify input parameters
        if ((securityGroupId == null) && (sgIdList == null)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "No service id (or list of ids) specified.");
        }



        List validateSGList = null;
        if (securityGroupId == null) {
            validateSGList = sgIdList;
        } else {
            validateSGList = new ArrayList();
            validateSGList.add(securityGroupId);
        }
        Long validatedAccountId = validateSecurityGroupsAndInstance(validateSGList, vmId);
        if (validatedAccountId == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to apply port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".  Invalid list of port forwarding services for the given instance.");
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != validatedAccountId.longValue())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
            } else {
                Account validatedAccount = findAccountById(validatedAccountId);
                if (!isChildDomain(account.getDomainId(), validatedAccount.getDomainId())) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Permission denied applying port forwarding services " + StringUtils.join(sgIdList, ",") + " to instance " + vmId + ".");
                }
            }
        }
    	
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            s_logger.warn("Unable to find virtual machine with id " + vmId);
            throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
        }
        long startEventId = EventUtils.saveScheduledEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "applying port forwarding service for Vm with Id: "+vmId);
    	
        boolean locked = false;
        Transaction txn = Transaction.currentTxn();
        try {
            EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY, "Applying port forwarding service for Vm with Id: "+vmId, startEventId);
            State vmState = userVm.getState();
            switch (vmState) {
            case Destroyed:
            case Error:
            case Expunging:
            case Unknown:
                throw new InvalidParameterValueException("Unable to assign port forwarding service(s) '"
                        + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "' to virtual machine " + vmId
                        + " due to virtual machine being in an invalid state for assigning a port forwarding service (" + vmState + ")");
            }

            // sanity check that the vm can be applied to the load balancer
            ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
            if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                }

                throw new InvalidParameterValueException("Unable to apply port forwarding service to virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }
            
            DomainRouterVO router = null;
            if (userVm.getDomainRouterId() != null)
            	router = _routerDao.findById(userVm.getDomainRouterId());
            if (router == null) {
                s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine " + userVm.toString());
                throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + vmId);
            }

            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }
            locked = true;

            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
                throw new PermissionDeniedException("User does not own supplied address");
            }

            VlanVO vlan = _vlanDao.findById(ipVO.getVlanDbId());
            if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
                throw new InvalidParameterValueException("Invalid IP address " + publicIp + " for applying port forwarding services, the IP address is not in a 'virtual network' vlan.");
            }

            txn.start();

            if (securityGroupId == null) {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on list passed in
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                {
                    // Save and create the event
                    String description;
                    String type = EventTypes.EVENT_NET_RULE_DELETE;
                    String level = EventVO.LEVEL_INFO;

                    for (FirewallRuleVO fwRule : fwRulesToRemove) {
                        fwRule.setEnabled(false); // disable rule for sending to the agent
                        _firewallRulesDao.remove(fwRule.getId()); // remove the rule from the database

                        description = "deleted ip forwarding rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                                + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                        EventUtils.saveEvent(userId, userVm.getAccountId(), level, type, description);
                    }
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);
                if ((updatedRules != null) && (updatedRules.size() != fwRulesToRemove.size())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to clean up all port forwarding service rules for public IP " + publicIp + " and guest vm " + userVm.getName()
                                + " while applying port forwarding service(s) '" + ((securityGroupId == null) ? StringUtils.join(sgIdList, ",") : securityGroupId) + "'"
                                + " -- intended to remove " + fwRulesToRemove.size() + " rules, removd " + ((updatedRules == null) ? "null" : updatedRules.size()) + " rules.");
                    }
                }

                List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    boolean success = _securityGroupVMMapDao.remove(sgVmMapping.getId());

                    SecurityGroupVO securityGroup = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());

                    // save off an event for removing the security group
                    EventVO event = new EventVO();
                    event.setUserId(userId);
                    event.setAccountId(userVm.getAccountId());
                    event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
                    String sgRemoveLevel = EventVO.LEVEL_INFO;
                    String sgRemoveDesc = "Successfully removed ";
                    if (!success) {
                        sgRemoveLevel = EventVO.LEVEL_ERROR;
                        sgRemoveDesc = "Failed to remove ";
                    }
                    String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
                    event.setParameters(params);
                    event.setDescription(sgRemoveDesc + "port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
                    event.setLevel(sgRemoveLevel);
                    _eventDao.persist(event);
                }
            } else {
                List existingVMMaps = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId.longValue());
                if ((existingVMMaps != null) && !existingVMMaps.isEmpty()) {
                    for (SecurityGroupVMMapVO existingVMMap : existingVMMaps) {
                        if (existingVMMap.getInstanceId() == userVm.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("port forwarding service " + securityGroupId + " is already applied to virtual machine " + userVm.toString() + ", skipping assignment.");
                            }
                            return;
                        }
                    }
                }
            }

            List finalSecurityGroupIdList = new ArrayList();
            if (securityGroupId != null) {
                finalSecurityGroupIdList.add(securityGroupId);
            } else {
                finalSecurityGroupIdList.addAll(sgIdList);
            }

            for (Long sgId : finalSecurityGroupIdList) {
                if (sgId.longValue() == 0) {
                    // group id of 0 means to remove all groups, which we just did above
                    break;
                }

                SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(sgId));
                if (securityGroup == null) {
                    s_logger.warn("Unable to find port forwarding service with id " + sgId);
                    throw new InvalidParameterValueException("Unable to find port forwarding service with id " + sgId);
                }

                if (!_domainDao.isChildDomain(securityGroup.getDomainId(), userVm.getDomainId())) {
                    s_logger.warn("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                    throw new InvalidParameterValueException("Unable to assign port forwarding service " + sgId + " to user vm " + vmId + ", user vm's domain (" + userVm.getDomainId()
                            + ") is not in the domain of the port forwarding service (" + securityGroup.getDomainId() + ")");
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(publicIp);
                Map> mappedPublicPorts = new HashMap>();

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
                    }
                }

                List loadBalancers = _loadBalancerDao.listByIpAddress(publicIp);
                if (loadBalancers != null) {
                    for (LoadBalancerVO loadBalancer : loadBalancers) {
                        // load balancers don't have to be applied to an
                        // instance for there to be a conflict on the load
                        // balancers ip/port, so just
                        // map the public port to a pair of empty strings
                        mappedPublicPorts.put(loadBalancer.getPublicPort(), new Pair("", ""));
                    }

                }

                List firewallRulesToApply = new ArrayList();
                List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgId);
                for (NetworkRuleConfigVO netRule : netRules) {
                    Pair privateIpPort = mappedPublicPorts.get(netRule.getPublicPort());
                    if (privateIpPort != null) {
                        if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(netRule.getPrivatePort())) {
                            continue; // already mapped
                        } else {
                            throw new NetworkRuleConflictException("An existing service rule for " + publicIp + ":" + netRule.getPublicPort()
                                    + " already exists, found while trying to apply service rule " + netRule.getId() + " from port forwarding service " + securityGroup.getName() + ".");
                        }
                    }

                    FirewallRuleVO newFwRule = new FirewallRuleVO();
                    newFwRule.setEnabled(true);
                    newFwRule.setForwarding(true);
                    newFwRule.setPrivatePort(netRule.getPrivatePort());
                    newFwRule.setProtocol(netRule.getProtocol());
                    newFwRule.setPublicPort(netRule.getPublicPort());
                    newFwRule.setPublicIpAddress(publicIp);
                    newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                    newFwRule.setGroupId(netRule.getSecurityGroupId());

                    firewallRulesToApply.add(newFwRule);
                    _firewallRulesDao.persist(newFwRule);

                    String description = "created new ip forwarding rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                            + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
                }

                // now that individual rules have been created from the security group, save the security group mapping for this ip/vm instance
                SecurityGroupVMMapVO sgVmMap = new SecurityGroupVMMapVO(sgId, publicIp, vmId);
                _securityGroupVMMapDao.persist(sgVmMap);

                // Save off information for the event that the security group was applied
                EventVO event = new EventVO();
                event.setUserId(userId);
                event.setAccountId(userVm.getAccountId());
                event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_APPLY);
                event.setStartId(startEventId);
                event.setDescription("Successfully applied port forwarding service " + securityGroup.getName() + " to virtual machine " + userVm.getName());
                String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId+"\nnumRules="+firewallRulesToApply.size()+"\ndcId="+userVm.getDataCenterId();
                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
                _eventDao.persist(event);

                _networkMgr.updateFirewallRules(publicIp, firewallRulesToApply, router);
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public void removeSecurityGroup(RemovePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	
    	Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long securityGroupId = cmd.getId();
        String publicIp = cmd.getPublicIp();
        Long vmId = cmd.getVirtualMachineId();
        
        //verify input parameters
        SecurityGroupVO securityG = _securityGroupDao.findById(securityGroupId);
        if (securityG == null) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId);
        } else if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != securityG.getAccountId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a port forwarding service with id " + securityGroupId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), securityG.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid port forwarding service id (" + securityGroupId + ") given, unable to remove port forwarding service.");
            }
        }
        
        UserVmVO vmInstance = findUserVMInstanceById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }
        if (account != null) {
            if (!isAdmin(account.getType()) && (account.getId() != vmInstance.getAccountId())) {
                throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId + " for this account");
            } else if (!isChildDomain(account.getDomainId(), vmInstance.getDomainId())) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid virtual machine id (" + vmId + ") given, unable to remove port forwarding service.");
            }
        }

        Account ipAddrAccount = findAccountByIpAddress(publicIp);
        if (ipAddrAccount == null) {
            if (account == null) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find ip address " + publicIp);
            } else {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        Long accountId = ipAddrAccount.getId();
        if ((account != null) && !isAdmin(account.getType())) {
            if (account.getId() != accountId) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "account " + account.getAccountName() + " doesn't own ip address " + publicIp);
            }
        }

        if (userId == null) {
            userId = Long.valueOf(1);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "removing port forwarding services for Vm with Id: "+vmId);

        /*TODO : ASK KRIS AS TO WHAT DO WE DO WITH THIS PART IN THE EXECUTOR CODE
        UserVmVO userVm = userVmDao.findById(param.getInstanceId());
        if(userVm == null)
        	return null;
        
        if (userVm.getDomainRouterId() == null) {
        	return null;
        } else
        	return routerDao.findById(userVm.getDomainRouterId());
	    */
        removeSecurityGroup(userId, securityGroupId, publicIp, vmId, eventId);
    }
    
    @Override
    @DB
    public void removeSecurityGroup(long userId, long securityGroupId, String publicIp, long vmId, long startEventId) throws InvalidParameterValueException, PermissionDeniedException {
        // This gets complicated with overlapping rules. As an example:
        // security group 1 has the following port mappings: 22->22 on TCP,
        // 23->23 on TCP, 80->8080 on TCP
        // security group 2 has the following port mappings: 22->22 on TCP,
        // 7891->7891 on TCP
        // User assigns group 1 & 2 on 192.168.10.120 to vm 1
        // Later, user removed group 1 from 192.168.10.120 and vm 1
        // Final valid port mappings should be 22->22 and 7891->7891 which both
        // come from security group 2. The mapping
        // for port 22 should not be removed.
        boolean locked = false;
        }
        UserVm userVm = _userVmDao.findById(vmId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Unable to find vm: " + vmId);
        }
        EventUtils.saveStartedEvent(userId, userVm.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE, "Removing port forwarding services for Vm with Id: "+vmId, startEventId);
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
            throw new InvalidParameterValueException("Unable to find port forwarding service: " + securityGroupId);
        }

        DomainRouterVO router = null;
        if (userVm.getDomainRouterId() != null)
        	router = _routerDao.findById(userVm.getDomainRouterId());
        if (router == null) {
            throw new InvalidParameterValueException("Unable to find router for ip address: " + publicIp);
        }

        Transaction txn = Transaction.currentTxn();
        try {
            IPAddressVO ipVO = _publicIpAddressDao.acquire(publicIp);
            if (ipVO == null) {
                // throw this exception because hackers can use the api to probe
                // for allocated ips
                throw new PermissionDeniedException("User does not own supplied address");
            }

            locked = true;
            if ((ipVO.getAllocated() == null) || (ipVO.getAccountId() == null) || (ipVO.getAccountId().longValue() != userVm.getAccountId())) {
            } else {
                throw new PermissionDeniedException("User/account does not own supplied address");
            }

            txn.start();

            // get the account for writing events
            Account account = _accountDao.findById(userVm.getAccountId());
            {
                // - send one command to agent to remove *all* rules for
                // publicIp/vm combo
                // - add back all rules based on existing SG mappings
                List fwRulesToRemove = _firewallRulesDao.listForwardingByPubAndPrivIp(true, publicIp, userVm.getGuestIpAddress());
                for (FirewallRuleVO fwRule : fwRulesToRemove) {
                    fwRule.setEnabled(false);
                }

                List updatedRules = _networkMgr.updateFirewallRules(null, fwRulesToRemove, router);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "ip forwarding";
                String level = EventVO.LEVEL_INFO;

                for (FirewallRuleVO fwRule : updatedRules) {
                    _firewallRulesDao.remove(fwRule.getId());

                    description = "deleted " + ruleName + " rule [" + fwRule.getPublicIpAddress() + ":" + fwRule.getPublicPort() + "]->[" + fwRule.getPrivateIpAddress() + ":"
                            + fwRule.getPrivatePort() + "]" + " " + fwRule.getProtocol();

                    EventUtils.saveEvent(userId, account.getId(), level, type, description);
                }
            }

            // since we know these groups all pass muster, just keep track
            // of the public ports we are mapping on this public IP and
            // don't duplicate
            List alreadyMappedPorts = new ArrayList();
            List fwRulesToAdd = new ArrayList();
            List sgVmMappings = _securityGroupVMMapDao.listByIpAndInstanceId(publicIp, vmId);
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                if (sgVmMapping.getSecurityGroupId() == securityGroupId) {
                    _securityGroupVMMapDao.remove(sgVmMapping.getId());
                } else {
                    List netRules = _networkRuleConfigDao.listBySecurityGroupId(sgVmMapping.getSecurityGroupId());
                    for (NetworkRuleConfigVO netRule : netRules) {
                        if (!alreadyMappedPorts.contains(netRule.getPublicPort())) {
                            FirewallRuleVO newFwRule = new FirewallRuleVO();
                            newFwRule.setEnabled(true);
                            newFwRule.setForwarding(true);
        if (domainId != null) {
                            newFwRule.setPrivatePort(netRule.getPrivatePort());
                            newFwRule.setProtocol(netRule.getProtocol());
                            newFwRule.setPublicPort(netRule.getPublicPort());
                            newFwRule.setPublicIpAddress(publicIp);
                            newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                            newFwRule.setGroupId(netRule.getSecurityGroupId());

                            fwRulesToAdd.add(newFwRule);

                            alreadyMappedPorts.add(netRule.getPublicPort());
                        }
                    }
                }
            }

            for (FirewallRuleVO addedRule : fwRulesToAdd) {
                _firewallRulesDao.persist(addedRule);

                String description = "created new ip forwarding rule [" + addedRule.getPublicIpAddress() + ":" + addedRule.getPublicPort() + "]->["
                        + addedRule.getPrivateIpAddress() + ":" + addedRule.getPrivatePort() + "]" + " " + addedRule.getProtocol();

                EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_NET_RULE_ADD, description);
            }

            // save off an event for removing the security group
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(userVm.getAccountId());
            event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_REMOVE);
            event.setDescription("Successfully removed port forwarding service " + securityGroup.getName() + " from virtual machine " + userVm.getName());
            event.setLevel(EventVO.LEVEL_INFO);
            String params = "sgId="+securityGroup.getId()+"\nvmId="+vmId;
            event.setParameters(params);
            _eventDao.persist(event);

            _networkMgr.updateFirewallRules(publicIp, fwRulesToAdd, router);

            txn.commit();
        } catch (Exception ex) {
            txn.rollback();
            throw new CloudRuntimeException("Unhandled exception", ex);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(publicIp);
            }
        }
    }

    @Override
    public Long validateSecurityGroupsAndInstance(List securityGroupIds, Long instanceId) {
        if ((securityGroupIds == null) || securityGroupIds.isEmpty() || (instanceId == null)) {
            return null;
        }

        List securityGroups = new ArrayList();
        for (Long securityGroupId : securityGroupIds) {
            if (securityGroupId.longValue() == 0) {
                continue;
            }
            SecurityGroupVO securityGroup = _securityGroupDao.findById(securityGroupId);
            if (securityGroup == null) {
                return null;
            }
            securityGroups.add(securityGroup);
        }

        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            return null;
        }

        long accountId = userVm.getAccountId();
        for (SecurityGroupVO securityGroup : securityGroups) {
            Long sgAccountId = securityGroup.getAccountId();
            if ((sgAccountId != null) && (sgAccountId.longValue() != accountId)) {
                return null;
            }
        }
        return Long.valueOf(accountId);
    }

    private FirewallRuleVO createFirewallRule(long userId, String ipAddress, UserVm userVm, String publicPort, String privatePort, String protocol, Long securityGroupId) throws NetworkRuleConflictException {
        // sanity check that the vm can be applied to the load balancer
        ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
        if ((offering == null) || !GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
            if (s_logger.isDebugEnabled()) {
        }

                s_logger.debug("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
            }

            throw new IllegalArgumentException("Unable to create port forwarding rule (" + protocol + ":" + publicPort + "->" + privatePort+ ") for virtual machine " + userVm.toString() + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
        }

        // check for ip address/port conflicts by checking existing forwarding and load balancing rules
        List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);
        Map> mappedPublicPorts = new HashMap>();

        if (existingRulesOnPubIp != null) {
            for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                mappedPublicPorts.put(fwRule.getPublicPort(), new Pair(fwRule.getPrivateIpAddress(), fwRule.getPrivatePort()));
            }
        }

        Pair privateIpPort = mappedPublicPorts.get(publicPort);
        if (privateIpPort != null) {
            if (privateIpPort.first().equals(userVm.getGuestIpAddress()) && privateIpPort.second().equals(privatePort)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("skipping the creating of firewall rule " + ipAddress + ":" + publicPort + " to " + userVm.getGuestIpAddress() + ":" + privatePort + "; rule already exists.");
                }
                return null; // already mapped
                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + publicPort
                        + " already exists, found while trying to create mapping to " + userVm.getGuestIpAddress() + ":" + privatePort + ((securityGroupId == null) ? "." : " from port forwarding service "
                        + securityGroupId.toString() + "."));
            }
        }

        FirewallRuleVO newFwRule = new FirewallRuleVO();
        newFwRule.setEnabled(true);
        newFwRule.setForwarding(true);
        newFwRule.setPrivatePort(privatePort);
        newFwRule.setProtocol(protocol);
        newFwRule.setPublicPort(publicPort);
        newFwRule.setPublicIpAddress(ipAddress);
        newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
        newFwRule.setGroupId(securityGroupId);

        // In 1.0 the rules were always persisted when a user created a rule.  When the rules get sent down
        // the stopOnError parameter is set to false, so the agent will apply all rules that it can.  That
        // behavior is preserved here by persisting the rule before sending it to the agent.
        _firewallRulesDao.persist(newFwRule);

        boolean success = _networkMgr.updateFirewallRule(newFwRule, null, null);

        // Save and create the event
        String description;
        String ruleName = "ip forwarding";
        String level = EventVO.LEVEL_INFO;
        Account account = _accountDao.findById(userVm.getAccountId());

        if (success == true) {
            description = "created new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        } else {
            level = EventVO.LEVEL_ERROR;
            description = "failed to create new " + ruleName + " rule [" + newFwRule.getPublicIpAddress() + ":" + newFwRule.getPublicPort() + "]->["
                    + newFwRule.getPrivateIpAddress() + ":" + newFwRule.getPrivatePort() + "]" + " " + newFwRule.getProtocol();
        }

        EventUtils.saveEvent(Long.valueOf(userId), account.getId(), level, EventTypes.EVENT_NET_RULE_ADD, description);

        return newFwRule;
    }

    @Override
    public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) {
        SearchCriteria sc = _eventDao.createSearchCriteria();
        if (userId > 0) {
            sc.addAnd("userId", SearchCriteria.Op.EQ, userId);
        }
        if (accountId > 0) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (level != null) {
            sc.addAnd("level", SearchCriteria.Op.EQ, level);
        }
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate);
        }

        return _eventDao.search(sc, null);
    }

    private Date massageDate(Date date, int hourOfDay, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    @Override
        Object name = cmd.getServiceOfferingName();
    public List searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list users.");
            }
        } else {
            // default domainId to the admin's domain
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(UserAccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object username = cmd.getUsername();
        Object type = cmd.getAccountType();
        Object accountName = cmd.getAccountName();
        Object state = cmd.getState();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _userAccountDao.createSearchBuilder();
        sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        if ((accountName == null) && (domainId != null)) {
            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 (keyword != null) {
            SearchCriteria ssc = _userAccountDao.createSearchCriteria();
            ssc.addOr("username", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("firstname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("lastname", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("email", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("accountState", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("username", SearchCriteria.Op.SC, ssc);
        }

        if (username != null) {
            sc.setParameters("username", "%" + username + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
            if (domainId != null) {
                sc.setParameters("domainId", domainId);
            }
        } else if (domainId != null) {
            DomainVO domainVO = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domainVO.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        return _userAccountDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServiceOfferings(ListServiceOfferingsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(ServiceOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _offeringsDao.createSearchCriteria();

        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Long vmId = cmd.getVirtualMachineId();

        if (keyword != null) {
            SearchCriteria ssc = _offeringsDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        } else if (vmId != null) {
            Account account = (Account)UserContext.current().getAccountObject();

            UserVmVO vmInstance = _userVmDao.findById(vmId);
            if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
                throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
            }
            if ((account != null) && !isAdmin(account.getType())) {
                if (account.getId() != vmInstance.getAccountId()) {
                    throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
                }
            }

            ServiceOfferingVO offering = _offeringsDao.findById(vmInstance.getServiceOfferingId());
            sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());
            
            // Only return offerings with the same Guest IP type and storage pool preference
            sc.addAnd("guestIpType", SearchCriteria.Op.EQ, offering.getGuestIpType());
            sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, offering.getUseLocalStorage());
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        return _offeringsDao.search(sc, searchFilter);
    }

    @Override
    public List searchForClusters(ListClustersCmd cmd) {
        Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _clusterDao.createSearchCriteria();

        Object id = cmd.getId();
        Object name = cmd.getClusterName();
        Object podId = cmd.getPodId();
        Object zoneId = cmd.getZoneId();

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
        return _hostPodDao.search(sc, searchFilter);
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        
        if (podId != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }
        
        if (zoneId != null) {
        	sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        return _clusterDao.search(sc, searchFilter);
    }

    @Override
    public List searchForServers(ListHostsCmd cmd) {
        Object name = cmd.getHostName();
        Object type = cmd.getType();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object cluster = cmd.getClusterId();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        return searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zone, pod, cluster, id, keyword);
    }

    private List searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword) {
        Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
        SearchCriteria sc = _hostDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _hostDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("status", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }
        if (state != null) {
            sc.addAnd("status", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (cluster != null) {
            sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForPods(ListPodsByCmd cmd) {
        Filter searchFilter = new Filter(HostPodVO.class, "dataCenterId", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _hostPodDao.createSearchCriteria();

        String podName = cmd.getPodName();
        Long id = cmd.getId();
        Long zoneId = cmd.getZoneId();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _hostPodDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (podName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + podName + "%");
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
    }

    @Override
    public List searchForZones(Criteria c) {
        Long dataCenterId = (Long) c.getCriteria(Criteria.DATACENTERID);

        if (dataCenterId != null) {
            DataCenterVO dc = _dcDao.findById(dataCenterId);
            List datacenters = new ArrayList();
            datacenters.add(dc);
            return datacenters;
        }

        Filter searchFilter = new Filter(DataCenterVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _dcDao.createSearchCriteria();

        String zoneName = (String) c.getCriteria(Criteria.ZONENAME);

        if (zoneName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + zoneName + "%");
        }

        return _dcDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVlans(ListVlanIpRangesCmd cmd) throws InvalidParameterValueException {
        // If an account name and domain ID are specified, look up the account
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        if (accountName != null && domainId != null) {
    }
            Account account = _accountDao.findActiveAccount(accountName, domainId);
            if (account == null) {
                throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
            } else {
                accountId = account.getId();
            }
        } 

        Filter searchFilter = new Filter(VlanVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object vlan = cmd.getVlan();
        Object dataCenterId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vlanDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("vlan", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
       
        if (accountId != null) {
        	SearchBuilder accountVlanMapSearch = _accountVlanMapDao.createSearchBuilder();
        	accountVlanMapSearch.and("accountId", accountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.join("accountVlanMapSearch", accountVlanMapSearch, sb.entity().getId(), accountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        if (podId != null) {
        	SearchBuilder podVlanMapSearch = _podVlanMapDao.createSearchBuilder();
        	podVlanMapSearch.and("podId", podVlanMapSearch.entity().getPodId(), SearchCriteria.Op.EQ);
        	sb.join("podVlanMapSearch", podVlanMapSearch, sb.entity().getId(), podVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.INNER);
        }
        
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _vlanDao.createSearchCriteria();
            ssc.addOr("vlanId", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("ipRange", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("vlanId", SearchCriteria.Op.SC, ssc);
        } else {
        	if (id != null) {
            	sc.setParameters("id", id);
        	}
        	
        	if (vlan != null) {
        		sc.setParameters("vlan", vlan);
        	}
        
        	if (dataCenterId != null) {
            	sc.setParameters("dataCenterId", dataCenterId);
        	}
        	
        	if (accountId != null) {
        		sc.setJoinParameters("accountVlanMapSearch", "accountId", accountId);
        	}
        	
        	if (podId != null) {
                        + " and parentId " + parentId);
        		sc.setJoinParameters("podVlanMapSearch", "podId", podId);
        	}
        }

        return _vlanDao.search(sc, searchFilter);
    }
    
    @Override
    public Long getPodIdForVlan(long vlanDbId) {
    	List podVlanMaps = _podVlanMapDao.listPodVlanMapsByVlan(vlanDbId);
    	if (podVlanMaps.isEmpty()) {
    		return null;
    	} else {
    		return podVlanMaps.get(0).getPodId();
    	}
    }
    
    @Override
    public List searchForConfigurations(ListCfgsByCmd cmd) {
        Filter searchFilter = new Filter(ConfigurationVO.class, "name", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _configDao.createSearchCriteria();

        Object name = cmd.getConfigName();
        Object category = cmd.getCategory();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _configDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instance", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("component", SearchCriteria.Op.LIKE, "%" + keyword + "%");
    	ImageFormat imageFormat = null;
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("category", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("value", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (category != null) {
            sc.addAnd("category", SearchCriteria.Op.EQ, category);
        }

        // hidden configurations are not displayed using the search API
        sc.addAnd("category", SearchCriteria.Op.NEQ, "Hidden");

        return _configDao.search(sc, searchFilter);
    }

    @Override
    public List searchForAlertServers(Criteria c) {
        Filter searchFilter = new Filter(HostVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _hostDao.createSearchCriteria();

        Object[] states = (Object[]) c.getCriteria(Criteria.STATE);

        if (states != null) {
            sc.addAnd("status", SearchCriteria.Op.IN, states);
        }

        return _hostDao.search(sc, searchFilter);
    }

    @Override
    public List searchForTemplates(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object name = c.getCriteria(Criteria.NAME);
        Object isPublic = c.getCriteria(Criteria.ISPUBLIC);
        Object id = c.getCriteria(Criteria.ID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);

        SearchBuilder sb = _templateDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("publicTemplate", sb.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
        sb.and("format", sb.entity().getFormat(), SearchCriteria.Op.NEQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        
        SearchCriteria sc = sb.create();
        
        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (isPublic != null) {
            sc.setParameters("publicTemplate", isPublic);
        }
        if (creator != null) {
            sc.setParameters("accountId", creator);
        }

        sc.setParameters("format", ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    @Override
    public List listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
        TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        if ((account == null) || (account.getType() == Account.ACCOUNT_TYPE_ADMIN)) {
            // validate domainId before proceeding
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new InvalidParameterValueException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list ISOs.  Unable to find account " + accountName + " in domain " + domainId);
                }
            } else if (account != null) {
                accountId = account.getId();
            }
        } else {
            accountId = account.getId();
        }

        return listTemplates(cmd.getId(), cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, accountId, cmd.getPageSizeVal().intValue(), cmd.getStartIndex(), cmd.getZoneId());
    }

    private List listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long accountId, Integer pageSize, Long startIndex, Long zoneId) throws InvalidParameterValueException {
        VMTemplateVO template = null;
    	if (templateId != null) {
    		template = _templateDao.findById(templateId);
    		if (template == null) {
    			throw new InvalidParameterValueException("Please specify a valid template ID.");
    		}// If ISO requested then it should be ISO.
    		if (isIso && template.getFormat() != ImageFormat.ISO){
    			s_logger.error("Template Id " + templateId + " is not an ISO");
    			throw new InvalidParameterValueException("Template Id " + templateId + " is not an ISO");
    		}// If ISO not requested then it shouldn't be an ISO.
    		if (!isIso && template.getFormat() == ImageFormat.ISO){
    			s_logger.error("Incorrect format of the template id " + templateId);
    			throw new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the template id " + templateId);
    		}
        }
    	
    	Account account = null;
    	DomainVO domain = null;
        if (accountId != null) {
        	account = _accountDao.findById(accountId);
        	domain = _domainDao.findById(account.getDomainId());
        } else {
        	domain = _domainDao.findById(DomainVO.ROOT_DOMAIN);
        }
        
        List templates = new ArrayList();
        
        if (template == null) {
    		templates = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, bootable, account, domain, pageSize, startIndex, zoneId);
    	} else {
    		templates = new ArrayList();
    		templates.add(template);
    	}
        
        return templates;
    }

    @Override
    public List listPermittedTemplates(long accountId) {
        return _launchPermissionDao.listPermittedTemplates(accountId);
    }

    @Override
    public List listPods(long dataCenterId) {
        return _hostPodDao.listByDataCenterId(dataCenterId);
    }
    
    @Override
    public String changePrivateIPRange(boolean add, Long podId, String startIP, String endIP) throws InvalidParameterValueException {
        return _configMgr.changePrivateIPRange(add, podId, startIP, endIP);
    }

    @Override
    public User findUserById(Long userId) {
        return _userDao.findById(userId);
    }

    @Override
    public List findAccountsLike(String accountName) {
        return _accountDao.findAccountsLike(accountName);
    }

    @Override
    public Account findActiveAccountByName(String accountName) {
        return _accountDao.findActiveAccountByName(accountName);
    }

    @Override
    public Account findActiveAccount(String accountName, Long domainId) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }
        return _accountDao.findActiveAccount(accountName, domainId);
    }

    @Override
    public Account findAccountByName(String accountName, Long domainId) {
        if (domainId == null)
            domainId = DomainVO.ROOT_DOMAIN;
        return _accountDao.findAccount(accountName, domainId);
    }

    @Override
    public Account findAccountById(Long accountId) {
        return _accountDao.findById(accountId);
    }

    @Override
    public List searchForAccounts(ListAccountsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = cmd.getId();
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId == null) {
                // default domainId to the admin's domain
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            } else if (account != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list accounts");
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(AccountVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getAccountType();
        Object state = cmd.getState();
        Object isCleanupRequired = cmd.isCleanupRequired();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _accountDao.createSearchBuilder();
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nid", sb.entity().getId(), SearchCriteria.Op.NEQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("needsCleanup", sb.entity().getNeedsCleanup(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _accountDao.createSearchCriteria();
            ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("accountName", SearchCriteria.Op.SC, ssc);
        }

        if (accountName != null) {
            sc.setParameters("accountName", "%" + accountName + "%");
        }

        if (accountId != null) {
            sc.setParameters("id", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            sc.setParameters("nid", 1L);
        } else {
        	sc.setParameters("nid", 1L);
        }

        if (type != null) {
            sc.setParameters("type", type);
        }

        if (state != null) {
            sc.setParameters("state", state);
        }

        if (isCleanupRequired != null) {
            sc.setParameters("needsCleanup", isCleanupRequired);
        }

        return _accountDao.search(sc, searchFilter);
    }

    @Override
    public Account findAccountByIpAddress(String ipAddress) {
        IPAddressVO address = _publicIpAddressDao.findById(ipAddress);
        if ((address != null) && (address.getAccountId() != null)) {
            return _accountDao.findById(address.getAccountId());
        }
        return null;
    }

    @Override
    public boolean deleteLimit(Long limitId) {
        // A limit ID must be passed in
        if (limitId == null)
            return false;

        return _resourceLimitDao.expunge(limitId);
    }

    @Override
    public ResourceLimitVO findLimitById(long limitId) {
        return _resourceLimitDao.findById(limitId);
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
        Boolean isPublic = (Boolean) c.getCriteria(Criteria.ISPUBLIC);
        Long creator = (Long) c.getCriteria(Criteria.CREATED_BY);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchCriteria sc = _templateDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _templateDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (creator != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, creator);
        }
        if (ready != null) {
            sc.addAnd("ready", SearchCriteria.Op.EQ, ready);
        }
        if (isPublic != null) {
            sc.addAnd("publicTemplate", SearchCriteria.Op.EQ, isPublic);
        }

        sc.addAnd("format", SearchCriteria.Op.EQ, ImageFormat.ISO);

        return _templateDao.search(sc, searchFilter);
    }

    @Override
    public List findVMInstancesLike(String vmInstanceName) {
        return _vmInstanceDao.findVMInstancesLike(vmInstanceName);
    }

    @Override
    public VMInstanceVO findVMInstanceById(long vmId) {
        return _vmInstanceDao.findById(vmId);
    }

    @Override
    public UserVmVO findUserVMInstanceById(long userVmId) {
        return _userVmDao.findById(userVmId);
    }

    @Override
    public ServiceOfferingVO findServiceOfferingById(long offeringId) {
        return _offeringsDao.findById(offeringId);
    }

    @Override
    public List listAllServiceOfferings() {
        return _offeringsDao.listAllIncludingRemoved();
    }

    @Override
    public List listAllActiveHosts() {
        return _hostDao.listAll();
    }

    @Override
    public DataCenterVO findDataCenterById(long dataCenterId) {
        return _dcDao.findById(dataCenterId);
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        }
        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

        if (hostId != null) {
            sc.setParameters("hostIdEQ", hostId);
        } else {
            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);

            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();
            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }
        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        }

        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        	{
        		//do nothing
        	}
        	else
        	{
        		returnableVolumes.add(v);
        	}
        }
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
            try {
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);
        }

        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }

    @Override
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            }
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
        }
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
    @Override
    @Override

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

				mac.init(keySpec);
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

                    if (account != null) {
    @Override
        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group

                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
		if(rootVolume!=null){
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }
        Object ipAddress = cmd.getIpAddress();
    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

    }
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        	
        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {

            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
				return false;
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
			else
            systemVMs.addAll(searchForConsoleProxy(c));
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
				return true;
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
						"HmacSHA1");
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
		}
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
    	
			if(!poolStatus.equals(Status.Up))
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Method invocation
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
=======
    public List searchForLimits(Criteria c) {
        Long domainId = (Long) c.getCriteria(Criteria.DOMAINID);
        Long accountId = (Long) c.getCriteria(Criteria.ACCOUNTID);
        ResourceType type = (ResourceType) c.getCriteria(Criteria.TYPE);
        
        // For 2.0, we are just limiting the scope to having an user retrieve
        // limits for himself and if limits don't exist, use the ROOT domain's limits.
        // - Will
        List limits = new ArrayList();
        

        if(accountId!=null && domainId!=null)
        {
	        //if domainId==1 and account belongs to admin
	        //return all records for resource limits (bug 3778)
	        
	        if(domainId==1)
	        {
	        	AccountVO account = _accountDao.findById(accountId);
	        	
	        	if(account!=null && account.getType()==1)
	        	{
	        		//account belongs to admin
	        		//return all limits
	        		limits = _resourceLimitDao.listAllIncludingRemoved();
	        		return limits;
	        	}
	        }
	
	        //if account belongs to system, accountid=1,domainid=1
	        //return all the records for resource limits (bug:3778)
	        if(accountId==1 && domainId==1)
	        {
	        	limits = _resourceLimitDao.listAllIncludingRemoved();
	        	return limits;
	        }
        }
        
        if (accountId != null) {
        	SearchBuilder sb = _resourceLimitDao.createSearchBuilder();
        	sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        	sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);

        	SearchCriteria sc = sb.create();

        	if (accountId != null) {
        		sc.setParameters("accountId", accountId);
        	}

        	if (type != null) {
        		sc.setParameters("type", type);
        	}
        	
        	// Listing all limits for an account
        	if (type == null) {
        		//List userLimits = _resourceLimitDao.search(sc, searchFilter);
        		List userLimits = _resourceLimitDao.listByAccountId(accountId);
	        	List rootLimits = _resourceLimitDao.listByDomainId(DomainVO.ROOT_DOMAIN);
	        	ResourceType resourceTypes[] = ResourceType.values();
        	
	        	for (ResourceType resourceType: resourceTypes) {
	        		boolean found = false;
	        		for (ResourceLimitVO userLimit : userLimits) {
	        			if (userLimit.getType() == resourceType) {
	        				limits.add(userLimit);
	        				found = true;
	        				break;
	        			}
	        		}
	        		if (!found) {
	        			// Check the ROOT domain
	        			for (ResourceLimitVO rootLimit : rootLimits) {
	        				if (rootLimit.getType() == resourceType) {
	        					limits.add(rootLimit);
	        					found = true;
	        					break;
	        				}
	        			}
	        		}
	        		if (!found) {
	        			limits.add(new ResourceLimitVO(domainId, accountId, resourceType, -1L));
	        		}
	        	}
        	} else {
        		AccountVO account = _accountDao.findById(accountId);
        		limits.add(new ResourceLimitVO(null, accountId, type, _accountMgr.findCorrectResourceLimit(account, type)));
        	}
        } else if (domainId != null) {
        	if (type == null) {
        		ResourceType resourceTypes[] = ResourceType.values();
        		List domainLimits = _resourceLimitDao.listByDomainId(domainId);
        		for (ResourceType resourceType: resourceTypes) {
	        		boolean found = false;
	        		for (ResourceLimitVO domainLimit : domainLimits) {
	        			if (domainLimit.getType() == resourceType) {
	        				limits.add(domainLimit);
	        				found = true;
	        				break;
	        			}
	        		}
	        		if (!found) {
	        			limits.add(new ResourceLimitVO(domainId, null, resourceType, -1L));
	        		}
        		}
        	} else {
        		limits.add(_resourceLimitDao.findByDomainIdAndType(domainId, type));
        	}
        }
        return limits;
    }

    @Override
    public long findCorrectResourceLimit(ResourceType type, long accountId) {
        AccountVO account = _accountDao.findById(accountId);
        
        if (account == null) {
            return -1;
        }
        
        return _accountMgr.findCorrectResourceLimit(account, type);
    }
    
    @Override
    public long getResourceCount(ResourceType type, long accountId) {
    	AccountVO account = _accountDao.findById(accountId);
        
        if (account == null) {
            return -1;
        }
        
        return _accountMgr.getResourceCount(account, type);
    }

    @Override
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
Solution content
    }

    @Override
    public List listIsos(Criteria c) {
        Filter searchFilter = new Filter(VMTemplateVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Boolean ready = (Boolean) c.getCriteria(Criteria.READY);
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Long guestOSId = cmd.getOsTypeId();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId().longValue() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
=======
    public VlanVO findVlanById(long vlanDbId) {
        return _vlanDao.findById(vlanDbId);
    }
    
    @Override
    public long extractVolumeAsync(String url, Long volumeId, Long zoneId) throws URISyntaxException{
    	
    	URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }
        String host = uri.getHost();
        
        try {
        	InetAddress hostAddr = InetAddress.getByName(host);
        	if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
        		throw new IllegalArgumentException("Illegal host specified in url");
        	}
        	if (hostAddr instanceof Inet6Address) {
        		throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
        	}
        } catch (UnknownHostException uhe) {
        	throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
    		throw new IllegalArgumentException("Please specify a valid zone.");
    	}
        
        VolumeVO volume = findVolumeById(volumeId); 
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");
        
 		ExtractTemplateParam param = new ExtractTemplateParam(userId, volumeId, zoneId, eventId , url);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
    	job.setUserId(userId);
    	job.setAccountId(accountId);
        job.setCmd("ExtractVolume");
        job.setCmdInfo(gson.toJson(param));
        job.setCmdOriginator(ExtractVolumeCmd.getStaticName());        
        return _asyncMgr.submitAsyncJob(job);
    	
    }
    
    @Override
    public void extractVolume(String url, Long volumeId, Long zoneId, long eventId, Long asyncJobId) throws URISyntaxException, InternalErrorException{
          
        VolumeVO volume = findVolumeById(volumeId);        
        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);
        
        saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(asyncJobId, Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(asyncJobId, AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(asyncJobId, AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }

        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd", eventId, asyncJobId, _asyncMgr);
        
    }
    
    @Override
    public long extractTemplateAsync(String url, Long templateId, Long zoneId) throws URISyntaxException{
        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }
        String host = uri.getHost();
        
        try {
        	InetAddress hostAddr = InetAddress.getByName(host);
        	if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
        		throw new IllegalArgumentException("Illegal host specified in url");
        	}
        	if (hostAddr instanceof Inet6Address) {
        		throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
        	}
        } catch (UnknownHostException uhe) {
        	throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
    	if (_dcDao.findById(zoneId) == null) {
    		throw new IllegalArgumentException("Please specify a valid zone.");
    	}
        
        VMTemplateVO template = findTemplateById(templateId);
        
        VMTemplateHostVO tmpltHostRef = findTemplateHostRef(templateId, zoneId);
        if (tmpltHostRef != null && tmpltHostRef.getDownloadState() != com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED){
        	throw new IllegalArgumentException("The template hasnt been downloaded ");
        }
        
        boolean isISO = template.getFormat() == ImageFormat.ISO;
        if ( _uploadMonitor.isTypeUploadInProgress(templateId, isISO ? Type.ISO : Type.TEMPLATE) ){
            throw new IllegalArgumentException(template.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same"); 
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = template.getAccountId();
        String event = isISO ? EventTypes.EVENT_ISO_UPLOAD : EventTypes.EVENT_TEMPLATE_UPLOAD;
        long eventId = saveScheduledEvent(userId, accountId, event, "Extraction job");
        
 		ExtractTemplateParam param = new ExtractTemplateParam(userId, templateId, zoneId, eventId , url);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
    	job.setUserId(userId);
    	job.setAccountId(accountId);
        job.setCmd("ExtractTemplate");
        job.setCmdInfo(gson.toJson(param));
        job.setCmdOriginator(isISO ? ExtractIsoCmd.getStaticName() : ExtractTemplateCmd.getStaticName());
        
        return _asyncMgr.submitAsyncJob(job);
    	    	
    }
    
    @Override
    public void extractTemplate(String url, Long templateId, Long zoneId, long eventId, long asyncJobId) throws URISyntaxException{

    	VMTemplateVO template = findTemplateById(templateId);        
        VMTemplateHostVO tmpltHostRef = findTemplateHostRef(templateId, zoneId);
        String event = template.getFormat() == ImageFormat.ISO ? EventTypes.EVENT_ISO_UPLOAD : EventTypes.EVENT_TEMPLATE_UPLOAD;
        saveStartedEvent(template.getAccountId(), template.getAccountId(), event, "Starting upload of " +template.getName()+ " to " +url, eventId);
        _tmpltMgr.extract(template, url, tmpltHostRef, zoneId, eventId, asyncJobId, _asyncMgr);
        
    }
    
    @Override
    public Long createTemplate(long userId, Long zoneId, String name, String displayText, boolean isPublic, boolean featured, String format, String diskType, String url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable) throws InvalidParameterValueException,IllegalArgumentException, ResourceAllocationException {
        try
        {
            if (name.length() > 32)
            {
                throw new InvalidParameterValueException("Template name should be less than 32 characters");
            }
            	
            if (!name.matches("^[\\p{Alnum} ._-]+")) {
                throw new InvalidParameterValueException("Only alphanumeric, space, dot, dashes and underscore characters allowed");
            }
        	
            ImageFormat imgfmt = ImageFormat.valueOf(format.toUpperCase());
            if (imgfmt == null) {
                throw new IllegalArgumentException("Image format is incorrect " + format + ". Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
            }
            
            FileSystem fileSystem = FileSystem.valueOf(diskType);
            if (fileSystem == null) {
                throw new IllegalArgumentException("File system is incorrect " + diskType + ". Supported file systems are " + EnumUtils.listValues(FileSystem.values()));
            }
            
            URI uri = new URI(url);
            if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme().equalsIgnoreCase("file"))) {
               throw new IllegalArgumentException("Unsupported scheme for url: " + url);
            }
            int port = uri.getPort();
            if (!(port == 80 || port == 443 || port == -1)) {
            	throw new IllegalArgumentException("Only ports 80 and 443 are allowed");
            }
            String host = uri.getHost();
            try {
            	InetAddress hostAddr = InetAddress.getByName(host);
            	if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
            		throw new IllegalArgumentException("Illegal host specified in url");
            	}
            	if (hostAddr instanceof Inet6Address) {
            		throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            	}
            } catch (UnknownHostException uhe) {
            	throw new IllegalArgumentException("Unable to resolve " + host);
            }
            
            // Check that the resource limit for templates/ISOs won't be exceeded
            UserVO user = _userDao.findById(userId);
            if (user == null) {
                throw new IllegalArgumentException("Unable to find user with id " + userId);
            }
        	AccountVO account = _accountDao.findById(user.getAccountId());
            if (_accountMgr.resourceLimitExceeded(account, ResourceType.template)) {
            	ResourceAllocationException rae = new ResourceAllocationException("Maximum number of templates and ISOs for account: " + account.getAccountName() + " has been exceeded.");
            	rae.setResourceType("template");
            	throw rae;
            }
            
            // If a zoneId is specified, make sure it is valid
            if (zoneId != null) {
            	if (_dcDao.findById(zoneId) == null) {
            		throw new IllegalArgumentException("Please specify a valid zone.");
            	}
            }
            VMTemplateVO systemvmTmplt = _templateDao.findRoutingTemplate();
            if (systemvmTmplt.getName().equalsIgnoreCase(name) || systemvmTmplt.getDisplayText().equalsIgnoreCase(displayText)) {
            	throw new IllegalArgumentException("Cannot use reserved names for templates");
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
            }
        }
        
Solution content
        	}
        }
        } else if (domainId != null) {
    	Long guestOSId = cmd.getOsTypeId();
        } else {
    }

    @Override
    public boolean updateTemplate(UpdateTemplateOrIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long id = cmd.getId();
    	String name = cmd.getName();
    	String displayText = cmd.getDisplayText();
    	String format = cmd.getFormat();
    	Boolean passwordEnabled = cmd.isPasswordEnabled();
    	Boolean bootable = cmd.isBootable();
    	Account account= (Account)UserContext.current().getAccountObject();
    	
    	//verify that template exists
    	VMTemplateVO template = findTemplateById(id);
    	if (template == null) {
    		throw new InvalidParameterValueException("unable to find template/iso with id " + id);
    	}
    	
        //Don't allow to modify system template
        if (id == Long.valueOf(1)) {
        	throw new InvalidParameterValueException("Unable to update template/iso with id " + id);
        }
    	
    	//do a permission check
        if (account != null) {
            Long templateOwner = template.getAccountId();
            if (!BaseCmd.isAdmin(account.getType())) {
                if ((templateOwner == null) || (account.getId() != templateOwner.longValue())) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied.");
                }
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(templateOwner);
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new PermissionDeniedException("Unable to modify template/iso with id " + id + ", permission denied");
                }
            }
        }
        

    	boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
    	if (!updateNeeded) {
    		return true;
    	}
    	
    	template = _templateDao.createForUpdate(id);
    	
    	if (name != null) {
    		template.setName(name);
    	}
    	
    	if (displayText != null) {
    		template.setDisplayText(displayText);
    	}
    	
    	ImageFormat imageFormat = null;
    	if (format != null) {
    		try {
    			imageFormat = ImageFormat.valueOf(format.toUpperCase());
    		} catch (IllegalArgumentException e) {
    			throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
    		}
    		
    		template.setFormat(imageFormat);
    	}
    	
    	if (guestOSId != null) {
    		GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
    		
    		if (guestOS == null) {
        }
            sb.and("allocated", sb.entity().getAllocated(), SearchCriteria.Op.NNULL);

        if (hostId != null) {
        	{
    			throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
    		} else {
    			template.setGuestOSId(guestOSId);
    		}
    	}
    	
    	if (passwordEnabled != null) {
    		template.setEnablePassword(passwordEnabled);
    	}
    	
    	if (bootable != null) {
    		template.setBootable(bootable);
    	}
    	
        return _templateDao.update(id, template);
    }
    
    @Override
    public boolean copyTemplate(long userId, long templateId, long sourceZoneId, long destZoneId, long startEventId) throws InternalErrorException {
    	boolean success = false;
		try {
			success = _tmpltMgr.copy(userId, templateId, sourceZoneId, destZoneId, startEventId);
		} catch (Exception e) {
			s_logger.warn("Unable to copy template " + templateId + " from zone " + sourceZoneId + " to " + destZoneId , e);
			success = false;
		}
		return success;
    }

    @Override
    public VMTemplateVO findTemplateById(long templateId) {
        return _templateDao.findById(templateId);
    }
    
    @Override
    public List searchForUserVMs(ListVMsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            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();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.NAME, cmd.getInstanceName());
        c.addCriteria(Criteria.STATE, cmd.getState());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        // ignore these search requests if it's not an admin
        if (isAdmin == true) {
            c.addCriteria(Criteria.DOMAINID, domainId);
            c.addCriteria(Criteria.PODID, cmd.getPodId());
            c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        }

        c.addCriteria(Criteria.ACCOUNTID, new Object[] {accountId});
        c.addCriteria(Criteria.ISADMIN, isAdmin); 

        return searchForUserVMs(c);
    }

    @Override
    public List searchForUserVMs(Criteria c) {
        Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        
        SearchBuilder sb = _userVmDao.createSearchBuilder();
       
        // some criteria matter for generating the join condition
        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        
        // get the rest of the criteria
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object notState = c.getCriteria(Criteria.NOTSTATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object hostName = c.getCriteria(Criteria.HOSTNAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
        Object isAdmin = c.getCriteria(Criteria.ISADMIN);
        Object ipAddress = c.getCriteria(Criteria.IPADDRESS);
        Object groupId = c.getCriteria(Criteria.GROUPID);
        
        sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("stateEQ", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("stateNEQ", sb.entity().getState(), SearchCriteria.Op.NEQ);
        sb.and("stateNIN", sb.entity().getState(), SearchCriteria.Op.NIN);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        } else {
        sb.and("hostIdEQ", sb.entity().getHostId(), SearchCriteria.Op.EQ);
        sb.and("hostIdIN", sb.entity().getHostId(), SearchCriteria.Op.IN);
        sb.and("guestIP", sb.entity().getGuestIpAddress(), SearchCriteria.Op.EQ);
        
        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (groupId != null && (Long)groupId == -1) {
        	SearchBuilder vmSearch = _groupVMMapDao.createSearchBuilder();
        	vmSearch.and("instanceId", vmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("vmSearch", vmSearch, sb.entity().getId(), vmSearch.entity().getInstanceId(), JoinBuilder.JoinType.LEFTOUTER);
        }
        else if (groupId != null) {
        	SearchBuilder groupSearch = _groupVMMapDao.createSearchBuilder();
        	groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
            sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
        }

        // populate the search criteria with the values passed in
        SearchCriteria sc = sb.create();
        
        if (groupId != null && (Long)groupId == -1){
        	sc.setJoinParameters("vmSearch", "instanceId", (Object)null);
        }
        else if (groupId != null ) {
        	sc.setJoinParameters("groupSearch", "groupId", groupId);
        }

        if (keyword != null) {
            SearchCriteria ssc = _userVmDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("displayName", SearchCriteria.Op.SC, ssc);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }
        if (accountIds != null) {
            if (accountIds.length == 1) {
                if (accountIds[0] != null) {
                    sc.setParameters("accountIdEQ", accountIds[0]);
                }
            } else {
                sc.setParameters("accountIdIN", accountIds);
            }
            sc.setParameters("hostIdEQ", hostId);
        		//do nothing
            DomainVO domain = _domainDao.findById((Long)domainId);

            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }
        if (state != null) {
            if (notState != null && (Boolean) notState == true) {
                sc.setParameters("stateNEQ", state);
            } else {
                sc.setParameters("stateEQ", state);
            }
        }

        if ((isAdmin != null) && ((Boolean) isAdmin != true)) {
            sc.setParameters("stateNIN", "Destroyed", "Expunging");
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
            
            if(state == null)
            	sc.setParameters("stateNEQ", "Destroyed");
        }

            if (hostName != null) {
                List hosts = _hostDao.findHostsLike((String) hostName);
                if (hosts != null & !hosts.isEmpty()) {
                    Long[] hostIds = new Long[hosts.size()];
                    for (int i = 0; i < hosts.size(); i++) {
                        HostVO host = hosts.get(i);
                        hostIds[i] = host.getId();
                    }
                    sc.setParameters("hostIdIN", (Object[]) hostIds);
                } else {
                    return new ArrayList();
                }
            }
        }

        if (ipAddress != null) {
            sc.setParameters("guestIP", ipAddress);
        }
        
        return _userVmDao.search(sc, searchFilter);
    }

    @Override
    public FirewallRuleVO updatePortForwardingRule(UpdateIPForwardingRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	String publicIp = cmd.getPublicIp();
    	String privateIp = cmd.getPrivateIp();
    	String privatePort = cmd.getPrivatePort();
    	String publicPort = cmd.getPublicPort();
    	String protocol = cmd.getProtocol();
    	Long vmId = cmd.getVirtualMachineId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	UserVmVO userVM = null;
    	
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        IPAddressVO ipAddressVO = findIPAddressById(publicIp);
        if (ipAddressVO == null) {
            throw new InvalidParameterValueException("Unable to find IP address " + publicIp);
        }

        if (ipAddressVO.getAccountId() == null) {
            throw new InvalidParameterValueException("Unable to update port forwarding rule, owner of IP address " + publicIp + " not found.");
        }

        if (privateIp != null) {
            if (!NetUtils.isValidIp(privateIp)) {
                throw new InvalidParameterValueException("Invalid private IP address specified: " + privateIp);
            }
            Criteria c = new Criteria();
            c.addCriteria(Criteria.ACCOUNTID, new Object[] {ipAddressVO.getAccountId()});
            c.addCriteria(Criteria.DATACENTERID, ipAddressVO.getDataCenterId());
            c.addCriteria(Criteria.IPADDRESS, privateIp);
            List userVMs = searchForUserVMs(c);
        	}
            if ((userVMs == null) || userVMs.isEmpty()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid private IP address specified: " + privateIp + ", no virtual machine instances running with that address.");
            }
            userVM = userVMs.get(0);
        } else if (vmId != null) {
            userVM = findUserVMInstanceById(vmId);
            if (userVM == null) {
                throw new InvalidParameterValueException("Unable to find virtual machine with id " + vmId);
            }

            if ((ipAddressVO.getAccountId() == null) || (ipAddressVO.getAccountId().longValue() != userVM.getAccountId())) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied."); 
            }

            if (ipAddressVO.getDataCenterId() != userVM.getDataCenterId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule, IP address " + publicIp + " is not in the same availability zone as virtual machine " + userVM.toString());
            }

            privateIp = userVM.getGuestIpAddress();
        } else {
            throw new InvalidParameterValueException("No private IP address (privateip) or virtual machine instance id (virtualmachineid) specified, unable to update port forwarding rule");
        }

        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        if (account != null) {
            if (isAdmin(account.getType())) {
                if (!_domainDao.isChildDomain(account.getDomainId(), ipAddressVO.getDomainId())) {
                    throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
                }
            } else if (account.getId() != ipAddressVO.getAccountId()) {
                throw new PermissionDeniedException("Unable to update port forwarding rule on IP address " + publicIp + ", permission denied.");
            }
        }
        
        List fwRules = _firewallRulesDao.listIPForwardingForUpdate(publicIp, publicPort, protocol);
        if ((fwRules != null) && (fwRules.size() == 1)) {
            FirewallRuleVO fwRule = fwRules.get(0);
            String oldPrivateIP = fwRule.getPrivateIpAddress();
            String oldPrivatePort = fwRule.getPrivatePort();
            fwRule.setPrivateIpAddress(privateIp);
            fwRule.setPrivatePort(privatePort);
            _firewallRulesDao.update(fwRule.getId(), fwRule);
            _networkMgr.updateFirewallRule(fwRule, oldPrivateIP, oldPrivatePort);
            return fwRule;
        }
        return null;
    }

    @Override
    public FirewallRuleVO findForwardingRuleById(Long ruleId) {
        return _firewallRulesDao.findById(ruleId);
    }

    @Override
    public IPAddressVO findIPAddressById(String ipAddress) {
        return _publicIpAddressDao.findById(ipAddress);
    }

    @Override
    public List searchForNetworkRules(ListPortForwardingServiceRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long groupId = cmd.getPortForwardingServiceId();

        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAcct = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAcct != null) {
                        accountId = userAcct.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
            accountId = account.getId();
        }

        if ((groupId != null) && (accountId != null)) {
            SecurityGroupVO sg = _securityGroupDao.findById(groupId);
            if (sg != null) {
                if (sg.getAccountId() != accountId.longValue()) {
                    throw new PermissionDeniedException("Unable to list port forwarding service rules, account " + accountId + " does not own port forwarding service " + groupId);
                }
            } else {
                throw new InvalidParameterValueException("Unable to find port forwarding service with id " + groupId);
            }
        }

        Filter searchFilter = new Filter(NetworkRuleConfigVO.class, "id", true, null, null);

        // search by rule id is also supported
        Object id = cmd.getId();

        SearchBuilder sb = _networkRuleConfigDao.createSearchBuilder();
        if (id != null) {
            sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        }

        if (groupId != null) {
            sb.and("securityGroupId", sb.entity().getSecurityGroupId(), SearchCriteria.Op.EQ);
        }

        if (accountId != null) {
            // join with securityGroup table to make sure the account is the owner of the network rule
            SearchBuilder securityGroupSearch = _securityGroupDao.createSearchBuilder();

            securityGroupSearch.and("accountId", securityGroupSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
            sb.join("groupId", securityGroupSearch, securityGroupSearch.entity().getId(), sb.entity().getSecurityGroupId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (groupId != null) {
            sc.setParameters("securityGroupId", groupId);
        }

        if (accountId != null) {
            sc.setJoinParameters("groupId", "accountId", accountId);
        }

        return _networkRuleConfigDao.search(sc, searchFilter);
    }

    @Override
    public List searchForEvents(ListEventsCmd cmd) throws PermissionDeniedException, InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        boolean isAdmin = false;
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();

        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list events.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(EventVO.class, "createDate", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object type = cmd.getType();
        Object level = cmd.getLevel();
        Date startDate = cmd.getStartDate();
        Date endDate = cmd.getEndDate();
        Object keyword = cmd.getKeyword();
        Integer entryTime = cmd.getEntryTime();
        Integer duration = cmd.getDuration();

        if ((entryTime != null) && (duration != null)) {
            if (entryTime <= duration){
                throw new InvalidParameterValueException("Entry time must be greater than duration");
            }
            return listPendingEvents(entryTime, duration);
        }

        SearchBuilder sb = _eventDao.createSearchBuilder();
        sb.and("levelL", sb.entity().getLevel(), SearchCriteria.Op.LIKE);
        sb.and("levelEQ", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.LIKE);
        sb.and("domainIdEQ", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
        sb.and("createDateB", sb.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
        sb.and("createDateG", sb.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
        sb.and("createDateL", sb.entity().getCreateDate(), SearchCriteria.Op.LTEQ);

        if ((accountId == null) && (accountName == null) && (domainId != null) && isAdmin) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _eventDao.createSearchCriteria();
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("level", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("level", SearchCriteria.Op.SC, ssc);
        }
        
        if (level != null)
        	sc.setParameters("levelEQ", level);
        	
        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            if (accountName != null) {
                sc.setParameters("domainIdEQ", domainId);
                sc.setParameters("accountName", "%" + accountName + "%");
                sc.addAnd("removed", SearchCriteria.Op.NULL);
            } else if (isAdmin) {
                DomainVO domain = _domainDao.findById(domainId);
                sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }
        }

        if (type != null) {
            sc.setParameters("type", type);
        }
        
        if (startDate != null && endDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateB", startDate, endDate);
        } else if (startDate != null) {
            startDate = massageDate(startDate, 0, 0, 0);
            sc.setParameters("createDateG", startDate);
        } else if (endDate != null) {
            endDate = massageDate(endDate, 23, 59, 59);
            sc.setParameters("createDateL", endDate);
        }

        return _eventDao.searchAllEvents(sc, searchFilter);
    }

    @Override
    public List listRoutersByHostId(long hostId) {
        return _routerDao.listByHostId(hostId);
    }

    @Override
    public List listAllActiveRouters() {
        return _routerDao.listAll();
    }

    @Override
    public List searchForRouters(ListRoutersCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        	else
        	{
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        Account account = (Account)UserContext.current().getAccountObject();

        // validate domainId before proceeding
        if (domainId != null) {
            if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list routers");
            }
            if (accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                }
            }
        } else {
            domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
        }

        Filter searchFilter = new Filter(DomainRouterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getRouterName();
        Object state = cmd.getState();
        Object zone = cmd.getZoneId();
        Object pod = cmd.getPodId();
        Object hostId = cmd.getHostId();
        Object keyword = cmd.getKeyword();
        SearchBuilder sb = _routerDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
        sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _routerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (state != null) {
            sc.setParameters("state", state);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        if (hostId != null) {
            sc.setParameters("hostId", hostId);
        }

        return _routerDao.search(sc, searchFilter);
    }

    @Override
    public List searchForConsoleProxy(Criteria c) {
        Filter searchFilter = new Filter(ConsoleProxyVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        		returnableVolumes.add(v);
        SearchCriteria sc = _consoleProxyDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _consoleProxyDao.createSearchCriteria();
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("group", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _consoleProxyDao.search(sc, searchFilter);
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Long vmInstanceId = cmd.getVirtualMachineId();
        Object name = cmd.getVolumeName();
        Object keyword = cmd.getKeyword();

        Object type = null;
        Object zone = null;
        Object pod = null;
        //Object host = null; TODO
        if (isAdmin) {
            type = cmd.getType();
            zone = cmd.getZoneId();
            pod = cmd.getPodId();
            // host = cmd.getHostId(); TODO
        } else {
            domainId = null;
        // hack for now, this should be done better but due to needing a join I opted to
        // do this quickly and worry about making it pretty later
        SearchBuilder sb = _volumeDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN);
        sb.and("volumeType", sb.entity().getVolumeType(), SearchCriteria.Op.LIKE);
        sb.and("instanceId", sb.entity().getInstanceId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);

        // Don't return DomR and ConsoleProxy volumes
        sb.and("domRNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domPNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);
        sb.and("domSNameLabel", sb.entity().getName(), SearchCriteria.Op.NLIKE);

        // Only return Volumes that are in the "Created" state
        sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ);

        // Only return volumes that are not destroyed
        sb.and("destroyed", sb.entity().getDestroyed(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        // now set the SC criteria...
        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _volumeDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("nameLabel", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("volumeType", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        if (type != null) {
            sc.setParameters("volumeType", "%" + type + "%");
        }
        if (vmInstanceId != null) {
            sc.setParameters("instanceId", vmInstanceId);
        }
        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }
        if (pod != null) {
            sc.setParameters("podId", pod);
        }
        
        // Don't return DomR and ConsoleProxy volumes
        /*
        sc.setParameters("domRNameLabel", "r-%");
        sc.setParameters("domPNameLabel", "v-%");
        sc.setParameters("domSNameLabel", "s-%");
		*/
        
        // Only return volumes that are not destroyed
        sc.setParameters("destroyed", false);

        List allVolumes = _volumeDao.search(sc, searchFilter);
        List returnableVolumes = new ArrayList(); //these are ones without domr and console proxy
        
        for(VolumeVO v:allVolumes)
        {
        	VMTemplateVO template = _templateDao.findById(v.getTemplateId());
        	if(template!=null && template.getUniqueName().equalsIgnoreCase("routing"))
        
        return returnableVolumes;
    }

    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         } else {
             return null;
         }
    }

    @Override
    public HostPodVO findHostPodById(long podId) {
        return _hostPodDao.findById(podId);
    }
    
    @Override
    public HostVO findSecondaryStorageHosT(long zoneId) {
    	return _storageMgr.getSecondaryStorageHost(zoneId);
    }

    @Override
    public List searchForIPAddresses(ListPublicIpAddressesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list IP addresses for domain " + domainId + ", permission denied.");
                }

                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Boolean isAllocated = cmd.isAllocatedOnly();
        if (isAllocated == null) {
            isAllocated = Boolean.TRUE;
        }

        Filter searchFilter = new Filter(IPAddressVO.class, "address", false, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object zone = cmd.getZoneId();
        Object address = cmd.getIpAddress();
        Object vlan = cmd.getVlanId();
        Object keyword = cmd.getKeyword();
        Object forVirtualNetwork  = cmd.isForVirtualNetwork();

        SearchBuilder sb = _publicIpAddressDao.createSearchBuilder();
        sb.and("accountIdEQ", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
        sb.and("address", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
        sb.and("vlanDbId", sb.entity().getVlanDbId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }
        
        if (forVirtualNetwork != null) {
        	SearchBuilder vlanSearch = _vlanDao.createSearchBuilder();
        	vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
        	sb.join("vlanSearch", vlanSearch, sb.entity().getVlanDbId(), vlanSearch.entity().getId(), JoinBuilder.JoinType.INNER);
        }

        if ((isAllocated != null) && (isAllocated == true)) {
        }

    @Override
        SearchCriteria sc = sb.create();
        if (accountId != null) {
            sc.setParameters("accountIdEQ", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }
        
        if (forVirtualNetwork != null) {
        	VlanType vlanType = (Boolean) forVirtualNetwork ? VlanType.VirtualNetwork : VlanType.DirectAttached;
        	sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
        }

        if (zone != null) {
            sc.setParameters("dataCenterId", zone);
        }

        if ((address == null) && (keyword != null)) {
            address = keyword;
        }

        if (address != null) {
            sc.setParameters("address", address + "%");
        }

        if (vlan != null) {
            sc.setParameters("vlanDbId", vlan);
        }

        return _publicIpAddressDao.search(sc, searchFilter);
    }

    @Override
    public List listAllActiveDiskTemplates() {
        return _diskTemplateDao.listAll();
    }
    public UserAccount authenticateUser(String username, String password, Long domainId, Map requestParameters) {
        UserAccount user = null;
        if (password != null) {
            user = getUserAccount(username, password, domainId);
        } else {
            String key = getConfigurationValue("security.singlesignon.key");
            if (key == null) {
                // the SSO key is gone, don't authenticate
                return null;
            }

            String singleSignOnTolerance = getConfigurationValue("security.singlesignon.tolerance.millis");
            if (singleSignOnTolerance == null) {
                // the SSO tolerance is gone (how much time before/after system time we'll allow the login request to be valid), don't authenticate
                return null;
            }

            long tolerance = Long.parseLong(singleSignOnTolerance);
            String signature = null;
            long timestamp = 0L;
            String unsignedRequest = null;

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List parameterNames = new ArrayList();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            try {
                for (String paramName : parameterNames) {
                    // parameters come as name/value pairs in the form String/String[]
                    String paramValue = ((String[])requestParameters.get(paramName))[0];

                    if ("signature".equalsIgnoreCase(paramName)) {
                        signature = paramValue;
                    } else {
                        if ("timestamp".equalsIgnoreCase(paramName)) {
                            String timestampStr = paramValue;
                            try {
                                // If the timestamp is in a valid range according to our tolerance, verify the request signature, otherwise return null to indicate authentication failure
                                timestamp = Long.parseLong(timestampStr);
                                long currentTime = System.currentTimeMillis();
                                if (Math.abs(currentTime - timestamp) > tolerance) {
                                    if (s_logger.isDebugEnabled()) {
                                        s_logger.debug("Expired timestamp passed in to login, current time = " + currentTime + ", timestamp = " + timestamp);
                                    }
                                    return null;
                                }
                            } catch (NumberFormatException nfe) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Invalid timestamp passed in to login: " + timestampStr);
                                }
                                return null;
                            }
                        }

                        if (unsignedRequest == null) {
                            unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        } else {
                            unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                        }
                    }
                }

                if ((signature == null) || (timestamp == 0L)) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Missing parameters in login request, signature = " + signature + ", timestamp = " + timestamp);
                    }
                    return null;
                }

                unsignedRequest = unsignedRequest.toLowerCase();

                Mac mac = Mac.getInstance("HmacSHA1");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                mac.init(keySpec);
            try {
                mac.update(unsignedRequest.getBytes());
                byte[] encryptedBytes = mac.doFinal();
                String computedSignature = new String(Base64.encodeBase64(encryptedBytes));
                boolean equalSig = signature.equals(computedSignature);
                if (!equalSig) {
                    s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
                } else {
                    user = getUserAccount(username, domainId);
                }
            } catch (Exception ex) {
                s_logger.error("Exception authenticating user", ex);
                return null;
            }
        }

        if (user != null) {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in");
            }
        	EventUtils.saveEvent(user.getId(), user.getAccountId(), EventTypes.EVENT_USER_LOGIN, "user has logged in");
            return user;
        } else {
        	if (s_logger.isDebugEnabled()) {
                s_logger.debug("User: " + username + " in domain " + domainId + " has failed to log in");
            }
            return null;
        }
    }

    @Override
    public void logoutUser(Long userId) {
        UserAccount userAcct = _userAccountDao.findById(userId);
        EventUtils.saveEvent(userId, userAcct.getAccountId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out");
    }

    @Override
    public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException {
        NetworkRuleConfigVO rule = null;
        try {
            Long securityGroupId = cmd.getPortForwardingServiceId();
            String port = cmd.getPublicPort();
            String privatePort = cmd.getPrivatePort();
            String protocol = cmd.getProtocol();
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = Long.valueOf(User.UID_SYSTEM);
            }

            SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId));
            if (sg == null) {
                throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist");
            }
            if (!NetUtils.isValidPort(port)) {
                throw new InvalidParameterValueException("port is an invalid value");
            }
            throw ex1;
            if (!NetUtils.isValidPort(privatePort)) {
                throw new InvalidParameterValueException("privatePort is an invalid value");
            }
            if (protocol != null) {
                if (!NetUtils.isValidProto(protocol)) {
                    throw new InvalidParameterValueException("Invalid protocol");
                }
            } else {
                protocol = "TCP";
            }

            // validate permissions
            Account account = (Account)UserContext.current().getAccountObject();
            if (account != null) {
                if (isAdmin(account.getType())) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) {
                        throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied.");
                    }
                } else if (account.getId() != sg.getAccountId()) {
                    throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule.");
                }
            }

            List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId);
            for (NetworkRuleConfigVO existingRule : existingRules) {
                if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) {
        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
                    throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol);
                }
            }

            NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol);
            netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating);
            rule = _networkRuleConfigDao.persist(netRule);
        } catch (Exception e) {
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                throw (InternalErrorException) e;
            } else {
                s_logger.error("Unhandled exception creating or updating network rule", e);
                throw new CloudRuntimeException("Unhandled exception creating network rule", e);
            }
        }
        return rule;
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
            if ((sgMappings != null) && !sgMappings.isEmpty()) {
                try {
                    for (SecurityGroupVMMapVO sgMapping : sgMappings) {
                        UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId());
                        createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId());
                    }
                } catch (NetworkRuleConflictException ex) {
                    netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted);
                    _networkRuleConfigDao.update(ruleId, netRule);
                    throw ex;
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }

    @Override
    public List listAllTemplates() {
        return _templateDao.listAllIncludingRemoved();
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("categoryId", sb.entity().getCategoryId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

        if (osCategoryId != null) {
            sc.setParameters("categoryId", osCategoryId);
        }

        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        SearchCriteria sc = sb.create();

        if (id != null) {
            sc.setParameters("id",id);
        }

    	return _guestOSCategoryDao.search(sc, searchFilter);
    }
    
    @Override
    public String getConfigurationValue(String name) {
    	return _configDao.getValue(name);
    }

    @Override
    public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) {
        return _consoleProxyMgr.assignProxy(dataCenterId, userVmId);
    }

    @Override
    public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException {
        return _consoleProxyMgr.startProxy(instanceId, startEventId);
    }

    @Override
    public boolean stopConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.stopProxy(instanceId, startEventId);
    }

    @Override
    public boolean rebootConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }


    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
        String accountName = cmd.getAccountName();
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
    @Override
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        _alertMgr.recalculateCapacity();

        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
        Long accountId = null;
                }
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
        
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);
    }

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }

                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
            }
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            //
        }
        */

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
        }
        /*
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

            _eventDao.persist(event);
                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }

            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    @Override
    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
    }
            } else {
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Long accountId = null;
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);

            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
        Object pod = c.getCriteria(Criteria.PODID);
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
        }
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {
        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }

		return null;
	}

	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method declaration
Method invocation
Method signature
Throw statement
Try statement
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }
=======
    public VolumeVO findVolumeById(long id) {
         VolumeVO volume = _volumeDao.findById(id);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) {
             return volume;
         }
         else {
             return null;
         }
    }
    
    @Override
    public VolumeVO findVolumeByInstanceAndDeviceId(long instanceId, long deviceId) 
    {
         VolumeVO volume = _volumeDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
         if (volume != null && !volume.getDestroyed() && volume.getRemoved() == null) 
         {
             return volume;
         }
         else 
         {
             return null;
         }
    }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
Solution content
    }

    @Override
    public List searchForVolumes(ListVolumesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        boolean isAdmin = false;
        if ((account == null) || isAdmin(account.getType())) {
            isAdmin = true;
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list volumes.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(VolumeVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
If statement
Method declaration
Method invocation
Method signature
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }
=======
    public long createOrUpdateRuleAsync(boolean isForwarding, long userId, long accountId, Long domainId, long securityGroupId, String address, String port,
            String privateIpAddress, String privatePort, String protocol, String algorithm) {

        CreateOrUpdateRuleParam param = new CreateOrUpdateRuleParam(isForwarding, userId, accountId, address, port, privateIpAddress, privatePort, protocol, algorithm, domainId,
                securityGroupId);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
    	job.setUserId(UserContext.current().getUserId());
    	job.setAccountId(accountId);
        job.setCmd("CreateOrUpdateRule");
        job.setCmdInfo(gson.toJson(param));
        job.setCmdOriginator(CreatePortForwardingServiceRuleCmd.getResultObjectName());
        
        return _asyncMgr.submitAsyncJob(job);
    }

    @Override
    public void deleteRule(long ruleId, long userId, long accountId) throws InvalidParameterValueException, PermissionDeniedException, InternalErrorException {
        Exception e = null;
        try {
            FirewallRuleVO rule = _firewallRulesDao.findById(ruleId);
            if (rule != null) {
                boolean success = false;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
Solution content
    }

    @Override
    public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException {
        NetworkRuleConfigVO netRule = null;
        if (ruleId != null) {
            Long userId = UserContext.current().getUserId();
            if (userId == null) {
                userId = User.UID_SYSTEM;
            }

            netRule = _networkRuleConfigDao.findById(ruleId);
            List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId());
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
If statement
Method declaration
Method invocation
Method signature
Try statement
Variable
Chunk
Conflicting content
<<<<<<< HEAD
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }
=======
    @Override
    public long deleteRuleAsync(long id, long userId, long accountId) {
        DeleteRuleParam param = new DeleteRuleParam(id, userId, accountId);
        Gson gson = GsonHelper.getBuilder().create();
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        return netRule;
    }
Solution content
                }
            }

            netRule.setCreateStatus(AsyncInstanceCreateStatus.Created);
            _networkRuleConfigDao.update(ruleId, netRule);
        }

        return netRule;
    }
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method invocation
Method signature
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();
=======
    public List listGuestOSByCriteria(Criteria c) 
    {
        
        Filter searchFilter = new Filter(GuestOSVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Long id = (Long) c.getCriteria(Criteria.ID);
        Long osCategoryId = (Long) c.getCriteria(Criteria.OSCATEGORYID);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
Solution content
    }

    @Override
    public List listGuestOSByCriteria(ListGuestOsCmd cmd) {
        Filter searchFilter = new Filter(GuestOSVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
        Long osCategoryId = cmd.getOsCategoryId();

        SearchBuilder sb = _guestOSDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Cast expression
Method invocation
Method signature
Variable
Chunk
Conflicting content
        return _guestOSDao.search(sc, searchFilter);
    }
<<<<<<< HEAD

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();
=======
    
    @Override
    public List listGuestOSCategoriesByCriteria(Criteria c) 
    {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Long id = (Long) c.getCriteria(Criteria.ID);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
Solution content
        return _guestOSDao.search(sc, searchFilter);
    }

    @Override
    public List listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd) {
        Filter searchFilter = new Filter(GuestOSCategoryVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long id = cmd.getId();

        SearchBuilder sb = _guestOSCategoryDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Method invocation
Method signature
Variable
Chunk
Conflicting content
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

<<<<<<< HEAD
=======
    @Override
    public boolean destroyConsoleProxy(long instanceId, long startEventId) {
        return _consoleProxyMgr.destroyProxy(instanceId, startEventId);
    }

    @Override
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public long startConsoleProxyAsync(long instanceId) {
        long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "starting console proxy with Id: "+instanceId);
        VMOperationParam param = new VMOperationParam(0, instanceId, null, eventId);
Solution content
        
            //
        return _consoleProxyMgr.rebootProxy(instanceId, startEventId);
    }

    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
            ConsoleProxyInfo proxy = getConsoleProxy(vm.getDataCenterId(), vmId);
            if (proxy != null)
                return proxy.getProxyImageUrl();
        }
        return null;
    }

    @Override
    public int getVncPort(VirtualMachine vm) {
        if (vm.getHostId() == null) {
        	s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port");
            return -1;
        }
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Trying to retrieve VNC port from agent about VM " + vm.getName());
        
        GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
        int port = answer == null ? -1 : answer.getPort();
        
        if(s_logger.isTraceEnabled())
        	s_logger.trace("Retrieved VNC port about VM " + vm.getName() + " is " + port);
        
        return port;
    }

    @Override
    public ConsoleProxyVO findConsoleProxyById(long instanceId) {
        return _consoleProxyDao.findById(instanceId);
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
    }
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);

        SearchCriteria sc = sb.create();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", "%" + domainName + "%");
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if ((domainName == null) && (level == null) && (domainId != null)) {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                sc.setParameters("path", domain.getPath() + "%");
            }
        }

        return _domainDao.search(sc, searchFilter);
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        return _domainDao.search(sc, searchFilter);
	}

    @Override
    public DomainVO createDomain(CreateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        String name = cmd.getDomainName();
        Long parentId = cmd.getParentDomainId();
        Long ownerId = UserContext.current().getAccountId();
        Account account = (Account)UserContext.current().getAccountObject();

        if (ownerId == null) {
            ownerId = Long.valueOf(1);
        }

        if (parentId == null) {
            parentId = Long.valueOf(DomainVO.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), parentId)) {
            throw new PermissionDeniedException("Unable to create domain " + name + ", permission denied.");
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            DomainVO domain = new DomainVO(name, ownerId, parentId);
            try {
                DomainVO dbDomain = _domainDao.create(domain);
                EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " created with owner id = " + ownerId
                        + " and parentId " + parentId);
                return dbDomain;
            } catch (IllegalArgumentException ex) {
            	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                        + " and parentId " + parentId);
                throw ex;
            }
        } else {
        _alertMgr.recalculateCapacity();
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_CREATE, "Domain, " + name + " was not created with owner id = " + ownerId
                    + " and parentId " + parentId);
        }
        return null;
    }

    @Override
    public String deleteDomain(DeleteDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getId();
        Boolean cleanup = cmd.getCleanup();

        if ((domainId == DomainVO.ROOT_DOMAIN) || ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId))) {
            throw new PermissionDeniedException("Unable to delete domain " + domainId + ", permission denied.");
        }

        try {
            DomainVO domain = _domainDao.findById(domainId);
            if (domain != null) {
                long ownerId = domain.getAccountId();
                if ((cleanup != null) && cleanup.booleanValue()) {
                    boolean success = cleanupDomain(domainId, ownerId);
                    if (!success) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Failed to clean up domain resources and sub domains, domain with id " + domainId + " was not deleted.");
                        return "Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domainId + ").";
                    }
                } else {
                    if (!_domainDao.remove(domainId)) {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
                        return "Delete failed on domain " + domain.getName() + " (id: " + domainId + "); please make sure all users and sub domains have been removed from the domain before deleting";
                    } else {
                    	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
                    }
                }
            } else {
                throw new InvalidParameterValueException("Failed to delete domain nable " + domainId + ", domain not found");
            }
            return "success";
        } catch (InvalidParameterValueException ex) {
            throw ex;
        } catch (Exception ex) {
            s_logger.error("Exception deleting domain with id " + domainId, ex);
            return "Delete failed on domain with id " + domainId + " due to an internal server error.";
        }
    }

    private boolean cleanupDomain(Long domainId, Long ownerId) {
        boolean success = true;
        {
            SearchCriteria sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);

            List domains = _domainDao.search(sc, null);

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
            }
        }

        {
            // delete users which will also delete accounts and release resources for those accounts
            SearchCriteria sc = _accountDao.createSearchCriteria();
            sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
            List accounts = _accountDao.search(sc, null);
            for (AccountVO account : accounts) {
                SearchCriteria userSc = _userDao.createSearchCriteria();
                userSc.addAnd("accountId", SearchCriteria.Op.EQ, account.getId());
                List users = _userDao.search(userSc, null);
                for (UserVO user : users) {
                    success = (success && deleteUserInternal(user.getId()));
                }
            }
        }

        // delete the domain itself
        boolean deleteDomainSuccess = _domainDao.remove(domainId);
        if (!deleteDomainSuccess) {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was not deleted");
        } else {
        	EventUtils.saveEvent(new Long(1), ownerId, EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_DELETE, "Domain with id " + domainId + " was deleted");
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }

    @Override
    public Long findDomainIdByAccountId(Long accountId) {
        if (accountId == null) {
            return null;
        }

        AccountVO account = _accountDao.findById(accountId);
        if (account != null) {
            return account.getDomainId();
        }

        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public List searchForAlerts(ListAlertsCmd cmd) {
        Filter searchFilter = new Filter(AlertVO.class, "lastSent", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _alertDao.createSearchCriteria();

        
        Object type = cmd.getType();
        Object keyword = cmd.getKeyword();

        if (keyword != null) {
            SearchCriteria ssc = _alertDao.createSearchCriteria();
            ssc.addOr("subject", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("subject", SearchCriteria.Op.SC, ssc);
        }

        if (type != null) {
            sc.addAnd("type", SearchCriteria.Op.EQ, type);
        }

        return _alertDao.search(sc, searchFilter);
    }

    @Override
    public List listCapacities(ListCapacityCmd cmd) {
        // make sure capacity is accurate before displaying it anywhere
        // NOTE: listCapacities is currently called by the UI only, so this
        // shouldn't be called much since it checks all hosts/VMs
        // to figure out what has been allocated.
        Filter searchFilter = new Filter(CapacityVO.class, "capacityType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _capacityDao.createSearchCriteria();

        Object type = cmd.getType();
        Object zoneId = cmd.getZoneId();
        Object podId = cmd.getPodId();
        Object hostId = cmd.getHostId();

        if (type != null) {
            sc.addAnd("capacityType", SearchCriteria.Op.EQ, type);
        }

        if (zoneId != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
        }

        if (podId != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, podId);
        }

        if (hostId != null) {
            sc.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
        }

        return _capacityDao.search(sc, searchFilter);
    }
    
    @Override
    public long getMemoryUsagebyHost(Long hostId) {
        long mem = 0;
        List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter);
        mem += vms.size() * _routerRamSize * 1024L * 1024L;
 
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.SecondaryStorageVm);
        mem += vms.size() * _ssRamSize * 1024L * 1024L;
        
        vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.ConsoleProxy);
        mem += vms.size() * _proxyRamSize * 1024L * 1024L;
        
        
        List instances = _userVmDao.listUpByHostId(hostId);
        for (UserVmVO vm : instances) {
            ServiceOffering so = findServiceOfferingById(vm.getServiceOfferingId());
            mem += so.getRamSize() * 1024L * 1024L;
        }
        return mem;
    }

    @Override
    public SnapshotVO createTemplateSnapshot(Long userId, long volumeId) {
        return _vmMgr.createTemplateSnapshot(userId, volumeId);
    }

    @Override
    public boolean destroyTemplateSnapshot(Long userId, long snapshotId) {
        return _vmMgr.destroyTemplateSnapshot(userId, snapshotId);
    }

    @Override
    public List listSnapshots(ListSnapshotsCmd cmd) throws InvalidParameterValueException {
        Long volumeId = cmd.getVolumeId();

        // Verify parameters
        if(volumeId != null){
            VolumeVO volume = _volumeDao.findById(volumeId);
            if (volume == null) {
                throw new InvalidParameterValueException("unable to find a volume with id " + volumeId);
            }
            checkAccountPermissions(volume.getAccountId(), volume.getDomainId(), "volume", volumeId);
        }

        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if(account != null && account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)
                accountId = account.getId();
            if (domainId != null && accountName != null) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                }
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SnapshotVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _snapshotDao.createSearchCriteria();

        Object name = cmd.getSnapshotName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();
        Object snapshotTypeStr = cmd.getSnapshotType();
        String interval = cmd.getIntervalType();

        sc.addAnd("status", SearchCriteria.Op.EQ, Snapshot.Status.BackedUp);

        if (volumeId != null) {
            sc.addAnd("volumeId", SearchCriteria.Op.EQ, volumeId);
        }
        
        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (keyword != null) {
            SearchCriteria ssc = _snapshotDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        }

        if (snapshotTypeStr != null) {
            SnapshotType snapshotType = SnapshotVO.getSnapshotType((String)snapshotTypeStr);
            if (snapshotType == null) {
                throw new InvalidParameterValueException("Unsupported snapshot type " + snapshotTypeStr);
            }
            sc.addAnd("snapshotType", SearchCriteria.Op.EQ, snapshotType.ordinal());
        } else {
            // Show only MANUAL and RECURRING snapshot types
            sc.addAnd("snapshotType", SearchCriteria.Op.NEQ, Snapshot.SnapshotType.TEMPLATE.ordinal());
        }

        if (interval != null && volumeId != null) {
            IntervalType intervalType =  DateUtil.IntervalType.getIntervalType(interval);
            if(intervalType == null) {
                throw new InvalidParameterValueException("Unsupported interval type " + intervalType);
            }
            SnapshotPolicyVO snapPolicy = _snapMgr.getPolicyForVolumeByInterval(volumeId, (short)intervalType.ordinal());
            if (snapPolicy == null) {
                s_logger.warn("Policy with interval "+ intervalType +" not assigned to volume: "+volumeId);
                return new ArrayList();
            }
            return _snapMgr.listSnapsforPolicy(snapPolicy.getId(), searchFilter);
        }
        
        return _snapshotDao.search(sc, searchFilter);
    }

    @Override
    public DiskOfferingVO findDiskOfferingById(long diskOfferingId) {
        return _diskOfferingDao.findById(diskOfferingId);

    @Override
    public List findPrivateDiskOffering() {
        return _diskOfferingDao.findPrivateDiskOffering();
    }
    
    protected boolean templateIsCorrectType(VMTemplateVO template) {
    	return true;
    }
    
	public static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}

    @Override
    @DB
    public boolean updateTemplatePermissions(UpdateTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException,
            PermissionDeniedException, InternalErrorException {
        Transaction txn = Transaction.currentTxn();
        
        //Input validation
        Long id = cmd.getId();
        Account account = (Account) UserContext.current().getAccountObject();
        List accountNames = cmd.getAccountNames();
        Long userId = UserContext.current().getUserId();
        Boolean isFeatured = cmd.isFeatured();
        Boolean isPublic = cmd.isPublic();
        String operation = cmd.getOperation();
        String mediaType = "";

        VMTemplateVO template = _templateDao.findById(id);
        if (template == null || !templateIsCorrectType(template)) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find " + mediaType + " with id " + id);
        }

        if(cmd instanceof UpdateTemplatePermissionsCmd)
        {
        	mediaType = "template";
        	if(template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid template");
        	}
        }
        if(cmd instanceof UpdateIsoPermissionsCmd)
        {
        	mediaType = "iso";
        	if(!template.getFormat().equals(ImageFormat.ISO))
        	{
        		throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Please provide a valid iso");
        	}
        }
        
        if (account != null) 
        {
            if (!isAdmin(account.getType()) && (template.getAccountId() != account.getId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
            } else if (account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
                Long templateOwnerDomainId = findDomainIdByAccountId(template.getAccountId());
                if (!isChildDomain(account.getDomainId(), templateOwnerDomainId)) {
                    throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to update permissions for " + mediaType + " with id " + id);
                }
            }
        }

        // If command is executed via 8096 port, set userId to the id of System account (1)
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }
        
        // If the template is removed throw an error.
        if (template.getRemoved() != null){
        	s_logger.error("unable to update permissions for " + mediaType + " with id " + id + " as it is removed  ");
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to update permissions for " + mediaType + " with id " + id + " as it is removed ");
        }
        
        if (id == Long.valueOf(1)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to update permissions for " + mediaType + " with id " + id);
        }
        
        boolean isAdmin = ((account == null) || isAdmin(account.getType()));
        boolean allowPublicUserTemplates = Boolean.parseBoolean(getConfigurationValue("allow.public.user.templates"));        
        if (!isAdmin && !allowPublicUserTemplates && isPublic != null && isPublic) {
        	throw new ServerApiException(BaseCmd.PARAM_ERROR, "Only private " + mediaType + "s can be created.");
        }

//        // package up the accountNames as a list
//        List accountNameList = new ArrayList();
        if (accountNames != null) 
        {
            if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) 
            {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." +
                        "  Given operation is: '" + operation + "'");
            }
//            StringTokenizer st = new StringTokenizer(accountNames, ",");
//            while (st.hasMoreTokens()) {
//                accountNameList.add(st.nextToken());
//            }
        }

        Long accountId = template.getAccountId();
        if (accountId == null) {
            // if there is no owner of the template then it's probably already a public template (or domain private template) so publishing to individual users is irrelevant
            throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
        }

        VMTemplateVO updatedTemplate = _templateDao.createForUpdate();
        
        if (isPublic != null) {
            updatedTemplate.setPublicTemplate(isPublic.booleanValue());
        }
        
        if (isFeatured != null) {
        }
        	updatedTemplate.setFeatured(isFeatured.booleanValue());
        }
        
        _templateDao.update(template.getId(), updatedTemplate);

        Long domainId = account.getDomainId();
        if ("add".equalsIgnoreCase(operation)) {
            txn.start();
            for (String accountName : accountNames) {
                Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (permittedAccount != null) {
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
                    txn.rollback();
                    throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + ", account not found.  "
                            + "No permissions updated, please verify the account names and retry.");
                }
            }
            txn.commit();
        } else if ("remove".equalsIgnoreCase(operation)) {
            try {
                List accountIds = new ArrayList();
                for (String accountName : accountNames) {
                    Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (permittedAccount != null) {
                        accountIds.add(permittedAccount.getId());
                    }
                }
                _launchPermissionDao.removePermissions(id, accountIds);
            } catch (CloudRuntimeException ex) {
                throw new InternalErrorException("Internal error removing launch permissions for template " + template.getName());
            }
        } else if ("reset".equalsIgnoreCase(operation)) {
            // do we care whether the owning account is an admin? if the
            // owner is an admin, will we still set public to false?
            updatedTemplate = _templateDao.createForUpdate();
            updatedTemplate.setPublicTemplate(false);
            updatedTemplate.setFeatured(false);
            _templateDao.update(template.getId(), updatedTemplate);
            _launchPermissionDao.removeAllPermissions(id);
        }
        return true;
    }

    @Override

        */
    public List listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String acctName = cmd.getAccountName();
        Long id = cmd.getId();
        Long accountId = null;

        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list " + cmd.getMediaType() + " permissions.");
                }
                if (acctName != null) {
                    Account userAccount = _accountDao.findActiveAccount(acctName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new PermissionDeniedException("Unable to find account " + acctName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        VMTemplateVO template = _templateDao.findById(id.longValue());
        if (template == null || !templateIsCorrectType(template)) {
            throw new InvalidParameterValueException("unable to find " + cmd.getMediaType() + " with id " + id);
        }

        if (accountId != null && !template.isPublicTemplate()) {
            if (account.getType() == Account.ACCOUNT_TYPE_NORMAL && template.getAccountId() != accountId) {
                throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
            } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
                DomainVO accountDomain = _domainDao.findById(account.getDomainId());
                Account templateAccount = _accountDao.findById(template.getAccountId());
                DomainVO templateDomain = _domainDao.findById(templateAccount.getDomainId());                    
                if (!templateDomain.getPath().contains(accountDomain.getPath())) {
                    throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
                }
            }                                    
        }

        if (id == Long.valueOf(1)) {
            throw new PermissionDeniedException("unable to list permissions for " + cmd.getMediaType() + " with id " + id);
        }

        List accountNames = new ArrayList();        
        List permissions = _launchPermissionDao.findByTemplate(id);
        if ((permissions != null) && !permissions.isEmpty()) {
            for (LaunchPermissionVO permission : permissions) {
                Account acct = _accountDao.findById(permission.getAccountId());
                accountNames.add(acct.getAccountName());
            }
        }
        return accountNames;
    }

    @Override
    public List searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
        Filter searchFilter = new Filter(DiskOfferingVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _diskOfferingDao.createSearchBuilder();

        // SearchBuilder and SearchCriteria are now flexible so that the search builder can be built with all possible
        // search terms and only those with criteria can be set.  The proper SQL should be generated as a result.
        Object name = cmd.getDiskOfferingName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        sb.addAnd("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ);
        if (domainId != null) {
            SearchBuilder domainSearch = _domainDao.createSearchBuilder();
            domainSearch.addAnd("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId());
        }
        */

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _diskOfferingDao.createSearchCriteria();
            ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        // FIXME:  disk offerings should search back up the hierarchy for available disk offerings...
        /*
        if (domainId != null) {
            sc.setParameters("domainId", domainId);
            //
            //DomainVO domain = _domainDao.findById((Long)domainId);
            //
            // I want to join on user_vm.domain_id = domain.id where domain.path like 'foo%'
            //sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");

        return _diskOfferingDao.search(sc, searchFilter);
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(long jobId) throws PermissionDeniedException {
        AsyncJobVO job = _asyncMgr.getAsyncJob(jobId);
        if (job == null) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("queryAsyncJobResult error: Permission denied, invalid job id " + jobId);

            throw new PermissionDeniedException("Permission denied, invalid job id " + jobId);
        }

        // treat any requests from API server as trusted requests
        if (!UserContext.current().isApiServer() && job.getAccountId() != UserContext.current().getAccountId()) {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Mismatched account id in job and user context, perform further securty check. job id: "
                	+ jobId + ", job owner account: " + job.getAccountId() + ", accound id in current context: " + UserContext.current().getAccountId());
        	
        	Account account = _accountDao.findById(UserContext.current().getAccountId());
        	if(account == null || account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
	            if (s_logger.isDebugEnabled()) {
	            	if(account == null)
		                s_logger.debug("queryAsyncJobResult error: Permission denied, account no long exist for account id in context, job id: " + jobId
		                	+ ", accountId  " + UserContext.current().getAccountId());
	            	else
	            		s_logger.debug("queryAsyncJobResult error: Permission denied, invalid ownership for job " + jobId + ", job account owner: "
	            			+ job.getAccountId() + ", account id in context: " + UserContext.current().getAccountId());
	            }
	
	            throw new PermissionDeniedException("Permission denied, invalid job ownership, job id: " + jobId);
        	}
        }
        return _asyncMgr.queryAsyncJobResult(jobId);
    }

    @Override
    public AsyncJobVO findAsyncJobById(long jobId) {
        return _asyncMgr.getAsyncJob(jobId);
    }

    @Override
    public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String portForwardingServiceName = cmd.getPortForwardingServiceName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((accountName != null) && (domainId != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the security group
                    if (account != null) {
                        accountId = account.getId();
                        domainId = account.getDomainId();
                    }
                }
            } else {
                accountId = account.getId();
                domainId = account.getDomainId();
            }
        }

        if (accountId == null) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified.");
        }

        if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) {
            throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits.");
        }

        SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId);
        return _securityGroupDao.persist(group);
    }

    @Override
    public boolean deleteSecurityGroup(DeletePortForwardingServiceCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
    	Long securityGroupId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	Account account = (Account)UserContext.current().getAccountObject();
    	
        //Verify input parameters
        if (userId == null) {
            userId = Long.valueOf(User.UID_SYSTEM);
        }

        //verify parameters
        SecurityGroupVO securityGroup = _securityGroupDao.findById(Long.valueOf(securityGroupId));
        if (securityGroup == null) {
        	throw new InvalidParameterValueException("unable to find port forwarding service with id " + securityGroupId);
        }

        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != securityGroup.getAccountId()) {
                    throw new PermissionDeniedException("unable to find port forwarding service with id " + securityGroupId + " for this account, permission denied");
                }
            } else if (!isChildDomain(account.getDomainId(), securityGroup.getDomainId())) {
                throw new PermissionDeniedException("Unable to delete port forwarding service " + securityGroupId + ", permission denied.");
            }
        }
        
        long startEventId = EventUtils.saveScheduledEvent(userId, securityGroup.getAccountId(), EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE, "deleting port forwarding service with Id: " + securityGroupId);
        
        final EventVO event = new EventVO();
        event.setUserId(userId);
        event.setAccountId(securityGroup.getAccountId());
        event.setType(EventTypes.EVENT_PORT_FORWARDING_SERVICE_DELETE);
        event.setStartId(startEventId);
        try {
            List sgVmMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId);
            if (sgVmMappings != null) {
                for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                    removeSecurityGroup(userId, sgVmMapping.getSecurityGroupId(), sgVmMapping.getIpAddress(), sgVmMapping.getInstanceId(), startEventId);
                }
            }
    @Override
            _networkRuleConfigDao.deleteBySecurityGroup(securityGroupId);

        } catch (InvalidParameterValueException ex1) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex1);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("Failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex1;
        } catch (PermissionDeniedException ex2) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Invalid parameter value exception deleting port forwarding service " + securityGroup.getName() + " (id: " + securityGroup.getId() + "), " + ex2);
            }
            event.setLevel(EventVO.LEVEL_ERROR);
            event.setDescription("failed to delete port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
            _eventDao.persist(event);
            throw ex2;
        }

        boolean success = _securityGroupDao.remove(Long.valueOf(securityGroupId));

        event.setLevel(EventVO.LEVEL_INFO);
        event.setDescription("Deleting port forwarding service - " + securityGroup.getName() + " (id: " + securityGroup.getId() + ")");
        _eventDao.persist(event);

        return success;
    }

    public List searchForSecurityGroups(ListPortForwardingServicesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // if an admin account was passed in, or no account was passed in, make sure we honor the accountName/domainId parameters
        Account account = (Account)UserContext.current().getAccountObject();
        Long accountId = null;
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list port forwarding services.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(SecurityGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object name = cmd.getPortForwardingServiceName();
        Object id = cmd.getId();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _securityGroupDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _securityGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, name + "%");
        }

        if (id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        return _securityGroupDao.search(sc, searchFilter);
    }

    @Override
    public Map> searchForSecurityGroupsByVM(ListPortForwardingServicesByVmCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list port forwarding services for domain " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            }
        } else {
            accountId = account.getId();
        }

        Object ipAddress = cmd.getIpAddress();
        Long instanceId = cmd.getVirtualMachineId();
        UserVm userVm = _userVmDao.findById(instanceId);
        if (userVm == null) {
            throw new InvalidParameterValueException("Internal error, unable to find virtual machine " + instanceId + " for listing port forwarding services.");
        }

        if ((accountId != null) && (userVm.getAccountId() != accountId.longValue())) {
            throw new PermissionDeniedException("Unable to list port forwarding services, account " + accountId + " does not own virtual machine " + instanceId);
        }

        Filter searchFilter = new Filter(SecurityGroupVMMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _securityGroupVMMapDao.createSearchCriteria();

        // TODO: keyword search on vm name?  vm group?  what makes sense here?  We can't search directly on 'name' as that's not a field of SecurityGroupVMMapVO.
        //Object keyword = cmd.getKeyword();

        /*
        if (keyword != null) {
            SearchCriteria ssc = _securityGroupVMMapDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        String accountName = cmd.getAccountName();
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        Long domainId = cmd.getDomainId();
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
        }

        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        if (loadBalancer == null) {
            return null;
        }

        if (account != null) {
            long lbAcctId = loadBalancer.getAccountId();
            if (isAdmin(account.getType())) {
                Account userAccount = _accountDao.findById(lbAcctId);
                if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) {
                    throw new PermissionDeniedException("Invalid load balancer rule id (" + loadBalancerId + ") given, unable to list load balancer instances.");
                }
            } else if (account.getId() != lbAcctId) {
                throw new PermissionDeniedException("Unable to list load balancer instances, account " + account.getAccountName() + " does not own load balancer rule " + loadBalancer.getName());
            }
        }

        List loadBalancerInstances = new ArrayList();
        List vmLoadBalancerMappings = null;
        if (applied) {
            // List only the instances that have actually been applied to the load balancer (pending is false).
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
        } else {
            // List all instances applied, even pending ones that are currently being assigned, so that the semantics
            // of "what instances can I apply to this load balancer" are maintained.
            vmLoadBalancerMappings = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
        }
        List appliedInstanceIdList = new ArrayList();
        if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) {
            for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) {
                appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId());
        Long accountId = null;
                    lock.unlock();
            }
        }

        IPAddressVO addr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        List userVms = _userVmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId());

        for (UserVmVO userVm : userVms) {
            // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it
            switch (userVm.getState()) {
            case Destroyed:
            case Expunging:
            case Error:
            case Unknown:
                continue;
            }

            boolean isApplied = appliedInstanceIdList.contains(userVm.getId());
            if (!applied && !isApplied) {
                loadBalancerInstances.add(userVm);
            } else if (applied && isApplied) {
                loadBalancerInstances.add(userVm);
            }
        }

        return loadBalancerInstances;
    }

    @Override
    public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        // do some parameter validation
        Account account = (Account)UserContext.current().getAccountObject();
        Account ipAddressOwner = null;
        String ipAddress = cmd.getPublicIp();

        if (ipAddress != null) {
            IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
            if (ipAddressVO == null) {
                throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " not found.");
            } else {
                Long ipAddrAcctId = ipAddressVO.getAccountId();
                if (ipAddrAcctId == null) {
                    throw new InvalidParameterValueException("Unable to list load balancers, IP address " + ipAddress + " is not associated with an account.");
                }
                ipAddressOwner = _accountDao.findById(ipAddrAcctId);
            }
        }

        if ((account == null) || isAdmin(account.getType())) {
            // validate domainId before proceeding
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list load balancers for domain id " + domainId + ", permission denied.");
                }
                if (accountName != null) {
                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
                    }
                }
            } else if (ipAddressOwner != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
                    throw new PermissionDeniedException("Unable to list load balancer rules for IP address " + ipAddress + ", permission denied.");
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountId = account.getId();
        }

        Filter searchFilter = new Filter(LoadBalancerVO.class, "ipAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getLoadBalancerRuleName();
        Object keyword = cmd.getKeyword();
        Object instanceId = cmd.getVirtualMachineId();

        SearchBuilder sb = _loadBalancerDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("nameEQ", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
        sb.and("ipAddress", sb.entity().getIpAddress(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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);
        }

        if (instanceId != null) {
            SearchBuilder lbVMSearch = _loadBalancerVMMapDao.createSearchBuilder();
            lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
            sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER);
        }

        SearchCriteria sc = sb.create();
        if (keyword != null) {
            SearchCriteria ssc = _loadBalancerDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.setParameters("nameEQ", name);
        }

        if (id != null) {
            sc.setParameters("id", id);
        }

        if (ipAddress != null) {
            sc.setParameters("ipAddress", ipAddress);
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (instanceId != null) {
            sc.setJoinParameters("lbVMSearch", "instanceId", instanceId);
        }

        return _loadBalancerDao.search(sc, searchFilter);
    }

    @Override
    public String[] getApiConfig() {
        return new String[] { "commands.properties" };
    }

    protected class AccountCleanupTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("AccountCleanup");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }

                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }

                Transaction txn = null;
                try {
                	txn = Transaction.open(Transaction.CLOUD_DB);
                	
                    List accounts = _accountDao.findCleanups();
                    s_logger.info("Found " + accounts.size() + " accounts to cleanup");
                    for (AccountVO account : accounts) {
                        s_logger.debug("Cleaning up " + account.getId());
                        try {
                            deleteAccount(account);
                        } catch (Exception e) {
                            s_logger.error("Skipping due to error on account " + account.getId(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                	if(txn != null)
                		txn.close();
                	
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }
    
    protected class EventPurgeTask implements Runnable {
        @Override
        public void run() {
            try {
                GlobalLock lock = GlobalLock.getInternLock("EventPurge");
                if (lock == null) {
                    s_logger.debug("Couldn't get the global lock");
                    return;
                }
                if (!lock.lock(30)) {
                    s_logger.debug("Couldn't lock the db");
                    return;
                }
                try {
                    final Calendar purgeCal = Calendar.getInstance();
                    purgeCal.add(Calendar.DAY_OF_YEAR, -_purgeDelay);
                    Date purgeTime = purgeCal.getTime();
                    s_logger.debug("Deleting events older than: "+purgeTime.toString());
                    List oldEvents = _eventDao.listOlderEvents(purgeTime);
                    s_logger.debug("Found "+oldEvents.size()+" events to be purged");
                    for (EventVO event : oldEvents){
                        _eventDao.expunge(event.getId());
                    }
                } catch (Exception e) {
                    s_logger.error("Exception ", e);
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                s_logger.error("Exception ", e);
            }
        }
    }

    @Override
    public StoragePoolVO findPoolById(Long id) {
        return _poolDao.findById(id);
    }

    @Override
    public List listClusterByPodId(long podId) {
        return _clusterDao.listByPodId(podId);
    }

    @Override
    public List searchForStoragePools(ListStoragePoolsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.CLUSTERID, cmd.getClusterId());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        return searchForStoragePools(c);
    }

    @Override
    public List searchForStoragePools(Criteria c) {
        Filter searchFilter = new Filter(StoragePoolVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _poolDao.createSearchCriteria();

        Object name = c.getCriteria(Criteria.NAME);
        Object host = c.getCriteria(Criteria.HOST);
        Object path = c.getCriteria(Criteria.PATH);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object cluster = c.getCriteria(Criteria.CLUSTERID);
        Object address = c.getCriteria(Criteria.ADDRESS);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _poolDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("type", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (host != null) {
            sc.addAnd("host", SearchCriteria.Op.EQ, host);
        }
        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.EQ, path);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
        	sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (address != null) {
        	sc.addAnd("hostAddress", SearchCriteria.Op.EQ, address);
        }
        if (cluster != null) {
        	sc.addAnd("clusterId", SearchCriteria.Op.EQ, cluster);
        }

        return _poolDao.search(sc, searchFilter);
    }

    @Override
    public List searchForStoragePoolsAndHosts(ListStoragePoolsAndHostsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());
        c.addCriteria(Criteria.NAME, cmd.getStoragePoolName());
        c.addCriteria(Criteria.ADDRESS, cmd.getIpAddress());
        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.PATH, cmd.getPath());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());

        List poolsAndHosts = new ArrayList();
        List pools = searchForStoragePools(c);
        if ((pools != null) && !pools.isEmpty()) {
            poolsAndHosts.addAll(pools);
        }

        if ((cmd.getPath() == null) && (cmd.getIpAddress() == null)) {
            List hosts = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), cmd.getStoragePoolName(), Host.Type.Storage.toString(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, null, cmd.getKeyword());
            if ((hosts != null) && !hosts.isEmpty()) {
                poolsAndHosts.addAll(hosts);
            }
        }

        return poolsAndHosts;
    }

    @Override
    public List searchForStoragePoolDetails(long poolId, String value)
    {
    	return _poolDao.searchForStoragePoolDetails(poolId, value);
    }
    
    @Override
    public List searchForAsyncJobs(ListAsyncJobsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Filter searchFilter = new Filter(AsyncJobVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchBuilder sb = _jobDao.createSearchBuilder();

        Object accountId = null;
        Long domainId = cmd.getDomainId();
        Account account = (Account)UserContext.current().getAccountObject();
        if ((account == null) || isAdmin(account.getType())) {
            String accountName = cmd.getAccountName();

            if ((accountName != null) && (domainId != null)) {
                Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                if (userAccount != null) {
                    accountId = userAccount.getId();
                } else {
                    throw new InvalidParameterValueException("Failed to list async jobs for account " + accountName + " in domain " + domainId + "; account not found.");
                }
            } else if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Failed to list async jobs for domain " + domainId + "; permission denied.");
                }                    

                // we can do a domain match for the admin case
                SearchBuilder domainSearch = _domainDao.createSearchBuilder();
                domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);

                SearchBuilder accountSearch = _accountDao.createSearchBuilder();
                accountSearch.join("domainSearch", domainSearch, accountSearch.entity().getDomainId(), domainSearch.entity().getId(), JoinType.INNER);

                sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinType.INNER);
            }
        } else {
            accountId = account.getId();
        }

        Object keyword = cmd.getKeyword();
        Object startDate = cmd.getStartDate();


        SearchCriteria sc = _jobDao.createSearchCriteria();
        if (keyword != null) {
            sc.addAnd("cmd", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }

        if (accountId != null) {
            sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById(domainId);
            sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
        }

        if (startDate != null) {
            sc.addAnd("created", SearchCriteria.Op.GTEQ, startDate);
        }

        return _jobDao.search(sc, searchFilter);
    }

    @Override
    public SnapshotPolicyVO findSnapshotPolicyById(Long policyId) {
        return _snapshotPolicyDao.findById(policyId);
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    public SecondaryStorageVmVO startSecondaryStorageVm(long instanceId, long startEventId) throws InternalErrorException {

        return _secStorageVmMgr.startSecStorageVm(instanceId, startEventId);
    }

    public boolean stopSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.stopSecStorageVm(instanceId, startEventId);
    }

    public boolean rebootSecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.rebootSecStorageVm(instanceId, startEventId);
    }

    public boolean destroySecondaryStorageVm(long instanceId, long startEventId) {
        return _secStorageVmMgr.destroySecStorageVm(instanceId, startEventId);
    }

	@Override
    public List searchForSecondaryStorageVm(Criteria c) {
        Filter searchFilter = new Filter(SecondaryStorageVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        SearchCriteria sc = _secStorageVmDao.createSearchCriteria();

        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object state = c.getCriteria(Criteria.STATE);
        Object zone = c.getCriteria(Criteria.DATACENTERID);
        Object pod = c.getCriteria(Criteria.PODID);
        Object hostId = c.getCriteria(Criteria.HOSTID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        if (keyword != null) {
            SearchCriteria ssc = _secStorageVmDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("instanceName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            ssc.addOr("state", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        
        if(id != null) {
            sc.addAnd("id", SearchCriteria.Op.EQ, id);
        }

        if (name != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
        }
        if (state != null) {
            sc.addAnd("state", SearchCriteria.Op.EQ, state);
        }
        if (zone != null) {
            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zone);
        }
        if (pod != null) {
            sc.addAnd("podId", SearchCriteria.Op.EQ, pod);
        }
        if (hostId != null) {
            sc.addAnd("hostId", SearchCriteria.Op.EQ, hostId);
        }
		return null;

        return _secStorageVmDao.search(sc, searchFilter);
    }

	@Override @SuppressWarnings({"unchecked", "rawtypes"})
	public List searchForSystemVm(ListSystemVMsCmd cmd) {
        Criteria c = new Criteria("id", Boolean.TRUE, cmd.getStartIndex(), cmd.getPageSizeVal());

        c.addCriteria(Criteria.KEYWORD, cmd.getKeyword());
        c.addCriteria(Criteria.ID, cmd.getId());
        c.addCriteria(Criteria.DATACENTERID, cmd.getZoneId());
        c.addCriteria(Criteria.PODID, cmd.getPodId());
        c.addCriteria(Criteria.HOSTID, cmd.getHostId());
        c.addCriteria(Criteria.NAME, cmd.getSystemVmName());
        c.addCriteria(Criteria.STATE, cmd.getState());

        String type = cmd.getSystemVmType();
        List systemVMs = new ArrayList();

        if (type == null) { //search for all vm types
            systemVMs.addAll(searchForConsoleProxy(c));
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("secondarystoragevm"))) { // search for ssvm
            systemVMs.addAll(searchForSecondaryStorageVm(c));
        } else if((type != null) && (type.equalsIgnoreCase("consoleproxy"))) { // search for consoleproxy
            systemVMs.addAll(searchForConsoleProxy(c));
        }

        return (List)systemVMs;
	}

	@Override
	public VMInstanceVO findSystemVMById(long instanceId) {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
		if(systemVm == null)
			return null;
		
		if(systemVm.getType() == VirtualMachine.Type.ConsoleProxy)
			return _consoleProxyDao.findById(instanceId);
		return _secStorageVmDao.findById(instanceId);
	}

	@Override
	public VMInstanceVO startSystemVM(StartSystemVMCmd cmd) throws InternalErrorException {
		
		//verify input
		Long id = cmd.getId();

		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: "+id);
			return startConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_START, "Starting secondary storage Vm Id: "+id);
			return startSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean stopSystemVM(StopSystemVmCmd cmd) {
		Long id = cmd.getId();
		
	    // verify parameters      
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
        if (systemVm == null) {
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + id);
        }
        
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+id);
			return stopConsoleProxy(id, eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_STOP, "stopping secondary storage Vm Id: "+id);
			return stopSecondaryStorageVm(id, eventId);
		}
	}

	@Override
	public boolean rebootSystemVM(RebootSystemVmCmd cmd)  {
		VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
	
		if (systemVm == null) {
	}
        	throw new ServerApiException (BaseCmd.PARAM_ERROR, "unable to find a system vm with id " + cmd.getId());
        }
		
		if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)){
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: "+cmd.getId());
			return rebootConsoleProxy(cmd.getId(), eventId);
		} else {
			long eventId = EventUtils.saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_REBOOT, "Rebooting secondary storage vm with Id: "+cmd.getId());
			return rebootSecondaryStorageVm(cmd.getId(), eventId);
		}
	}

	private String signRequest(String request, String key) {
		try
		{
			s_logger.info("Request: "+request);
			s_logger.info("Key: "+key);
			
			if(key != null && request != null)
			{
				Mac mac = Mac.getInstance("HmacSHA1");
				SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),
						"HmacSHA1");
				mac.init(keySpec);
				mac.update(request.getBytes());
				byte[] encryptedBytes = mac.doFinal();
				return new String ((Base64.encodeBase64(encryptedBytes)));
			}
		} catch (Exception ex) {
			s_logger.error("unable to sign request", ex);
		}
		return null;
	}
    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
        if ((user == null) || (user.getRemoved() != null))
        	throw new InvalidParameterValueException("Unable to find active user by id " + userId);

    	String cloudIdentifier = _configDao.getValue("cloud.identifier");
    	if (cloudIdentifier == null) {
    	    cloudIdentifier = "";
    	}

    	String signature = "";
    	try {
        	//get the user obj to get his secret key
        	user = getUser(userId);
        	String secretKey = user.getSecretKey();
        	String input = cloudIdentifier;
    		signature = signRequest(input, secretKey);
    	} catch (Exception e) {
			s_logger.warn("Exception whilst creating a signature:"+e);
		}
    	
    	ArrayList cloudParams = new ArrayList();
    	cloudParams.add(cloudIdentifier);
    	cloudParams.add(signature);

        return cloudParams;
    }

	@Override
	public NetworkGroupVO findNetworkGroupByName(Long accountId, String groupName) {
		NetworkGroupVO groupVO = _networkSecurityGroupDao.findByAccountAndName(accountId, groupName);
		return groupVO;
	}

    @Override
    public NetworkGroupVO findNetworkGroupById(long networkGroupId) {
        NetworkGroupVO groupVO = _networkSecurityGroupDao.findById(networkGroupId);
        return groupVO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHypervisorSnapshotCapable() {
        return _isHypervisorSnapshotCapable;
    }
    
    @Override
    public List listPendingEvents(int entryTime, int duration) {
        Calendar calMin = Calendar.getInstance();
        Calendar calMax = Calendar.getInstance();
        calMin.add(Calendar.SECOND, -entryTime);
        calMax.add(Calendar.SECOND, -duration);
        Date minTime = calMin.getTime();
        Date maxTime = calMax.getTime();
        List startedEvents = _eventDao.listStartedEvents(minTime, maxTime);
        List pendingEvents = new ArrayList();
        for (EventVO event : startedEvents){
        }
            EventVO completedEvent = _eventDao.findCompletedEvent(event.getId());
            if(completedEvent == null){
                pendingEvents.add(event);
            }
        }
        return pendingEvents;
    }

	@Override
	public List getPreAllocatedLuns(ListPreallocatedLunsCmd cmd)	{
       Filter searchFilter = new Filter(PreallocatedLunVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        SearchCriteria sc = _lunDao.createSearchCriteria();

        Object targetIqn = cmd.getTargetIqn();
        Object scope = cmd.getScope();

        if (targetIqn != null) {
            sc.addAnd("targetIqn", SearchCriteria.Op.EQ, targetIqn);
        }
        
        if (scope == null || scope.toString().equalsIgnoreCase("ALL")) {
            return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("ALLOCATED")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NNULL);
        	sc.addAnd("taken", SearchCriteria.Op.NNULL);
        	
        	return _lunDao.search(sc, searchFilter);
        } else if(scope.toString().equalsIgnoreCase("FREE")) {
        	sc.addAnd("volumeId", SearchCriteria.Op.NULL);
        	sc.addAnd("taken", SearchCriteria.Op.NULL);
        	
        	return _lunDao.search(sc, searchFilter);
        }


	@Override
	public boolean checkLocalStorageConfigVal()
	{
		String value = _configs.get("use.local.storage");
		
		if(value!=null && value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
        if (account.getId() == Account.ACCOUNT_ID_SYSTEM) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "can not lock system account");
        }

        return lockAccountInternal(account.getId());
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
        Account account = _accountDao.findById(user.getAccountId());
        if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "user id : " + userId + " is a system account, delete is not allowed");
        }
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
        
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        if (_dcDao.findById(zoneId) == null) {
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }

                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (!isAdmin(account.getType())) {
                if (account.getId() != targetAccountId) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find a " + targetDesc + " with id " + targetId + " for this account");
                }
            } else if (!_domainDao.isChildDomain(account.getDomainId(), targetDomainId)) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to perform operation for " + targetDesc + " with id " + targetId + ", permission denied.");
            }
            accountId = account.getId();
        }
    
        return accountId;
    }
}
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
        return _asyncMgr.submitAsyncJob(job, true);
    }

<<<<<<< HEAD
=======
    @Override
    public long destroyConsoleProxyAsync(long instanceId) {
        long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_DESTROY, "destroying console proxy with Id: "+instanceId);
        VMOperationParam param = new VMOperationParam(0, instanceId, null, eventId);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
        job.setUserId(UserContext.current().getUserId());
        job.setAccountId(Account.ACCOUNT_ID_SYSTEM);
        job.setCmd("DestroyConsoleProxy");
        job.setCmdInfo(gson.toJson(param));
        
        return _asyncMgr.submitAsyncJob(job);
    }

    @Override
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
Solution content
    @Override
    public String getConsoleAccessUrlRoot(long vmId) {
        VMInstanceVO vm = this.findVMInstanceById(vmId);
        if (vm != null) {
File
ManagementServerImpl.java
Developer's decision
Combination
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    @Override
<<<<<<< HEAD
    }

    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();
=======
    public List searchForDomains(Criteria c) {
        Filter searchFilter = new Filter(DomainVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Long domainId = (Long) c.getCriteria(Criteria.ID);
        String domainName = (String) c.getCriteria(Criteria.NAME);
        Integer level = (Integer) c.getCriteria(Criteria.LEVEL);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
Solution content
    }

    @Override
    public List searchForDomains(ListDomainsCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _domainDao.createSearchBuilder();
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Cast expression
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }
=======
    public List searchForDomainChildren(Criteria c) {
        Filter searchFilter = new Filter(DomainVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
        Long domainId = (Long) c.getCriteria(Criteria.ID);
        String domainName = (String) c.getCriteria(Criteria.NAME);
        Object keyword = c.getCriteria(Criteria.KEYWORD);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        SearchCriteria sc = _domainDao.createSearchCriteria();
Solution content
    }

    @Override
    public List searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Object keyword = cmd.getKeyword();

        Account account = (Account)UserContext.current().getAccountObject();
        if (account != null) {
            if (domainId != null) {
                if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to list domains children for domain id " + domainId + ", permission denied.");
                }
            } else {
                domainId = account.getDomainId();
            }
        }

        SearchCriteria sc = _domainDao.createSearchCriteria();
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Cast expression
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
        return success && deleteDomainSuccess;
    }

<<<<<<< HEAD
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
=======
    @Override
    public void updateDomain(Long domainId, String domainName) {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
Solution content
        return success && deleteDomainSuccess;
    }

    @Override
    public boolean updateDomain(UpdateDomainCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{
    	Long domainId = cmd.getId();
    	String domainName = cmd.getName();
    	
        //check if domain exists in the system
    	DomainVO domain = _domainDao.findById(domainId);
    	if (domain == null) {
    		throw new InvalidParameterValueException("Unable to find domain " + domainId);
    	} else if (domain.getParent() == null) {
            //check if domain is ROOT domain - and deny to edit it
    		throw new InvalidParameterValueException("ROOT domain can not be edited");
    	}

    	// check permissions
    	Account account = (Account)UserContext.current().getAccountObject();
    	if ((account != null) && !isChildDomain(account.getDomainId(), domain.getId())) {
            throw new PermissionDeniedException("Unable to update domain " + domainId + ", permission denied");
    	}

    	if (domainName == null) {
    		domainName = domain.getName();
    	}
    	
        SearchCriteria sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
        List domains = _domainDao.search(sc, null);
File
ManagementServerImpl.java
Developer's decision
Combination
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
        List domains = _domainDao.search(sc, null);
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
<<<<<<< HEAD
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getOwner(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getOwner(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
=======
            DomainVO domain = _domainDao.findById(domainId);
            saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
        } else {
            DomainVO domain = _domainDao.findById(domainId);
            saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }
    }
Solution content
        if ((domains == null) || domains.isEmpty()) {
            _domainDao.update(domainId, domainName);
        List domains = _domainDao.search(sc, null);
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_DOMAIN_UPDATE, "Domain, " + domainName + " was updated");
            return true;
        } else {
            domain = _domainDao.findById(domainId);
            EventUtils.saveEvent(new Long(1), domain.getAccountId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_DOMAIN_UPDATE, "Failed to update domain " + domain.getName() + " with name " + domainName + ", name in use.");
            return false;
        }
    }
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Method invocation
Return statement
Variable
Chunk
Conflicting content
        return null;
    }

<<<<<<< HEAD
=======
    @Override
    public DomainVO findDomainIdById(Long domainId) {
        return _domainDao.findById(domainId);
    }

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
Solution content
        return null;
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
<<<<<<< HEAD
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId().longValue());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId().longValue());
=======
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(templateId, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(templateId, permittedAccount.getId());
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
Solution content
                    if (permittedAccount.getId() == account.getId()) {
                        continue; // don't grant permission to the template owner, they implicitly have permission
                    }
                    LaunchPermissionVO existingPermission = _launchPermissionDao.findByTemplateAndAccount(id, permittedAccount.getId());
                    if (existingPermission == null) {
                        LaunchPermissionVO launchPermission = new LaunchPermissionVO(id, permittedAccount.getId());
                        _launchPermissionDao.persist(launchPermission);
                    }
                } else {
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
If statement
Method invocation
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
=======
    public DiskOfferingVO createDiskOffering(long userId, long domainId, String name, String description, int numGibibytes, String tags) throws InvalidParameterValueException, InternalErrorException {
    	
    	if(numGibibytes!=0 && numGibibytes<1){
    		throw new InvalidParameterValueException("The minimum disk offering size is 1 GB");
    	}
    		
    	if (numGibibytes > _maxVolumeSizeInGb) {
        	throw new InvalidParameterValueException("The maximum allowed size for a disk is " + _maxVolumeSizeInGb + " Gb.");
        }
   
        return _configMgr.createDiskOffering(userId, domainId, name, description, numGibibytes, tags);
    }

    @Override
    public DiskOfferingVO updateDiskOffering(long userId, long diskOfferingId, String name, String description, String tags) {
    	return _configMgr.updateDiskOffering(userId, diskOfferingId, name, description, tags);
    }

    @Override
    public boolean deleteDiskOffering(long userId, long id) {
        return _configMgr.deleteDiskOffering(userId, id);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    }

    @Override
Solution content
    }

    @Override
    public AsyncJobResult queryAsyncJobResult(QueryAsyncJobResultCmd cmd) throws PermissionDeniedException {
        return queryAsyncJobResult(cmd.getId());
    }

    @Override
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Method invocation
Method signature
Return statement
Chunk
Conflicting content
            } else {
    }

    @Override
<<<<<<< HEAD
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();
=======
    @DB
    public LoadBalancerVO createLoadBalancer(Long userId, Long accountId, String name, String description, String ipAddress, String publicPort, String privatePort, String algorithm)
            throws InvalidParameterValueException, PermissionDeniedException {
        if (accountId == null) {
            throw new InvalidParameterValueException("accountId not specified");
        }
        if (!NetUtils.isValidIp(ipAddress)) {
            throw new InvalidParameterValueException("invalid ip address");
        }
        if (!NetUtils.isValidPort(publicPort)) {
            throw new InvalidParameterValueException("publicPort is an invalid value");
        }
        if (!NetUtils.isValidPort(privatePort)) {
            throw new InvalidParameterValueException("privatePort is an invalid value");
        }
        if ((algorithm == null) || !NetUtils.isValidAlgorithm(algorithm)) {
            throw new InvalidParameterValueException("Invalid algorithm");
        }

        boolean locked = false;
        try {
            LoadBalancerVO exitingLB = _loadBalancerDao.findByIpAddressAndPublicPort(ipAddress, publicPort);
            if (exitingLB != null) {
                throw new InvalidParameterValueException("IP Address/public port already load balanced by an existing load balancer rule");
            }

            List existingFwRules = _firewallRulesDao.listIPForwarding(ipAddress, publicPort, true);
            if ((existingFwRules != null) && !existingFwRules.isEmpty()) {
                FirewallRuleVO existingFwRule = existingFwRules.get(0);
                String securityGroupName = null;
                if (existingFwRule.getGroupId() != null) {
                    long groupId = existingFwRule.getGroupId();
                    SecurityGroupVO securityGroup = _securityGroupDao.findById(groupId);
                    securityGroupName = securityGroup.getName();
                }
                throw new InvalidParameterValueException("IP Address (" + ipAddress + ") and port (" + publicPort + ") already in use" +
                        ((securityGroupName == null) ? "" : " by port forwarding service " + securityGroupName));
            }

            IPAddressVO addr = _publicIpAddressDao.acquire(ipAddress);

            if (addr == null) {
                throw new PermissionDeniedException("User does not own ip address " + ipAddress);
            }

            locked = true;
            if ((addr.getAllocated() == null) || !accountId.equals(addr.getAccountId())) {
                throw new PermissionDeniedException("User does not own ip address " + ipAddress);
            }

            LoadBalancerVO loadBalancer = new LoadBalancerVO(name, description, accountId.longValue(), ipAddress, publicPort, privatePort, algorithm);
            loadBalancer = _loadBalancerDao.persist(loadBalancer);
            Long id = loadBalancer.getId();

            // Save off information for the event that the security group was applied
            EventVO event = new EventVO();
            event.setUserId(userId);
            event.setAccountId(accountId);
            event.setType(EventTypes.EVENT_LOAD_BALANCER_CREATE);

            if (id == null) {
                event.setDescription("Failed to create load balancer " + loadBalancer.getName() + " on ip address " + ipAddress + "[" + publicPort + "->" + privatePort + "]");
                event.setLevel(EventVO.LEVEL_ERROR);
            } else {
                event.setDescription("Successfully created load balancer " + loadBalancer.getName() + " on ip address " + ipAddress + "[" + publicPort + "->" + privatePort + "]");
                String params = "id="+loadBalancer.getId()+"\ndcId="+addr.getDataCenterId();
                }

                event.setParameters(params);
                event.setLevel(EventVO.LEVEL_INFO);
            }
            _eventDao.persist(event);

            return _loadBalancerDao.findById(id);
        } finally {
            if (locked) {
                _publicIpAddressDao.release(ipAddress);
            }
        }
    }

    @Override @DB
    public void assignToLoadBalancer(long userId, long loadBalancerId, List instanceIds) throws NetworkRuleConflictException, InternalErrorException,
            PermissionDeniedException, InvalidParameterValueException {
        Transaction txn = Transaction.currentTxn();
        try {
            List firewallRulesToApply = new ArrayList();
            long accountId = 0;
            DomainRouterVO router = null;

            LoadBalancerVO loadBalancer = _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
            if (loadBalancer == null) {
                s_logger.warn("Unable to find load balancer with id " + loadBalancerId);
                return;
            }

            List mappedInstances = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, false);
            Set mappedInstanceIds = new HashSet();
            if (mappedInstances != null) {
                for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
                    mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId()));
                }
            }

            for (Long instanceId : instanceIds) {
                if (mappedInstanceIds.contains(instanceId)) {
                    continue;
                }

                UserVmVO userVm = _userVmDao.findById(instanceId);
                if (userVm == null) {
                    s_logger.warn("Unable to find virtual machine with id " + instanceId);
                    throw new InvalidParameterValueException("Unable to find virtual machine with id " + instanceId);
                } else {
                    // sanity check that the vm can be applied to the load balancer
                    ServiceOfferingVO offering = _offeringsDao.findById(userVm.getServiceOfferingId());
                    if ((offering == null) || !NetworkOffering.GuestIpType.Virtualized.equals(offering.getGuestIpType())) {
                        // we previously added these instanceIds to the loadBalancerVMMap, so remove them here as we are rejecting the API request
                        // without actually modifying the load balancer
                        _loadBalancerVMMapDao.remove(loadBalancerId, instanceIds, Boolean.TRUE);

                        if (s_logger.isDebugEnabled()) {
                            s_logger.debug("Unable to add virtual machine " + userVm.toString() + " to load balancer " + loadBalancerId + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                        }

                        throw new InvalidParameterValueException("Unable to add virtual machine " + userVm.toString() + " to load balancer " + loadBalancerId + ", bad network type (" + ((offering == null) ? "null" : offering.getGuestIpType()) + ")");
                    }
                }

                if (accountId == 0) {
                    accountId = userVm.getAccountId();
                } else if (accountId != userVm.getAccountId()) {
                    s_logger.warn("guest vm " + userVm.getName() + " (id:" + userVm.getId() + ") belongs to account " + userVm.getAccountId()
                            + ", previous vm in list belongs to account " + accountId);
                    throw new InvalidParameterValueException("guest vm " + userVm.getName() + " (id:" + userVm.getId() + ") belongs to account " + userVm.getAccountId()
                            + ", previous vm in list belongs to account " + accountId);
                }
                
                DomainRouterVO nextRouter = null;
                if (userVm.getDomainRouterId() != null)
                	nextRouter = _routerDao.findById(userVm.getDomainRouterId());
                if (nextRouter == null) {
                    s_logger.warn("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + instanceId);
                    throw new InvalidParameterValueException("Unable to find router (" + userVm.getDomainRouterId() + ") for virtual machine with id " + instanceId);
            if (loadBalancer == null) {
                if (router == null) {
                    router = nextRouter;

                    // Make sure owner of router is owner of load balancer.  Since we are already checking that all VMs belong to the same router, by checking router
                    // ownership once we'll make sure all VMs belong to the owner of the load balancer.
                    if (router.getAccountId() != loadBalancer.getAccountId()) {
                        throw new InvalidParameterValueException("guest vm " + userVm.getName() + " (id:" + userVm.getId() + ") does not belong to the owner of load balancer " +
                                loadBalancer.getName() + " (owner is account id " + loadBalancer.getAccountId() + ")");
                    }
                } else if (router.getId() != nextRouter.getId()) {
                    throw new InvalidParameterValueException("guest vm " + userVm.getName() + " (id:" + userVm.getId() + ") belongs to router " + nextRouter.getName()
                            + ", previous vm in list belongs to router " + router.getName());
                }

                // check for ip address/port conflicts by checking exising forwarding and loadbalancing rules
                String ipAddress = loadBalancer.getIpAddress();
                String privateIpAddress = userVm.getGuestIpAddress();
                List existingRulesOnPubIp = _firewallRulesDao.listIPForwarding(ipAddress);

                if (existingRulesOnPubIp != null) {
                    for (FirewallRuleVO fwRule : existingRulesOnPubIp) {
                        if (!(  (fwRule.isForwarding() == false) &&
                                (fwRule.getGroupId() != null) &&
                                (fwRule.getGroupId() == loadBalancer.getId().longValue())  )) {
                            // if the rule is not for the current load balancer, check to see if the private IP is our target IP,
                            // in which case we have a conflict
                            if (fwRule.getPublicPort().equals(loadBalancer.getPublicPort())) {
                                throw new NetworkRuleConflictException("An existing port forwarding service rule for " + ipAddress + ":" + loadBalancer.getPublicPort()
                                        + " exists, found while trying to apply load balancer " + loadBalancer.getName() + " (id:" + loadBalancer.getId() + ") to instance "
                                        + userVm.getName() + ".");
                            }
                        } else if (fwRule.getPrivateIpAddress().equals(privateIpAddress) && fwRule.getPrivatePort().equals(loadBalancer.getPrivatePort()) && fwRule.isEnabled()) {
                            // for the current load balancer, don't add the same instance to the load balancer more than once
                            continue;
                        }
                    }
                }

                FirewallRuleVO newFwRule = new FirewallRuleVO();
                newFwRule.setAlgorithm(loadBalancer.getAlgorithm());
                newFwRule.setEnabled(true);
                newFwRule.setForwarding(false);
                newFwRule.setPrivatePort(loadBalancer.getPrivatePort());
                newFwRule.setPublicPort(loadBalancer.getPublicPort());
                newFwRule.setPublicIpAddress(loadBalancer.getIpAddress());
                newFwRule.setPrivateIpAddress(userVm.getGuestIpAddress());
                newFwRule.setGroupId(loadBalancer.getId());

                firewallRulesToApply.add(newFwRule);
            }

            // if there's no work to do, bail out early rather than reconfiguring the proxy with the existing rules
            if (firewallRulesToApply.isEmpty()) {
                return;
            }

            IPAddressVO ipAddr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
            List ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(accountId, ipAddr.getDataCenterId(), null);
            for (IPAddressVO ipv : ipAddrs) {
                List rules = _firewallRulesDao.listIPForwarding(ipv.getAddress(), false);
                firewallRulesToApply.addAll(rules);
            }

            txn.start();

            List updatedRules = null;
            if (router.getState().equals(State.Starting)) {
                // Starting is a special case...if the router is starting that means the IP address hasn't yet been assigned to the domR and the update firewall rules script will fail.
                // In this case, just store the rules and they will be applied when the router state is resent (after the router is started).
                updatedRules = firewallRulesToApply;
                updatedRules = _networkMgr.updateFirewallRules(loadBalancer.getIpAddress(), firewallRulesToApply, router);
            }

            // Save and create the event
            String description;
            String type = EventTypes.EVENT_NET_RULE_ADD;
            String ruleName = "load balancer";
            String level = EventVO.LEVEL_INFO;
            Account account = _accountDao.findById(accountId);

            LoadBalancerVO loadBalancerLock = null;
            try {
                loadBalancerLock = _loadBalancerDao.acquire(loadBalancerId);
                if (loadBalancerLock == null) {
                    s_logger.warn("assignToLoadBalancer: Failed to lock load balancer " + loadBalancerId + ", proceeding with updating loadBalancerVMMappings...");
                }
                if ((updatedRules != null) && (updatedRules.size() == firewallRulesToApply.size())) {
                    // flag the instances as mapped to the load balancer
                    List pendingMappedVMs = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId, true);
                    for (LoadBalancerVMMapVO pendingMappedVM : pendingMappedVMs) {
                        if (instanceIds.contains(pendingMappedVM.getInstanceId())) {
                            LoadBalancerVMMapVO pendingMappedVMForUpdate = _loadBalancerVMMapDao.createForUpdate();
                            pendingMappedVMForUpdate.setPending(false);
                            _loadBalancerVMMapDao.update(pendingMappedVM.getId(), pendingMappedVMForUpdate);
                        }
                    }

                    for (FirewallRuleVO updatedRule : updatedRules) {
                        if (updatedRule.getId() == null) {
                            _firewallRulesDao.persist(updatedRule);

                            description = "created new " + ruleName + " rule [" + updatedRule.getPublicIpAddress() + ":"
                                    + updatedRule.getPublicPort() + "]->[" + updatedRule.getPrivateIpAddress() + ":"
                                    + updatedRule.getPrivatePort() + "]" + " " + updatedRule.getProtocol();

                            saveEvent(userId, account.getId(), level, type, description);
                        }
                    }
                } else {
                    // Remove the instanceIds from the load balancer since there was a failure.  Make sure to commit the
                    // transaction here, otherwise the act of throwing the internal error exception will cause this
                    // remove operation to be rolled back.
                    _loadBalancerVMMapDao.remove(loadBalancerId, instanceIds, null);
                    txn.commit();

                    s_logger.warn("Failed to apply load balancer " + loadBalancer.getName() + " (id:" + loadBalancerId + ") to guest virtual machines " + StringUtils.join(instanceIds, ","));
                    throw new InternalErrorException("Failed to apply load balancer " + loadBalancer.getName() + " (id:" + loadBalancerId + ") to guest virtual machine " + StringUtils.join(instanceIds, ","));
                }
            } finally {
                if (loadBalancerLock != null) {
                    _loadBalancerDao.release(loadBalancerId);
                }
            }

            txn.commit();
        } catch (Throwable e) {
            txn.rollback();
            if (e instanceof NetworkRuleConflictException) {
                throw (NetworkRuleConflictException) e;
            } else if (e instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) e;
            } else if (e instanceof PermissionDeniedException) {
                throw (PermissionDeniedException) e;
            } else if (e instanceof InternalErrorException) {
                s_logger.warn("ManagementServer error", e);
                throw (InternalErrorException) e;
            }
            s_logger.warn("ManagementServer error", e);
	    }
    }

    @Override @DB
    public long assignToLoadBalancerAsync(long userId, long loadBalancerId, List instanceIds) {
        LoadBalancerVO loadBalancer = null;
        try {
            loadBalancer = _loadBalancerDao.acquire(loadBalancerId);

            // if unable to lock the load balancer, throw an exception
                throw new CloudRuntimeException("Failed to assign instances to load balancer, unable to lock load balancer " + loadBalancerId);
            }

            IPAddressVO ipAddress = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
            DomainRouterVO router = _routerDao.findBy(loadBalancer.getAccountId(), ipAddress.getDataCenterId());

            List mappedVMs = _loadBalancerVMMapDao.listByLoadBalancerId(loadBalancerId);
            for (LoadBalancerVMMapVO mappedVM : mappedVMs) {
                if (instanceIds.contains(mappedVM.getInstanceId())) {
                    instanceIds.remove(mappedVM.getInstanceId());
                }
            }

            if (instanceIds.isEmpty()) {
                // nothing to do, return 0 since no job is being submitted
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("assignToLoadBalancerAsync:  all given instance ids are already mapped, no work to do...skipping async job");
                }
                return 0L;
            }
            for (Long instanceId : instanceIds) {
                LoadBalancerVMMapVO loadBalancerMapping = new LoadBalancerVMMapVO(loadBalancerId, instanceId.longValue(), true);
                _loadBalancerVMMapDao.persist(loadBalancerMapping);
            }

            LoadBalancerParam param = new LoadBalancerParam(userId, router.getId(), loadBalancerId, instanceIds);
            Gson gson = GsonHelper.getBuilder().create();

            AsyncJobVO job = new AsyncJobVO();
            job.setUserId(UserContext.current().getUserId());
            job.setAccountId(loadBalancer.getAccountId());
            job.setCmd("AssignToLoadBalancer");
            job.setCmdInfo(gson.toJson(param));
            return _asyncMgr.submitAsyncJob(job, true);
        } finally {
            if (loadBalancer != null) {
                _loadBalancerDao.release(loadBalancer.getId());
            }
        }
    }

    @Override @DB
    public boolean removeFromLoadBalancer(long userId, long loadBalancerId, List instanceIds) throws InvalidParameterValueException {
        Transaction txn = Transaction.currentTxn();
        LoadBalancerVO loadBalancerLock = null;
        boolean success = true;
        try {
            LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
            if (loadBalancer == null) {
                return false;
            }

            IPAddressVO ipAddress = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
            if (ipAddress == null) {
                return false;
            }

            DomainRouterVO router = _routerDao.findBy(ipAddress.getAccountId(), ipAddress.getDataCenterId());
            if (router == null) {
                return false;
            }

            txn.start();
            for (Long instanceId : instanceIds) {
                UserVm userVm = _userVmDao.findById(instanceId);
                if (userVm == null) {
                    s_logger.warn("Unable to find virtual machine with id " + instanceId);
                    throw new InvalidParameterValueException("Unable to find virtual machine with id " + instanceId);
                }
                FirewallRuleVO fwRule = _firewallRulesDao.findByGroupAndPrivateIp(loadBalancerId, userVm.getGuestIpAddress(), false);
                if (fwRule != null) {
                    fwRule.setEnabled(false);
                    _firewallRulesDao.update(fwRule.getId(), fwRule);
                }
            }

            List allLbRules = new ArrayList();
            IPAddressVO ipAddr = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
            List ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(loadBalancer.getAccountId(), ipAddr.getDataCenterId(), null);
            for (IPAddressVO ipv : ipAddrs) {
                List rules = _firewallRulesDao.listIPForwarding(ipv.getAddress(), false);
                allLbRules.addAll(rules);
            }

            _networkMgr.updateFirewallRules(loadBalancer.getIpAddress(), allLbRules, router);

            // firewall rules are updated, lock the load balancer as mappings are updated
            loadBalancerLock = _loadBalancerDao.acquire(loadBalancerId);
            if (loadBalancerLock == null) {
                s_logger.warn("removeFromLoadBalancer: failed to lock load balancer " + loadBalancerId + ", deleting mappings anyway...");
            }

            // remove all the loadBalancer->VM mappings
            _loadBalancerVMMapDao.remove(loadBalancerId, instanceIds, Boolean.FALSE);

            // Save and create the event
            String description;
            String type = EventTypes.EVENT_NET_RULE_DELETE;
            String level = EventVO.LEVEL_INFO;
            Account account = _accountDao.findById(loadBalancer.getAccountId());

            for (FirewallRuleVO updatedRule : allLbRules) {
                if (!updatedRule.isEnabled()) {
                    _firewallRulesDao.remove(updatedRule.getId());

                    description = "deleted load balancer rule [" + updatedRule.getPublicIpAddress() + ":" + updatedRule.getPublicPort() + "]->["
                            + updatedRule.getPrivateIpAddress() + ":" + updatedRule.getPrivatePort() + "]" + " " + updatedRule.getProtocol();

                    saveEvent(userId, account.getId(), level, type, description);
                }
            }
            txn.commit();
        } catch (Exception ex) {
            s_logger.warn("Failed to delete load balancing rule with exception: ", ex);
            success = false;
            txn.rollback();
        } finally {
            if (loadBalancerLock != null) {
                _loadBalancerDao.release(loadBalancerId);
            }
        }
        return success;
    }

    @Override
    public long removeFromLoadBalancerAsync(long userId, long loadBalancerId, List instanceIds) {
        LoadBalancerVO loadBalancer = _loadBalancerDao.findById(loadBalancerId);
        IPAddressVO ipAddress = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
        DomainRouterVO router = _routerDao.findBy(loadBalancer.getAccountId(), ipAddress.getDataCenterId());
        LoadBalancerParam param = new LoadBalancerParam(userId, router.getId(), loadBalancerId, instanceIds);
        Gson gson = GsonHelper.getBuilder().create();

        AsyncJobVO job = new AsyncJobVO();
    	job.setUserId(UserContext.current().getUserId());
    	job.setAccountId(loadBalancer.getAccountId());
        job.setCmd("RemoveFromLoadBalancer");
        job.setCmdInfo(gson.toJson(param));
        
        return _asyncMgr.submitAsyncJob(job, true);
    }

    @Override @DB
    public boolean deleteLoadBalancer(long userId, long loadBalancerId) {
        Transaction txn = Transaction.currentTxn();
        LoadBalancerVO loadBalancer = null;
        LoadBalancerVO loadBalancerLock = null;
        try {
            loadBalancer = _loadBalancerDao.findById(loadBalancerId);
            if (loadBalancer == null) {
                return false;
            }

            IPAddressVO ipAddress = _publicIpAddressDao.findById(loadBalancer.getIpAddress());
            if (ipAddress == null) {
                return false;
            }

            DomainRouterVO router = _routerDao.findBy(ipAddress.getAccountId(), ipAddress.getDataCenterId());
            List fwRules = _firewallRulesDao.listByLoadBalancerId(loadBalancerId);

            txn.start();

            if ((fwRules != null) && !fwRules.isEmpty()) {
                for (FirewallRuleVO fwRule : fwRules) {
                    fwRule.setEnabled(false);
                    _firewallRulesDao.update(fwRule.getId(), fwRule);
                }

                List allLbRules = new ArrayList();
                List ipAddrs = _networkMgr.listPublicIpAddressesInVirtualNetwork(loadBalancer.getAccountId(), ipAddress.getDataCenterId(), null);
                for (IPAddressVO ipv : ipAddrs) {
                    List rules = _firewallRulesDao.listIPForwarding(ipv.getAddress(), false);
                    allLbRules.addAll(rules);
                }

                _networkMgr.updateFirewallRules(loadBalancer.getIpAddress(), allLbRules, router);

                // firewall rules are updated, lock the load balancer as the mappings are updated
                loadBalancerLock = _loadBalancerDao.acquire(loadBalancerId);
                if (loadBalancerLock == null) {
                    s_logger.warn("deleteLoadBalancer: failed to lock load balancer " + loadBalancerId + ", deleting mappings anyway...");
                }

                // remove all loadBalancer->VM mappings
                _loadBalancerVMMapDao.remove(loadBalancerId);

                // Save and create the event
                String description;
                String type = EventTypes.EVENT_NET_RULE_DELETE;
                String ruleName = "load balancer";
                String level = EventVO.LEVEL_INFO;
                Account account = _accountDao.findById(loadBalancer.getAccountId());

                for (FirewallRuleVO updatedRule : fwRules) {
                    _firewallRulesDao.remove(updatedRule.getId());

                    description = "deleted " + ruleName + " rule [" + updatedRule.getPublicIpAddress() + ":" + updatedRule.getPublicPort() + "]->["
                                  + updatedRule.getPrivateIpAddress() + ":" + updatedRule.getPrivatePort() + "]" + " " + updatedRule.getProtocol();
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        if (applied == null) {
            applied = Boolean.TRUE;
Solution content
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }
        */

        if (instanceId != null) {
            sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
        }

        if (ipAddress != null) {
            sc.addAnd("ipAddress", SearchCriteria.Op.EQ, ipAddress);
        }

        Map> securityGroups = new HashMap>();
        List sgVmMappings = _securityGroupVMMapDao.search(sc, searchFilter);
        if (sgVmMappings != null) {
            for (SecurityGroupVMMapVO sgVmMapping : sgVmMappings) {
                SecurityGroupVO sg = _securityGroupDao.findById(sgVmMapping.getSecurityGroupId());
                List sgList = securityGroups.get(sgVmMapping.getIpAddress());
                if (sgList == null) {
                    sgList = new ArrayList();
                }
                sgList.add(sg);
                securityGroups.put(sgVmMapping.getIpAddress(), sgList);
            }
        }
        return securityGroups;
    }

    @Override
    public boolean isSecurityGroupNameInUse(Long domainId, Long accountId, String name) {
        if (domainId == null) {
            domainId = DomainVO.ROOT_DOMAIN;
        }

        return _securityGroupDao.isNameInUse(accountId, domainId, name);
    }

    @Override
    public SecurityGroupVO findSecurityGroupById(Long groupId) {
        return _securityGroupDao.findById(groupId);
    }

    @Override
    public LoadBalancerVO findLoadBalancer(Long accountId, String name) {
        SearchCriteria sc = _loadBalancerDao.createSearchCriteria();
        sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId);
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        List loadBalancers = _loadBalancerDao.search(sc, null);
        if ((loadBalancers != null) && !loadBalancers.isEmpty()) {
            return loadBalancers.get(0);
        }
        return null;
    }

    @Override
    public LoadBalancerVO findLoadBalancerById(long loadBalancerId) {
        return _loadBalancerDao.findById(Long.valueOf(loadBalancerId));
    }

    @Override
    public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long loadBalancerId = cmd.getId();
        Boolean applied = cmd.isApplied();

        if (applied == null) {
            applied = Boolean.TRUE;
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Cast expression
Comment
For statement
If statement
Method declaration
Method invocation
Method signature
Try statement
Variable
Chunk
Conflicting content
		return null;
	}
        
<<<<<<< HEAD
    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
=======
    @Override
    public ArrayList getCloudIdentifierResponse(long userId)
    {
    	Criteria c = new Criteria ();
    	c.addCriteria(Criteria.NAME, "cloud.identifier");

    	List configs = searchForConfigurations(c, true);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	
    	//verify that user exists
        User user = findUserById(userId);
Solution content
		return null;
	}

    public ArrayList getCloudIdentifierResponse(GetCloudIdentifierCmd cmd) throws InvalidParameterValueException{
    	Long userId = cmd.getUserId();
    	
    	//verify that user exists
        User user = findUserById(userId);
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method invocation
Method signature
Variable
Chunk
Conflicting content
	}

	@Override
<<<<<<< HEAD
	public boolean lockAccount(LockAccountCmd cmd) {
=======
	public boolean addConfig(String instance, String component,String category, String name, String value, String description) 
	{
		return _configMgr.addConfig(category, instance, component, name, value, description);		
	}

	@Override
    public boolean preparePrimaryStorageForMaintenance(long primaryStorageId, long userId) {
		return	_storageMgr.preparePrimaryStorageForMaintenance(primaryStorageId, userId);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
Solution content
	}

	@Override
	public boolean lockAccount(LockAccountCmd cmd) {
        Account adminAccount = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Method declaration
Method invocation
Method signature
Return statement
Chunk
Conflicting content
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

<<<<<<< HEAD
        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
=======
	@Override
    public long preparePrimaryStorageForMaintenanceAsync(long primaryStorageId) throws InvalidParameterValueException 
	{
    	StoragePoolVO primaryStorage = _poolDao.findById(primaryStorageId);
    	
    	if (primaryStorage == null) {
            s_logger.debug("Unable to find primary storage id: " + primaryStorageId);
            throw new InvalidParameterValueException("Unable to find storage pool with ID: " + primaryStorageId + ". Please specify a valid primary storage ID.");
        }
        
        if (_poolDao.countBy(primaryStorage.getId(), Status.PrepareForMaintenance, Status.ErrorInMaintenance, Status.Maintenance) > 0) {
            throw new InvalidParameterValueException("There are other primary storages in maintenance mode.");
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }

<<<<<<< HEAD
Solution content
        Long domainId = cmd.getDomainId();
        String accountName = UserContext.current().getAccountName();

        if ((adminAccount != null) && !_domainDao.isChildDomain(adminAccount.getDomainId(), domainId)) {
            throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Failed to lock account " + accountName + " in domain " + domainId + ", permission denied.");
        }
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
If statement
Method invocation
Method signature
Throw statement
Variable
Chunk
Conflicting content
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }

<<<<<<< HEAD
        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
=======
	}
	
    @Override
    public boolean cancelPrimaryStorageMaintenance(long primaryStorageId, long userId)
    {
		return	_storageMgr.cancelPrimaryStorageForMaintenance(primaryStorageId, userId);
    }
	
	@Override
    public long cancelPrimaryStorageMaintenanceAsync(long primaryStorageId) throws InvalidParameterValueException 
	{
    	StoragePoolVO primaryStorage = _poolDao.findById(primaryStorageId);
    	
    	if (primaryStorage == null) {
            s_logger.debug("Unable to find primary storage id: " + primaryStorageId);
            throw new InvalidParameterValueException("Unable to find storage pool with ID: " + primaryStorageId + ". Please specify a valid primary storage ID.");
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }

        // don't allow modify system account
Solution content
        }

        Account account = _accountDao.findActiveAccount(accountName, domainId);
        if (account == null) {
            throw new ServerApiException (BaseCmd.PARAM_ERROR, "Unable to find active account with name " + accountName + " in domain " + domainId);
        }

        // don't allow modify system account
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
If statement
Method declaration
Method invocation
Method signature
Throw statement
Variable
Chunk
Conflicting content
	}

	@Override
<<<<<<< HEAD
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
=======
	public boolean validateCustomVolumeSizeRange(long size) throws InvalidParameterValueException {
        if (size<0 || (size>0 && size < 2097152)) {
            throw new InvalidParameterValueException("Please specify a size (in bytes) of at least 2 MB or above.");
        } else if (size > (_maxVolumeSizeInGb*1000000000)) {
        	throw new InvalidParameterValueException("The maximum size allowed is 2 TB");
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        }
        
        // If the user is a System user, return an error.  We do not allow this
Solution content
	}

	@Override
	public boolean deleteUser(DeleteUserCmd cmd) {
        Long userId = cmd.getId();
        
        //Verify that the user exists in the system
        User user = getUser(userId.longValue());
        if (user == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find user " + userId);
        }
        
        // If the user is a System user, return an error.  We do not allow this
File
ManagementServerImpl.java
Developer's decision
Version 1
Kind of conflict
Comment
If statement
Method invocation
Method signature
Throw statement
Variable
Chunk
Conflicting content
		
        return deleteUserInternal(userId);
	}
<<<<<<< HEAD
=======

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);
		
		if(poolHostRecordSet!=null)
		{
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities() {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));
    	
    	if(poolsInTransition==null)
    		return 0;
    	else
    		return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }
    
    //Move vmGroup section to UserVmManager when merge with api refactor branch is done
    @Override
    public InstanceGroupVO createVmGroup(String name, Long accountId){
    	return _vmMgr.createVmGroup(name, accountId);
    }
    
    @Override
    public InstanceGroupVO findVmGroupById(long groupId) {
    	InstanceGroupVO group = _vmGroupDao.findById(groupId);
    	//return only active vm groups
    	if (group.getRemoved() == null) {
    		return group;
    	}
    	else {
    		return null;
    	}
    }
    
    @Override
    public InstanceGroupVO updateVmGroup(long groupId, String name){
          
        if (name != null) {
        	_vmGroupDao.updateVmGroup(groupId, name);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }
    
    @Override
    public boolean isVmGroupNameInUse(Long accountId, String name) {
        return _vmGroupDao.isNameInUse(accountId, name);
    }
    
    @Override
    public boolean deleteVmGroup(long groupId) throws InternalErrorException{
        return _vmMgr.deleteVmGroup(groupId);
    }
    
    @Override
    public List searchForVmGroups(Criteria c) {
        Filter searchFilter = new Filter(InstanceGroupVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());

        Object[] accountIds = (Object[]) c.getCriteria(Criteria.ACCOUNTID);
        Object id = c.getCriteria(Criteria.ID);
        Object name = c.getCriteria(Criteria.NAME);
        Object domainId = c.getCriteria(Criteria.DOMAINID);
        Object keyword = c.getCriteria(Criteria.KEYWORD);

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);

        if ((accountIds == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountIds != null) {
            sc.setParameters("accountId", accountIds);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

        return _vmGroupDao.search(sc, searchFilter);
    }
    
	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}
    
    
    //Move section above to UserVmManager when merge with api refactor branch is done
    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }
    
    @Override
    public String getVersion(){
        final Class c = this.getClass();
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;
Solution content
		
        return deleteUserInternal(userId);
	}

	@Override
	public boolean checkIfMaintenable(long hostId) {

		//get the poolhostref record
		List poolHostRecordSet = _poolHostDao.listByHostId(hostId);

		
		{
		if(poolHostRecordSet!=null)
			//the above list has only 1 record
			StoragePoolHostVO poolHostRecord = poolHostRecordSet.get(0);
			
			//get the poolId and get hosts associated in that pool
			List hostsInPool = _poolHostDao.listByPoolId(poolHostRecord.getPoolId());
			
			if(hostsInPool!=null && hostsInPool.size()>1)
			{
				return true; //since there are other hosts to take over as master in this pool
			}
		}
		return false;
	}

    @Override
    public Map listCapabilities(ListCapabilitiesCmd cmd) {
        Map capabilities = new HashMap();
        
        String networkGroupsEnabled = _configs.get("direct.attach.network.groups.enabled");
        if(networkGroupsEnabled == null) 
            networkGroupsEnabled = "false";             

        capabilities.put("networkGroupsEnabled", networkGroupsEnabled);        
        capabilities.put("cloudStackVersion", getVersion());
        return capabilities;
    }

    @Override
    public GuestOSVO getGuestOs(Long guestOsId)
    {
    	return _guestOSDao.findById(guestOsId);
    }
    
    @Override
    public VolumeVO getRootVolume(Long instanceId)
    {
    	return _volumeDao.findByInstanceAndType(instanceId, Volume.VolumeType.ROOT).get(0);
    }
    
    @Override
    public long getPsMaintenanceCount(long podId){
    	List poolsInTransition = new ArrayList();
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
    	poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));

    	return poolsInTransition.size();
    }
    
    @Override
    public boolean isPoolUp(long instanceId){
		VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
		
		if(rootVolume!=null){
			Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
    	
			if(!poolStatus.equals(Status.Up))
				return false;
			else
				return true;
		}
		
		return false;
    }

    @Override
    public void extractVolume(ExtractVolumeCmd cmd) throws URISyntaxException, InternalErrorException {
        Long volumeId = cmd.getId();
        String url = cmd.getUrl();
        Long zoneId = cmd.getZoneId();
        AsyncJobVO job = cmd.getJob();
          
        VolumeVO volume = _volumeDao.findById(volumeId);        
        if (volume == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to find volume with id " + volumeId);
        }

        URI uri = new URI(url);
        if ( (uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
           throw new IllegalArgumentException("Unsupported scheme for url: " + url);
        }

        String host = uri.getHost();
        try {
            InetAddress hostAddr = InetAddress.getByName(host);
            if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
                throw new IllegalArgumentException("Illegal host specified in url");
            }
            if (hostAddr instanceof Inet6Address) {
                throw new IllegalArgumentException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
            }
        } catch (UnknownHostException uhe) {
            throw new IllegalArgumentException("Unable to resolve " + host);
        }
        
        if (_dcDao.findById(zoneId) == null) {
        return _vmGroupDao.search(sc, searchFilter);
            throw new IllegalArgumentException("Please specify a valid zone.");
        }
        
        if ( _uploadMonitor.isTypeUploadInProgress(volumeId, Type.VOLUME) ){
            throw new IllegalArgumentException(volume.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same");
        }
        
        long userId = UserContext.current().getUserId();
        long accountId = volume.getAccountId();        
        long eventId = EventUtils.saveScheduledEvent(userId, accountId, EventTypes.EVENT_VOLUME_UPLOAD, "Extraction job");

        String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); 
        StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId());
        Long sourceHostId = _storageMgr.findHostIdForStoragePool(srcPool);
        List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId);
        HostVO sserver = storageServers.get(0);

// FIXME:  fix the saving of scheduled v. started events
//        EventUtils.saveStartedEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, "Starting upload of " +volume.getName()+ " to " +url, eventId);        
        UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, 0, Type.VOLUME, null, null, url);
        uploadJob = _uploadDao.createForUpdate(uploadJob.getId());
        
        // Update the async Job
        ExtractJobResultObject resultObj = new ExtractJobResultObject(volume.getAccountId(), volume.getName(), UploadVO.Status.COPY_IN_PROGRESS.toString(), 0, uploadJob.getId());
        _asyncMgr.updateAsyncJobAttachment(job.getId(), Type.VOLUME.toString(), volumeId);
        _asyncMgr.updateAsyncJobStatus(job.getId(), AsyncJobResult.STATUS_IN_PROGRESS, resultObj);
        
        
     // Copy the volume from the source storage pool to secondary storage
        CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true);
        CopyVolumeAnswer cvAnswer = (CopyVolumeAnswer) _agentMgr.easySend(sourceHostId, cvCmd);
                
        if (cvAnswer == null || !cvAnswer.getResult()) {
            
            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
            
            resultObj.setResult_string(errorString);
            resultObj.setUploadStatus(UploadVO.Status.COPY_ERROR.toString());
            _asyncMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, resultObj);
            
            uploadJob.setUploadState(UploadVO.Status.COPY_ERROR);            
            uploadJob.setErrorString(errorString);
            uploadJob.setLastUpdated(new Date());
            _uploadDao.update(uploadJob.getId(), uploadJob);
            
            EventUtils.saveEvent(1L, volume.getAccountId(), EventTypes.EVENT_VOLUME_UPLOAD, errorString);
            
            throw new InternalErrorException(errorString);            
        }
        String volumeLocalPath = "volumes/"+volume.getId()+"/"+cvAnswer.getVolumePath()+".vhd"; 
        uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);        
        uploadJob.setLastUpdated(new Date());
        _uploadDao.update(uploadJob.getId(), uploadJob);
        
        _uploadMonitor.extractVolume(uploadJob, sserver, volume, url, zoneId, volumeLocalPath, eventId, job.getId(), _asyncMgr);
    }

    @Override
    public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();
        String groupName = cmd.getGroupName();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue());
        if (group == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "unable to find a group with id " + groupId + " for this account");
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
    }

                throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        //Check if name is already in use by this account (exclude this group)
        boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName);

        if (isNameInUse && !group.getName().equals(groupName)) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to update vm group, a group with name " + groupName + " already exisits for account");
        }

        if (groupName != null) {
        	_vmGroupDao.updateVmGroup(groupId, groupName);
        }
        InstanceGroupVO vmGroup = _vmGroupDao.findById(groupId);
        return vmGroup;
    }

    @Override
    public List searchForVmGroups(ListVMGroupsCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        if ((account == null) || isAdmin(account.getType())) {
            if (domainId != null) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Invalid domain id (" + domainId + ") given, unable to list vm groups.");
                }
                if (accountName != null) {
                    account = _accountDao.findActiveAccount(accountName, domainId);
                    if (account == null) {
                        throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find account " + accountName + " in domain " + domainId);
                    }
                    accountId = account.getId();
                }
            } else {
                domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
            }
        } else {
            accountName = account.getAccountName();
            accountId = account.getId();
            domainId = account.getDomainId();
        }

        Filter searchFilter = new Filter(InstanceGroupVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());

        Object id = cmd.getId();
        Object name = cmd.getGroupName();
        Object keyword = cmd.getKeyword();

        SearchBuilder sb = _vmGroupDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE);
        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);

        if ((accountId == null) && (domainId != null)) {
            // if accountId isn't specified, we can do a domain match for the admin case
            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 (keyword != null) {
            SearchCriteria ssc = _vmGroupDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
        }
        
    	if (id != null) {
        	sc.setParameters("id", id);
    	}
        
        if (name != null) {
            sc.setParameters("name", "%" + name + "%");
        }

        if (accountId != null) {
            sc.setParameters("accountId", accountId);
        } else if (domainId != null) {
            DomainVO domain = _domainDao.findById((Long)domainId);
            if (domain != null){
            	sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
            }   
        }

	@Override
	public InstanceGroupVO getGroupForVm(long vmId){
		return _vmMgr.getGroupForVm(vmId);
	}

    @Override
    public List searchForZoneWideVlans(long dcId, String vlanType, String vlanId){
    	return _vlanDao.searchForZoneWideVlans(dcId, vlanType, vlanId);
    }

    @Override
    public String getVersion(){
        final Class c = ManagementServer.class;
        String fullVersion = c.getPackage().getImplementationVersion();
        String version = "unknown"; 
        if(fullVersion.length() > 0){
            version = fullVersion.substring(0,fullVersion.lastIndexOf("."));
        }
        return version;
    }

	private Long checkAccountPermissions(long targetAccountId, long targetDomainId, String targetDesc, long targetId) throws ServerApiException {
        Long accountId = null;
File
ManagementServerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Comment
Method declaration
Chunk
Conflicting content
package com.cloud.servlet;

import java.io.IOException;
<<<<<<< HEAD

=======
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Solution content
package com.cloud.servlet;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
File
ConsoleProxyServlet.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
import org.apache.log4j.Logger;

<<<<<<< HEAD
=======
import com.cloud.api.BaseCmd;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.host.HostVO;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
Solution content
import org.apache.log4j.Logger;

import com.cloud.host.HostVO;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
File
ConsoleProxyServlet.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
	            account = (String)session.getAttribute(BaseCmd.Properties.ACCOUNT.getName());
	            accountObj = (Account)session.getAttribute(BaseCmd.Properties.ACCOUNT_OBJ.getName());
            }
<<<<<<< HEAD

            // FIXME:  are these set up correctly from ApiServer?
            String userIdStr = (String)session.getAttribute("userid");
            String account = (String)session.getAttribute("account");
            Object accountObj = session.getAttribute("accountobj");
            Long userId = null;
            if (userIdStr != null) {
                userId = Long.parseLong(userIdStr);
            }
=======
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

            // Do a sanity check here to make sure the user hasn't already been deleted
            if ((userId == null) || (account == null) || (accountObj == null) || !verifyUser(userId)) {
Solution content
/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 * 
 */

package com.cloud.servlet;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import com.cloud.host.HostVO;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.encoding.Base64;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;

/**
 * Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx
 * Console access : /conosole?cmd=access&vm=xxx
 * Authentication : /console?cmd=auth&vm=xxx&sid=xxx
 */
public class ConsoleProxyServlet extends HttpServlet {
	private static final long serialVersionUID = -5515382620323808168L;
	public static final Logger s_logger = Logger.getLogger(ConsoleProxyServlet.class.getName());
	private static final int DEFAULT_THUMBNAIL_WIDTH = 144;
	private static final int DEFAULT_THUMBNAIL_HEIGHT = 110;
	
	private final ManagementServer _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name);
	
	@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
		doGet(req, resp);
	}
	
	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
		try {
            String userId = null;
            String account = null;
            Account accountObj = null;
			
            Map params = new HashMap();
            params.putAll(req.getParameterMap());
            
            HttpSession session = req.getSession(false);
            if(session == null) {
            	if(verifyRequest(params)) {
                    userId = (String)params.get("userid")[0];
                    account = (String)params.get("account")[0];
                    accountObj = (Account)params.get("accountobj")[0];
            	} else {
					s_logger.info("Invalid web session or API key in request, reject console/thumbnail access");
					sendResponse(resp, "Access denied. Invalid web session or API key in request");
					return;
            	}
            } else {
                userId = (String)session.getAttribute("userid");
                account = (String)session.getAttribute("account");
                accountObj = (Account)session.getAttribute("accountobj");
            }

            // Do a sanity check here to make sure the user hasn't already been deleted
File
ConsoleProxyServlet.java
Developer's decision
Manual
Kind of conflict
Cast expression
Comment
If statement
Method invocation
Variable
Chunk
Conflicting content
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
<<<<<<< HEAD:server/src/com/cloud/storage/StorageManager.java
import com.cloud.api.commands.CancelPrimaryStorageMaintenanceCmd;
import com.cloud.api.commands.CreateStoragePoolCmd;
import com.cloud.api.commands.CreateVolumeCmd;
import com.cloud.api.commands.DeletePoolCmd;
import com.cloud.api.commands.DeleteVolumeCmd;
import com.cloud.api.commands.PreparePrimaryStorageForMaintenanceCmd;
import com.cloud.api.commands.UpdateStoragePoolCmd;
=======
import com.cloud.agent.api.to.VolumeTO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590:core/src/com/cloud/storage/StorageManager.java
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.deploy.DeployDestination;
Solution content
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.api.commands.CancelPrimaryStorageMaintenanceCmd;
import com.cloud.api.commands.CreateStoragePoolCmd;
import com.cloud.api.commands.CreateVolumeCmd;
import com.cloud.api.commands.DeletePoolCmd;
import com.cloud.api.commands.DeleteVolumeCmd;
import com.cloud.api.commands.PreparePrimaryStorageForMaintenanceCmd;
import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.deploy.DeployDestination;
File
StorageManager.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.user.Account;
<<<<<<< HEAD:server/src/com/cloud/storage/StorageManager.java
=======
import com.cloud.user.AccountVO;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590:core/src/com/cloud/storage/StorageManager.java
import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager;
import com.cloud.utils.exception.ExecutionException;
Solution content
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager;
import com.cloud.utils.exception.ExecutionException;
File
StorageManager.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
     * @return the primary storage pool
     * @throws InvalidParameterValueException
     */
<<<<<<< HEAD:server/src/com/cloud/storage/StorageManager.java
    public StoragePoolVO cancelPrimaryStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws InvalidParameterValueException;

	public StoragePoolVO updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException;
=======
    public boolean cancelPrimaryStorageForMaintenance(long primaryStorageId, long userId);
    
    /**
     * Allocates one volume.
     * @param 
     * @param type
     * @param offering
     * @param name
     * @param size
     * @param template
     * @param vm
     * @param account
     * @return VolumeVO a persisted volume.
     */
     DiskProfile allocateRawVolume(VolumeType type, String name, DiskOfferingVO offering, Long size, T vm, AccountVO owner);
     DiskProfile allocateTemplatedVolume(VolumeType type, String name, DiskOfferingVO offering, VMTemplateVO template, T vm, AccountVO owner);
    
     void create(T vm);
    Long findHostIdForStoragePool(StoragePoolVO pool);
	void createCapacityEntry(StoragePoolVO storagePool, long allocated);

    
    VolumeTO[] prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590:core/src/com/cloud/storage/StorageManager.java
}
Solution content
     * @return the primary storage pool
     * @throws InvalidParameterValueException
     */
    public StoragePoolVO cancelPrimaryStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws InvalidParameterValueException;

	public StoragePoolVO updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException;
    
    /**
     * Allocates one volume.
     * @param 
     * @param type
     * @param offering
     * @param name
     * @param size
     * @param template
     * @param vm
     * @param account
     * @return VolumeVO a persisted volume.
     */
     DiskProfile allocateRawVolume(VolumeType type, String name, DiskOfferingVO offering, Long size, T vm, AccountVO owner);
     DiskProfile allocateTemplatedVolume(VolumeType type, String name, DiskOfferingVO offering, VMTemplateVO template, T vm, AccountVO owner);
    
     void create(T vm);
    Long findHostIdForStoragePool(StoragePoolVO pool);
	void createCapacityEntry(StoragePoolVO storagePool, long allocated);

    
    VolumeTO[] prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException;
}
File
StorageManager.java
Developer's decision
Combination
Kind of conflict
Comment
Method interface
Chunk
Conflicting content
import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobManager;
<<<<<<< HEAD
=======
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.Config;
Solution content
import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobManager;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.configuration.Config;
File
StorageManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
<<<<<<< HEAD
import com.cloud.domain.dao.DomainDao;
=======
import com.cloud.deploy.DeployDestination;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.event.EventState;
import com.cloud.event.EventTypes;
import com.cloud.event.EventVO;
Solution content
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventState;
import com.cloud.event.EventTypes;
import com.cloud.event.EventVO;
File
StorageManagerImpl.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.vm.State;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
<<<<<<< HEAD
=======
import com.cloud.vm.DiskProfile;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
Solution content
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.State;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
File
StorageManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
    @Inject protected VMTemplateDao _templateDao;
    @Inject protected VMTemplateHostDao _templateHostDao;
    @Inject protected ServiceOfferingDao _offeringDao;
<<<<<<< HEAD
    @Inject protected DomainDao _domainDao;
=======
    @Inject protected UserDao _userDao;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    
    protected SearchBuilder HostTemplateStatesSearch;
    protected SearchBuilder PoolsUsedByVmSearch;
Solution content
    @Inject protected VMTemplateDao _templateDao;
    @Inject protected VMTemplateHostDao _templateHostDao;
    @Inject protected ServiceOfferingDao _offeringDao;
    @Inject protected DomainDao _domainDao;
    @Inject protected UserDao _userDao;
    
    protected SearchBuilder HostTemplateStatesSearch;
    protected SearchBuilder PoolsUsedByVmSearch;
File
StorageManagerImpl.java
Developer's decision
Concatenation
Kind of conflict
Attribute
Chunk
Conflicting content
        return answers[0];
    }
    
<<<<<<< HEAD
    private DiskCharacteristicsTO createDiskCharacteristics(VolumeVO volume, VMTemplateVO template, long dataCenterId, DiskOfferingVO diskOffering) {
=======
    protected DiskProfile createDiskCharacteristics(VolumeVO volume, VMTemplateVO template, DataCenterVO dc, DiskOfferingVO diskOffering) {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
            SearchCriteria sc = HostTemplateStatesSearch.create();
            sc.setParameters("id", template.getId());
Solution content
        return answers[0];
    }
    
    protected DiskProfile createDiskCharacteristics(VolumeVO volume, VMTemplateVO template, DataCenterVO dc, DiskOfferingVO diskOffering) {
        if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
            SearchCriteria sc = HostTemplateStatesSearch.create();
            sc.setParameters("id", template.getId());
File
StorageManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Method signature
Chunk
Conflicting content
        String volumeFolder = null;
        
        // Create the Volume object and save it so that we can return it to the user
<<<<<<< HEAD
        Account account = _accountDao.findById(volume.getAccountId());
=======
        Account account = _accountDao.findById(accountId);
        VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, 0, Volume.VolumeType.DATADISK);
        volume.setPoolId(null);
        volume.setDataCenterId(dc.getId());
        volume.setPodId(null);
        volume.setAccountId(accountId);
        volume.setDomainId(account.getDomainId());
        volume.setMirrorState(MirrorState.NOT_MIRRORED);
        if (diskOffering != null) {
            volume.setDiskOfferingId(diskOffering.getId());
        }
        volume.setSize(originalVolumeSize);
        volume.setStorageResourceType(Storage.StorageResourceType.STORAGE_POOL);
        volume.setInstanceId(null);
        volume.setUpdated(new Date());
        volume.setStatus(AsyncInstanceCreateStatus.Creating);
        volume.setSourceType(SourceType.Snapshot);
        volume.setSourceId(snapshot.getId());
        volume = _volsDao.persist(volume);
        volumeId = volume.getId();
        
        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
        if(asyncExecutor != null) {
            AsyncJobVO job = asyncExecutor.getJob();

            if(s_logger.isInfoEnabled())
                s_logger.info("CreateVolume created a new instance " + volumeId + ", update async job-" + job.getId() + " progress status");
            
            _asyncMgr.updateAsyncJobAttachment(job.getId(), "volume", volumeId);
            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, volumeId);
        }
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        
        final HashSet poolsToAvoid = new HashSet();
        StoragePoolVO pool = null;
Solution content
        String volumeFolder = null;
        
        // Create the Volume object and save it so that we can return it to the user
        Account account = _accountDao.findById(volume.getAccountId());

        final HashSet poolsToAvoid = new HashSet();
        StoragePoolVO pool = null;
File
StorageManagerImpl.java
Developer's decision
Version 1
Kind of conflict
If statement
Method invocation
Variable
Chunk
Conflicting content
        Pair pod = null;
        String volumeUUID = null;
        String details = null;
<<<<<<< HEAD
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
        DataCenterVO dc = _dcDao.findById(volume.getDataCenterId());
        DiskCharacteristicsTO dskCh = createDiskCharacteristics(volume, template, dc.getId(), diskOffering);

=======
        
        DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering);
        
        
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        // Determine what pod to store the volume in
        while ((pod = _agentMgr.findPod(null, null, dc, account.getId(), podsToAvoid)) != null) {
            // Determine what storage pool to store the volume in
Solution content
        Pair pod = null;
        String volumeUUID = null;
        String details = null;
        
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
        DataCenterVO dc = _dcDao.findById(volume.getDataCenterId());
        DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering);

        // Determine what pod to store the volume in
        while ((pod = _agentMgr.findPod(null, null, dc, account.getId(), podsToAvoid)) != null) {
            // Determine what storage pool to store the volume in
File
StorageManagerImpl.java
Developer's decision
Combination
Kind of conflict
Method invocation
Variable
Chunk
Conflicting content
                                    ServiceOfferingVO offering, DiskOfferingVO diskOffering, List avoids, long size) {
        StoragePoolVO pool = null;
        final HashSet avoidPools = new HashSet(avoids);
<<<<<<< HEAD

        DiskCharacteristicsTO dskCh = null;
=======
       
        DiskProfile dskCh = null;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
            dskCh = createDiskCharacteristics(volume, template, dc.getId(), offering);
        } else {
Solution content
                                    ServiceOfferingVO offering, DiskOfferingVO diskOffering, List avoids, long size) {
        StoragePoolVO pool = null;
        final HashSet avoidPools = new HashSet(avoids);
       
        DiskProfile dskCh = null;
        if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
            dskCh = createDiskCharacteristics(volume, template, dc, offering);
        } else {
File
StorageManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Variable
Chunk
Conflicting content
            throw new ResourceAllocationException("No host exists to associate a storage pool with");
        }
        long poolId = _storagePoolDao.getNextInSequence(Long.class, "id");
<<<<<<< HEAD
        String uuid = UUID.nameUUIDFromBytes(new String(storageHost + hostPath + System.currentTimeMillis()).getBytes()).toString();
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("In createPool Setting poolId - " +poolId+ " uuid - " +uuid+ " zoneId - " +zoneId+ " podId - " +podId+ " poolName - " +cmd.getStoragePoolName());
        }
=======
        String uuid = UUID.nameUUIDFromBytes(new String(storageHost + hostPath).getBytes()).toString();
        
        List spHandles = _storagePoolDao.findIfDuplicatePoolsExistByUUID(uuid);
        if(spHandles!=null && spHandles.size()>0)
        {
        	s_logger.debug("Another active pool with the same uuid already exists");
        	throw new ResourceInUseException("Another active pool with the same uuid already exists");
        }
        
        s_logger.debug("In createPool Setting poolId - " +poolId+ " uuid - " +uuid+ " zoneId - " +zoneId+ " podId - " +podId+ " poolName - " +poolName);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        pool.setId(poolId);
        pool.setUuid(uuid);
        pool.setDataCenterId(cmd.getZoneId());
Solution content
            throw new ResourceAllocationException("No host exists to associate a storage pool with");
        }
        long poolId = _storagePoolDao.getNextInSequence(Long.class, "id");
        String uuid = UUID.nameUUIDFromBytes(new String(storageHost + hostPath).getBytes()).toString();
        
        List spHandles = _storagePoolDao.findIfDuplicatePoolsExistByUUID(uuid);
        if ((spHandles != null) && (spHandles.size() > 0)) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Another active pool with the same uuid already exists");
            }
        	throw new ResourceInUseException("Another active pool with the same uuid already exists");
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("In createPool Setting poolId - " +poolId+ " uuid - " +uuid+ " zoneId - " +zoneId+ " podId - " +podId+ " poolName - " + cmd.getStoragePoolName());
        }

        pool.setId(poolId);
        pool.setUuid(uuid);
        pool.setDataCenterId(cmd.getZoneId());
File
StorageManagerImpl.java
Developer's decision
Manual
Kind of conflict
If statement
Method invocation
Variable
Chunk
Conflicting content
    }

    @Override
<<<<<<< HEAD
    public VolumeVO createVolumeDB(CreateVolumeCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException {
        // FIXME:  some of the scheduled event stuff might be missing here...
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account targetAccount = null;
        if ((account == null) || isAdmin(account.getType())) {
            // Admin API call
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to create volume in domain " + domainId + ", permission denied.");
                }
=======
    @DB
    public VolumeVO createVolume(long accountId, long userId, String userSpecifiedName, DataCenterVO dc, DiskOfferingVO diskOffering, long startEventId, long size) 
    {
    	String volumeName = "";
        VolumeVO createdVolume = null;
        
        try 
        {
	        // Determine the volume's name
	        volumeName = getRandomVolumeName();
	
	        // Create the Volume object and save it so that we can return it to the user
	        Account account = _accountDao.findById(accountId);
	        VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, 0, Volume.VolumeType.DATADISK);
	        volume.setPoolId(null);
	        volume.setDataCenterId(dc.getId());
	        volume.setPodId(null);
	        volume.setAccountId(accountId);
	        volume.setDomainId(account.getDomainId());
	        volume.setMirrorState(MirrorState.NOT_MIRRORED);
	        volume.setDiskOfferingId(diskOffering.getId());
	        volume.setStorageResourceType(Storage.StorageResourceType.STORAGE_POOL);
	        volume.setInstanceId(null);
	        volume.setUpdated(new Date());
	        volume.setStatus(AsyncInstanceCreateStatus.Creating);
	        volume.setDomainId(account.getDomainId());
	        volume.setSourceId(diskOffering.getId());
	        volume.setSourceType(SourceType.DiskOffering);
	        volume = _volsDao.persist(volume);
	
	        AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
	        if (asyncExecutor != null) {
	            AsyncJobVO job = asyncExecutor.getJob();
	
	            if (s_logger.isInfoEnabled())
	                s_logger.info("CreateVolume created a new instance " + volume.getId() + ", update async job-" + job.getId() + " progress status");
	
	            _asyncMgr.updateAsyncJobAttachment(job.getId(), "volume", volume.getId());
	            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, volume.getId());
	        }
	        
	        List poolsToAvoid = new ArrayList();
	        Set podsToAvoid = new HashSet();
	        Pair pod = null;
	
	        while ((pod = _agentMgr.findPod(null, null, dc, account.getId(), podsToAvoid)) != null) {
	            if ((createdVolume = createVolume(volume, null, null, dc, pod.first(), null, null, diskOffering, poolsToAvoid, size)) != null) {
	            	break;
	            } else {
	                podsToAvoid.add(pod.first().getId());
	            }
	        }
	
	        // Create an event
	        EventVO event = new EventVO();
	        event.setAccountId(accountId);
	        event.setUserId(userId);
	        event.setType(EventTypes.EVENT_VOLUME_CREATE);
	        event.setStartId(startEventId);
	
	        Transaction txn = Transaction.currentTxn();
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590

                targetAccount = _accountDao.findActiveAccount(accountName, domainId);
            } else {
Solution content
    }

    @Override
    public VolumeVO createVolumeDB(CreateVolumeCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ResourceAllocationException {
        // FIXME:  some of the scheduled event stuff might be missing here...
        Account account = (Account)UserContext.current().getAccountObject();
        String accountName = cmd.getAccountName();
        Long domainId = cmd.getDomainId();
        Account targetAccount = null;
        if ((account == null) || isAdmin(account.getType())) {
            // Admin API call
            if ((domainId != null) && (accountName != null)) {
                if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                    throw new PermissionDeniedException("Unable to create volume in domain " + domainId + ", permission denied.");
                }

                targetAccount = _accountDao.findActiveAccount(accountName, domainId);
            } else {
File
StorageManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Annotation
Cast expression
Comment
If statement
Method invocation
Method signature
Try statement
Variable
While statement
Chunk
Conflicting content
    
    @Override
    @DB
<<<<<<< HEAD
    public boolean preparePrimaryStorageForMaintenance(PreparePrimaryStorageForMaintenanceCmd cmd) {
    	Long primaryStorageId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
    	
        boolean destroyVolumes = false;
=======
    public boolean preparePrimaryStorageForMaintenance(long primaryStorageId, long userId) 
    {
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
        long count = 1;
        boolean restart = true;
        try 
Solution content
    
    @Override @DB
    public boolean preparePrimaryStorageForMaintenance(PreparePrimaryStorageForMaintenanceCmd cmd) {
    	Long primaryStorageId = cmd.getId();
    	Long userId = UserContext.current().getUserId();
        boolean restart = true;
        try 
File
StorageManagerImpl.java
Developer's decision
Manual
Kind of conflict
Method invocation
Method signature
Variable
Chunk
Conflicting content
    		return false;
    	}
    }
<<<<<<< HEAD

	private boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}
	
	@Override
	public boolean deleteVolume(DeleteVolumeCmd cmd) throws InvalidParameterValueException {
    	Account account = (Account) UserContext.current().getAccountObject();
    	Long volumeId = cmd.getId();
    	
    	boolean isAdmin;
    	if (account == null) {
    		// Admin API call
    		isAdmin = true;
    	} else {
    		// User API call
    		isAdmin = isAdmin(account.getType());
    	}

    	// Check that the volume ID is valid
    	VolumeVO volume = _volsDao.findById(volumeId);
    	if (volume == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId);
    	}
    	
    	// If the account is not an admin, check that the volume is owned by the account that was passed in
    	if (!isAdmin) {
    		if (account.getId() != volume.getAccountId()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId + " for account: " + account.getAccountName());
    		}
    	} else if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), volume.getDomainId())) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to delete volume with id " + volumeId + ", permission denied.");
    	}


        // Check that the volume is stored on shared storage
        if (!volumeOnSharedStoragePool(volume)) {
            throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
        }

        // Check that the volume is not currently attached to any VM
        if (volume.getInstanceId() != null) {
            throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
        }
           
        // Check that the volume is not already destroyed
        if (volume.getDestroyed()) {
            throw new InvalidParameterValueException("Please specify a volume that is not already destroyed.");
        }
        
        try {
			// Destroy the volume
			destroyVolume(volume);
		} catch (Exception e) {
			s_logger.warn("Error destroying volume:"+e);
			throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Error destroying volume:"+e);
		}
        
        return true;
    	
	}

	private boolean validateCustomVolumeSizeRange(long size) throws InvalidParameterValueException {
	    if (size<0 || (size>0 && size < 1)) {
	        throw new InvalidParameterValueException("Please specify a size of at least 1 Gb.");
	    } else if (size > _maxVolumeSizeInGb) {
	        throw new InvalidParameterValueException("The maximum size allowed is " + _maxVolumeSizeInGb + " Gb.");
	    }

	    return true;
	}
}
=======
	
	protected DiskProfile toDiskProfile(VolumeVO vol, DiskOfferingVO offering) {
	    return new DiskProfile(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.isRecreatable(), vol.getTemplateId());
	}
	
    @Override
    public  DiskProfile allocateRawVolume(VolumeType type, String name, DiskOfferingVO offering, Long size, T vm, AccountVO owner) {
        if (size == null) {
            size = offering.getDiskSizeInBytes();
        }
        VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size);
        if (vm != null) {
            vol.setInstanceId(vm.getId());
        }
        
        vol = _volsDao.persist(vol);
        
        return toDiskProfile(vol, offering);
    }
    
    @Override 
    public  DiskProfile allocateTemplatedVolume(VolumeType type, String name, DiskOfferingVO offering, VMTemplateVO template, T vm, AccountVO owner) {
        assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really....";
        
        SearchCriteria sc = HostTemplateStatesSearch.create();
        sc.setParameters("id", template.getId());
        sc.setParameters("state", com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
        sc.setJoinParameters("host", "dcId", vm.getDataCenterId());
        
        List sss = _vmTemplateHostDao.search(sc, null);
        if (sss.size() == 0) {
            throw new CloudRuntimeException("Template " + template.getName() + " has not been completely downloaded to zone " + vm.getDataCenterId());
        }
        VMTemplateHostVO ss = sss.get(0);
        
        VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), ss.getSize());
        if (vm != null) {
            vol.setInstanceId(vm.getId());
        }
        vol.setTemplateId(template.getId());
        
        vol = _volsDao.persist(vol);
        
        return toDiskProfile(vol, offering);
    }
    
    final protected DiskProfile createDiskCharacteristics(VolumeVO volume, DiskOfferingVO offering) {
        return new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), offering.getId(), volume.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.isRecreatable(), volume.getTemplateId());
    }
    
    final protected DiskProfile createDiskCharacteristics(VolumeVO volume) {
        DiskOfferingVO offering = _diskOfferingDao.findById(volume.getDiskOfferingId());
        return createDiskCharacteristics(volume, offering);
    }
    
    @Override
    public  void create(T vm) {
        List vols = _volsDao.findByInstance(vm.getId());
        assert vols.size() >= 1 : "Come on, what's with the zero volumes for " + vm;
        for (VolumeVO vol : vols) {
            DiskProfile dskCh = createDiskCharacteristics(vol);
            int retry = _retry;
            while (--retry >= 0) {
                
            }
        }
        /*
StoragePoolVO pool = null;
final HashSet avoidPools = new HashSet(avoids);

VolumeType volType = volume.getVolumeType();

VolumeTO created = null;
int retry = _retry;
while (--retry >= 0) {
created = null;

txn.start();

long podId = pod.getId();
pod = _podDao.lock(podId, true);
if (pod == null) {
txn.rollback();
volume.setStatus(AsyncInstanceCreateStatus.Failed);
volume.setDestroyed(true);
_volsDao.persist(volume);
throw new CloudRuntimeException("Unable to acquire lock on the pod " + podId);
}

pool = findStoragePool(dskCh, dc, pod, clusterId, offering, vm, template, avoidPools);
if (pool == null) {
txn.rollback();
break;
}

avoidPools.add(pool);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Trying to create " + volume + " on " + pool);
}

volume.setPoolId(pool.getId());
_volsDao.persist(volume);

txn.commit();

CreateCommand cmd = null;
VMTemplateStoragePoolVO tmpltStoredOn = null;
if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool);
if (tmpltStoredOn == null) {
continue;
}
cmd = new CreateCommand(volume, vm, dskCh, tmpltStoredOn.getLocalDownloadPath(), pool);
} else {
cmd = new CreateCommand(volume, vm, dskCh, pool, size);
}

Answer answer = sendToPool(pool, cmd);
if (answer != null && answer.getResult()) {
created = ((CreateAnswer)answer).getVolume();
break;
}

volume.setPoolId(null);
_volsDao.persist(volume);

s_logger.debug("Retrying the create because it failed on pool " + pool);
}

if (created == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to create a volume for " + volume);
}
volume.setStatus(AsyncInstanceCreateStatus.Failed);
volume.setDestroyed(true);
_volsDao.persist(volume);

return null;
}

volume.setStatus(AsyncInstanceCreateStatus.Created);
volume.setFolder(pool.getPath());
volume.setPath(created.getPath());
volume.setSize(created.getSize());
volume.setPoolType(pool.getPoolType());
volume.setPodId(pod.getId());
_volsDao.persist(volume);
return volume;
    */
        
    }
}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
Solution content
txn.rollback();
    		return false;
    	}
    }

	private boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}
	
	@Override
	public boolean deleteVolume(DeleteVolumeCmd cmd) throws InvalidParameterValueException {
    	Account account = (Account) UserContext.current().getAccountObject();
    	Long volumeId = cmd.getId();
    	
    	boolean isAdmin;
    	if (account == null) {
    		// Admin API call
    		isAdmin = true;
    	} else {
    		// User API call
    		isAdmin = isAdmin(account.getType());
    	}

    	// Check that the volume ID is valid
    	VolumeVO volume = _volsDao.findById(volumeId);
    	if (volume == null) {
    		throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId);
    	}
    	
    	// If the account is not an admin, check that the volume is owned by the account that was passed in
    	if (!isAdmin) {
    		if (account.getId() != volume.getAccountId()) {
                throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find volume with ID: " + volumeId + " for account: " + account.getAccountName());
    		}
    	} else if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), volume.getDomainId())) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to delete volume with id " + volumeId + ", permission denied.");
    	}


        // Check that the volume is stored on shared storage
        if (!volumeOnSharedStoragePool(volume)) {
            throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
        }

        // Check that the volume is not currently attached to any VM
        if (volume.getInstanceId() != null) {
            throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
        }
           
        // Check that the volume is not already destroyed
        if (volume.getDestroyed()) {
            throw new InvalidParameterValueException("Please specify a volume that is not already destroyed.");
        }
        
        try {
			// Destroy the volume
			destroyVolume(volume);
		} catch (Exception e) {
			s_logger.warn("Error destroying volume:"+e);
			throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Error destroying volume:"+e);
		}
        
        return true;
    	
	}

	private boolean validateCustomVolumeSizeRange(long size) throws InvalidParameterValueException {
	    if (size<0 || (size>0 && size < 1)) {
volume.setStatus(AsyncInstanceCreateStatus.Failed);
}

	        throw new InvalidParameterValueException("Please specify a size of at least 1 Gb.");
	    } else if (size > _maxVolumeSizeInGb) {
	        throw new InvalidParameterValueException("The maximum size allowed is " + _maxVolumeSizeInGb + " Gb.");
	    }

	    return true;
	}
	
	protected DiskProfile toDiskProfile(VolumeVO vol, DiskOfferingVO offering) {
	    return new DiskProfile(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.isRecreatable(), vol.getTemplateId());
	}
	
    @Override
    public  DiskProfile allocateRawVolume(VolumeType type, String name, DiskOfferingVO offering, Long size, T vm, AccountVO owner) {
        if (size == null) {
            size = offering.getDiskSizeInBytes();
        }
        VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size);
        if (vm != null) {
            vol.setInstanceId(vm.getId());
        }
        
        vol = _volsDao.persist(vol);
        
        return toDiskProfile(vol, offering);
    }
    
    @Override 
    public  DiskProfile allocateTemplatedVolume(VolumeType type, String name, DiskOfferingVO offering, VMTemplateVO template, T vm, AccountVO owner) {
        assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really....";
        
        SearchCriteria sc = HostTemplateStatesSearch.create();
        sc.setParameters("id", template.getId());
        sc.setParameters("state", com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
        sc.setJoinParameters("host", "dcId", vm.getDataCenterId());
        
        List sss = _vmTemplateHostDao.search(sc, null);
        if (sss.size() == 0) {
            throw new CloudRuntimeException("Template " + template.getName() + " has not been completely downloaded to zone " + vm.getDataCenterId());
        }
        VMTemplateHostVO ss = sss.get(0);
        
        VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), ss.getSize());
        if (vm != null) {
            vol.setInstanceId(vm.getId());
        }
        vol.setTemplateId(template.getId());
        
        vol = _volsDao.persist(vol);
        
        return toDiskProfile(vol, offering);
    }
    
    final protected DiskProfile createDiskCharacteristics(VolumeVO volume, DiskOfferingVO offering) {
        return new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), offering.getId(), volume.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.isRecreatable(), volume.getTemplateId());
    }
    
    final protected DiskProfile createDiskCharacteristics(VolumeVO volume) {
        DiskOfferingVO offering = _diskOfferingDao.findById(volume.getDiskOfferingId());
        return createDiskCharacteristics(volume, offering);
    }
    
    @Override
    public  void create(T vm) {
        List vols = _volsDao.findByInstance(vm.getId());
        assert vols.size() >= 1 : "Come on, what's with the zero volumes for " + vm;
        for (VolumeVO vol : vols) {
            DiskProfile dskCh = createDiskCharacteristics(vol);
            int retry = _retry;
            while (--retry >= 0) {
                
            }
        }
        /*
StoragePoolVO pool = null;
final HashSet avoidPools = new HashSet(avoids);

VolumeType volType = volume.getVolumeType();

VolumeTO created = null;
int retry = _retry;
while (--retry >= 0) {
created = null;

txn.start();

long podId = pod.getId();
pod = _podDao.lock(podId, true);
if (pod == null) {
volume.setPoolId(null);
volume.setDestroyed(true);
_volsDao.persist(volume);
throw new CloudRuntimeException("Unable to acquire lock on the pod " + podId);
}

pool = findStoragePool(dskCh, dc, pod, clusterId, offering, vm, template, avoidPools);
if (pool == null) {
txn.rollback();
break;
}

avoidPools.add(pool);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Trying to create " + volume + " on " + pool);
}

volume.setPoolId(pool.getId());
_volsDao.persist(volume);

txn.commit();

CreateCommand cmd = null;
VMTemplateStoragePoolVO tmpltStoredOn = null;
if (volume.getVolumeType() == VolumeType.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
tmpltStoredOn = _tmpltMgr.prepareTemplateForCreate(template, pool);
if (tmpltStoredOn == null) {
continue;
}
cmd = new CreateCommand(volume, vm, dskCh, tmpltStoredOn.getLocalDownloadPath(), pool);
} else {
cmd = new CreateCommand(volume, vm, dskCh, pool, size);
}

Answer answer = sendToPool(pool, cmd);
if (answer != null && answer.getResult()) {
created = ((CreateAnswer)answer).getVolume();
break;
_volsDao.persist(volume);

s_logger.debug("Retrying the create because it failed on pool " + pool);
}

if (created == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to create a volume for " + volume);
}
volume.setStatus(AsyncInstanceCreateStatus.Failed);
volume.setDestroyed(true);
_volsDao.persist(volume);

return null;
}

volume.setStatus(AsyncInstanceCreateStatus.Created);
volume.setFolder(pool.getPath());
volume.setPath(created.getPath());
volume.setSize(created.getSize());
volume.setPoolType(pool.getPoolType());
volume.setPodId(pod.getId());
_volsDao.persist(volume);
return volume;
    */
        
    }
}
File
StorageManagerImpl.java
Developer's decision
Combination
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
<<<<<<< HEAD
=======
import com.cloud.storage.Volume;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
Solution content
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.VolumeType;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
File
AbstractStoragePoolAllocator.java
Developer's decision
Version 2
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
<<<<<<< HEAD
import com.cloud.storage.Volume;
=======
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.download.DownloadState.DownloadEvent;
import com.cloud.utils.exception.CloudRuntimeException;
Solution content
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.download.DownloadState.DownloadEvent;
import com.cloud.utils.exception.CloudRuntimeException;
File
DownloadListener.java
Developer's decision
None
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
<<<<<<< HEAD
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Volume;
=======
import com.cloud.storage.Storage;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Storage.StoragePoolType;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.TemplateInfo;
Solution content
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.TemplateInfo;
File
LocalSecondaryStorageResource.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotScheduleVO;
import com.cloud.storage.SnapshotVO;
<<<<<<< HEAD
=======
import com.cloud.storage.VolumeVO;
import com.cloud.storage.Storage.ImageFormat;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.utils.component.Manager;
import com.cloud.utils.db.Filter;
Solution content
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotScheduleVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.utils.component.Manager;
import com.cloud.utils.db.Filter;
File
SnapshotManager.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
    void validateSnapshot(Long userId, SnapshotVO snapshot);

<<<<<<< HEAD
    boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd) throws InvalidParameterValueException;
=======
	ImageFormat getImageFormat(Long volumeId);

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    void validateSnapshot(Long userId, SnapshotVO snapshot);

    boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd) throws InvalidParameterValueException;
	ImageFormat getImageFormat(Long volumeId);
}
File
SnapshotManager.java
Developer's decision
Concatenation
Kind of conflict
Method interface
Chunk
Conflicting content
import java.net.URISyntaxException;
import java.util.List;

<<<<<<< HEAD
import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
import com.cloud.api.commands.DetachIsoCmd;
import com.cloud.api.commands.RegisterIsoCmd;
import com.cloud.api.commands.RegisterTemplateCmd;
=======
import com.cloud.async.AsyncJobManager;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
Solution content
import java.net.URISyntaxException;
import java.util.List;

import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
import com.cloud.api.commands.DetachIsoCmd;
import com.cloud.api.commands.ExtractIsoCmd;
import com.cloud.api.commands.ExtractTemplateCmd;
import com.cloud.api.commands.RegisterIsoCmd;
import com.cloud.api.commands.RegisterTemplateCmd;
import com.cloud.async.AsyncJobManager;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
File
TemplateManager.java
Developer's decision
Manual
Kind of conflict
Import
Chunk
Conflicting content
    void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO);
    
    boolean templateIsDeleteable(VMTemplateHostVO templateHostRef);
<<<<<<< HEAD
 
    /**
     * Deletes a template
     * @param cmd - the command specifying templateId
     */
    boolean deleteTemplate(DeleteTemplateCmd cmd) throws InvalidParameterValueException, InternalErrorException, PermissionDeniedException;
    
    /**
     * Deletes a template
     * @param cmd - the command specifying isoId
     * @return true if deletion is successful, false otherwise
     * @throws InvalidParameterValueException, InternalErrorException, PermissionDeniedException
     */
    boolean deleteIso(DeleteIsoCmd cmd) throws InvalidParameterValueException, InternalErrorException, PermissionDeniedException;
=======

	void extract(VMTemplateVO template, String url, VMTemplateHostVO tmpltHostRef, Long zoneId, long eventId, long asyncJobId, AsyncJobManager asyncMgr);
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    
}
Solution content
    void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO);
    
    boolean templateIsDeleteable(VMTemplateHostVO templateHostRef);
 
    /**
     * Deletes a template
     * @param cmd - the command specifying templateId
     */
    boolean deleteTemplate(DeleteTemplateCmd cmd) throws InvalidParameterValueException, InternalErrorException, PermissionDeniedException;
    
    /**
     * Deletes a template
     * @param cmd - the command specifying isoId
     * @return true if deletion is successful, false otherwise
     * @throws InvalidParameterValueException, InternalErrorException, PermissionDeniedException
     */
    boolean deleteIso(DeleteIsoCmd cmd) throws InvalidParameterValueException, InternalErrorException, PermissionDeniedException;

	void extract(VMTemplateVO template, String url, VMTemplateHostVO tmpltHostRef, Long zoneId, long eventId, long asyncJobId, AsyncJobManager asyncMgr);
    void extract(ExtractIsoCmd cmd) throws InvalidParameterValueException, PermissionDeniedException;
    void extract(ExtractTemplateCmd cmd) throws InvalidParameterValueException, PermissionDeniedException;
}
File
TemplateManager.java
Developer's decision
Manual
Kind of conflict
Comment
Method interface
Chunk
Conflicting content
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
<<<<<<< HEAD
import com.cloud.agent.manager.AgentManager;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
import com.cloud.api.commands.DetachIsoCmd;
import com.cloud.api.commands.RegisterIsoCmd;
import com.cloud.api.commands.RegisterTemplateCmd;
=======
import com.cloud.async.AsyncJobManager;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
Solution content
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.manager.AgentManager;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.AttachIsoCmd;
import com.cloud.api.commands.CopyIsoCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
import com.cloud.api.commands.DetachIsoCmd;
import com.cloud.api.commands.ExtractIsoCmd;
import com.cloud.api.commands.ExtractTemplateCmd;
import com.cloud.api.commands.RegisterIsoCmd;
import com.cloud.api.commands.RegisterTemplateCmd;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobVO;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
File
TemplateManagerImpl.java
Developer's decision
Manual
Kind of conflict
Import
Chunk
Conflicting content
    @Inject DomainDao _domainDao;
    long _routerTemplateId = -1;
    @Inject StorageManager _storageMgr;
<<<<<<< HEAD
    @Inject UserVmManager _vmMgr;
    @Inject ConfigurationDao _configDao;
    protected SearchBuilder HostTemplateStatesSearch;
=======
    protected SearchBuilder HostTemplateStatesSearch;	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    
    @Override
    public Long registerIso(RegisterIsoCmd cmd) throws InvalidParameterValueException, IllegalArgumentException, ResourceAllocationException{
Solution content
    @Inject DomainDao _domainDao;
    long _routerTemplateId = -1;
    @Inject StorageManager _storageMgr;
    @Inject UserVmManager _vmMgr;
    @Inject ConfigurationDao _configDao;
    protected SearchBuilder HostTemplateStatesSearch;
    
    @Override
    public Long registerIso(RegisterIsoCmd cmd) throws InvalidParameterValueException, IllegalArgumentException, ResourceAllocationException{
File
TemplateManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Attribute
Chunk
Conflicting content
	 * @throws InvalidParameterValueException
	 * @throws PermissionDeniedException
	 */
<<<<<<< HEAD
	List searchForLimits(ListResourceLimitsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException;

    /**
     * Updates an existing resource limit with the specified details. If a limit doesn't exist, will create one.
     * @param cmd the command that wraps the domainId, accountId, type, and max parameters
     * @return the updated/created resource limit
     * @throws InvalidParameterValueException
     */
	ResourceLimitVO updateResourceLimit(UpdateResourceLimitCmd cmd) throws InvalidParameterValueException;
=======
	public ResourceLimitVO updateResourceLimit(Long domainId, Long accountId, ResourceType type, Long max) throws InvalidParameterValueException;
	
	AccountVO getSystemAccount();
	
	
	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
	 * @throws InvalidParameterValueException
	 * @throws PermissionDeniedException
	 */
	List searchForLimits(ListResourceLimitsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException;

    /**
     * Updates an existing resource limit with the specified details. If a limit doesn't exist, will create one.
     * @param cmd the command that wraps the domainId, accountId, type, and max parameters
     * @return the updated/created resource limit
     * @throws InvalidParameterValueException
     */
	ResourceLimitVO updateResourceLimit(UpdateResourceLimitCmd cmd) throws InvalidParameterValueException;
	
	AccountVO getSystemAccount();
}
File
AccountManager.java
Developer's decision
Combination
Kind of conflict
Comment
Method interface
Chunk
Conflicting content
import org.apache.log4j.Logger;

<<<<<<< HEAD
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.ListResourceLimitsCmd;
import com.cloud.api.commands.UpdateResourceLimitCmd;
=======
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ResourceCountDao;
Solution content
import org.apache.log4j.Logger;

import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.ListResourceLimitsCmd;
import com.cloud.api.commands.UpdateResourceLimitCmd;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.ResourceLimitVO;
import com.cloud.configuration.dao.ResourceCountDao;
File
AccountManagerImpl.java
Developer's decision
Version 1
Kind of conflict
Import
Chunk
Conflicting content
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
<<<<<<< HEAD
import com.cloud.exception.PermissionDeniedException;
import com.cloud.server.Criteria;
import com.cloud.storage.dao.VMTemplateDao;
=======
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.Filter;
Solution content
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.server.Criteria;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.Filter;
File
AccountManagerImpl.java
Developer's decision
Combination
Kind of conflict
Import
Chunk
Conflicting content
            return _resourceLimitDao.persist(new ResourceLimitVO(domainId, accountId, resourceType, max));
        }
    }
<<<<<<< HEAD
=======
    
    @Override
    public AccountVO getSystemAccount() {
        return _systemAccount;
    }

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
            return _resourceLimitDao.persist(new ResourceLimitVO(domainId, accountId, resourceType, max));
        }
    }

    @Override
    public AccountVO getSystemAccount() {
        return _systemAccount;
    }
}
File
AccountManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
     * @throws InternalErrorException
     * @throws InvalidParameterValueException 
     */
<<<<<<< HEAD
    void detachVolumeFromVM(DetachVolumeCmd cmmd) throws InternalErrorException, InvalidParameterValueException;
=======
    void detachVolumeFromVM(long volumeId, long startEventId, long deviceId, long instanceId) throws InternalErrorException;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    
    /**
     * Attaches an ISO to the virtual CDROM device of the specified VM. Will eject any existing virtual CDROM if isoPath is null.
Solution content
     * @throws InternalErrorException
     * @throws InvalidParameterValueException 
     */
    void detachVolumeFromVM(DetachVolumeCmd cmmd) throws InternalErrorException, InvalidParameterValueException;
    
    /**
     * Attaches an ISO to the virtual CDROM device of the specified VM. Will eject any existing virtual CDROM if isoPath is null.
File
UserVmManager.java
Developer's decision
Version 1
Kind of conflict
Method interface
Chunk
Conflicting content
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VolumeDao;
<<<<<<< HEAD
import com.cloud.user.Account;
=======
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
Solution content
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
File
UserVmManagerImpl.java
Developer's decision
Concatenation
Kind of conflict
Import
Chunk
Conflicting content
    @Inject NetworkGroupManager _networkGroupManager;
    @Inject ServiceOfferingDao _serviceOfferingDao;
    @Inject EventDao _eventDao = null;
<<<<<<< HEAD
    
=======
    @Inject InstanceGroupDao _vmGroupDao;
    @Inject InstanceGroupVMMapDao _groupVMMapDao;

>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    private IpAddrAllocator _IpAllocator;
    ScheduledExecutorService _executor = null;
    int _expungeInterval;
Solution content
    @Inject NetworkGroupManager _networkGroupManager;
    @Inject ServiceOfferingDao _serviceOfferingDao;
    @Inject EventDao _eventDao = null;
    @Inject InstanceGroupDao _vmGroupDao;
    @Inject InstanceGroupVMMapDao _groupVMMapDao;

    private IpAddrAllocator _IpAllocator;
    ScheduledExecutorService _executor = null;
    int _expungeInterval;
File
UserVmManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Attribute
Chunk
Conflicting content
    }
    
    @Override
<<<<<<< HEAD
    public void detachVolumeFromVM(DetachVolumeCmd cmmd) throws InternalErrorException, InvalidParameterValueException {
    	
    	Account account = (Account) UserContext.current().getAccountObject();
    	Long volumeId = cmmd.getId();
=======
    public void detachVolumeFromVM(long volumeId, long startEventId, long deviceId, long instanceId) throws InternalErrorException {
    	VolumeVO volume = null;
    	
    	if(volumeId!=0)
    	{
    		volume = _volsDao.findById(volumeId);
    	}
    	else
    	{
    		volume = _volsDao.findByInstanceAndDeviceId(instanceId, deviceId).get(0);
    	}
    	
    	Long vmId = null;
    	
    	if(instanceId==0)
    	{
    		vmId = volume.getInstanceId();
    	}
    	else
    	{
    		vmId = instanceId;
    	}
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
    	
    	boolean isAdmin;
    	if (account == null) {
Solution content
    }
    
    @Override
    public void detachVolumeFromVM(DetachVolumeCmd cmmd) throws InternalErrorException, InvalidParameterValueException {    	
    	Account account = (Account) UserContext.current().getAccountObject();
    	if ((cmmd.getId() == null && cmmd.getDeviceId() == null && cmmd.getVirtualMachineId() == null) ||
    	    (cmmd.getId() != null && (cmmd.getDeviceId() != null || cmmd.getVirtualMachineId() != null)) ||
    	    (cmmd.getId() == null && (cmmd.getDeviceId()==null || cmmd.getVirtualMachineId() == null))) {
    	    throw new InvalidParameterValueException("Please provide either a volume id, or a tuple(device id, instance id)");
    	}

    	Long volumeId = cmmd.getId();
    	VolumeVO volume = null;
    	
    	if(volumeId != null) {
    		volume = _volsDao.findById(volumeId);
    	} else {
    		volume = _volsDao.findByInstanceAndDeviceId(cmmd.getVirtualMachineId(), cmmd.getDeviceId()).get(0);
    	}

    	Long vmId = null;
    	
    	if (cmmd.getVirtualMachineId() == null) {
    		vmId = volume.getInstanceId();
    	} else {
    		vmId = cmmd.getVirtualMachineId();
    	}

    	boolean isAdmin;
    	if (account == null) {
File
UserVmManagerImpl.java
Developer's decision
Manual
Kind of conflict
Cast expression
If statement
Method invocation
Method signature
Variable
Chunk
Conflicting content
    	}
    }
	
<<<<<<< HEAD
	private static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}
	
    @Override
    public void updateVirtualMachine(UpdateVMCmd cmd) 
    {

        String displayName = cmd.getDisplayName();
        String group = cmd.getGroup();
        Boolean ha = cmd.getHaEnable();
        Long id = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
    
        //Input validation
        UserVmVO vmInstance = null;
        
        // Verify input parameters
        try 
        {
        	vmInstance = _vmDao.findById(id.longValue());
        } 
        catch (Exception ex1) 
        {
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find virtual machine by id");
        }

        if (vmInstance == null) {
	public boolean rebootVirtualMachine(RebootVMCmd cmd) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find virtual machine with id " + id);
        }

        userId = accountAndUserValidation(id, account, userId,vmInstance);  
        
        if (group == null) {
    		group = vmInstance.getGroup();
    	}

    	if (displayName == null) {
    		displayName = vmInstance.getDisplayName();
    	}
    	
    	if (ha == null) {
    		ha = vmInstance.isHaEnabled();
    	}

    	long accountId = vmInstance.getAccountId();

        
        UserVmVO vm = _vmDao.findById(id);
        if (vm == null) {
            throw new CloudRuntimeException("Unable to find virual machine with id " + id);
        }

        boolean haEnabled = vm.isHaEnabled();
        _vmDao.updateVM(id, displayName, group, ha);
        if (haEnabled != ha) {
            String description = null;
            String type = null;
            if (ha) 
            {
                description = "Successfully enabled HA for virtual machine " + vm.getName();
                type = EventTypes.EVENT_VM_ENABLE_HA;
            } 
            else 
            {
                description = "Successfully disabled HA for virtual machine " + vm.getName();
                type = EventTypes.EVENT_VM_DISABLE_HA;
            }
            // create a event for the change in HA Enabled flag
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, type, description, null);
        }
    }

	@Override
	public boolean stopVirtualMachine(StopVMCmd cmd) throws ServerApiException{
		
		//Input validation
		Account account = (Account)UserContext.current().getAccountObject();
		Long userId = UserContext.current().getUserId();
		Long id = cmd.getId();
		
        //if account is removed, return error
        if(account!=null && account.getRemoved() != null)
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account " + account.getId()+" is removed");
        		
        UserVmVO vmInstance = _vmDao.findById(id.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + id);
        }
        
        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_STOP, "stopping Vm with Id: "+id);
        
        userId = accountAndUserValidation(id, account, userId, vmInstance);
   
        return stopVirtualMachine(userId, id, eventId);
	}

	@Override
	public UserVmVO startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, ExecutionException, ConcurrentOperationException {
		//Input validation
		Account account = (Account)UserContext.current().getAccountObject();
		Long userId = UserContext.current().getUserId();
		Long id = cmd.getId();
		
        //if account is removed, return error
        if(account!=null && account.getRemoved() != null)
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account " + account.getId()+" is removed");
        		
        UserVmVO vmInstance = _vmDao.findById(id.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + id);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_START, "Starting Vm with Id: "+id);
        
        userId = accountAndUserValidation(id, account, userId, vmInstance);
        
        return startVirtualMachine(userId, id, null, null, eventId);
		
	}

	@Override
        Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long vmId = cmd.getId();
        
        //Verify input parameters
        UserVmVO vmInstance = _vmDao.findById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        userId = accountAndUserValidation(vmId, account, userId, vmInstance);
        
        EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Rebooting Vm with Id: "+vmId);
        
        boolean status = rebootVirtualMachine(userId, vmId);
        
        if(status)
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Successfully rebooted vm with id:"+vmId);
        	return status;
        }
        else
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Failed to reboot vm with id:"+vmId);
        	return status;
        }
	}

	@Override
	public boolean destroyVm(DestroyVMCmd cmd) {
	
        Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long vmId = cmd.getId();
        
        //Verify input parameters
        UserVmVO vmInstance = _vmDao.findById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        userId = accountAndUserValidation(vmId, account, userId, vmInstance);
        
        EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_DESTROY, "Destroying Vm with Id: "+vmId);
        
        boolean status = destroyVirtualMachine(userId, vmId);
        
        if(status)
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_DESTROY, "Successfully destroyed vm with id:"+vmId);
        	return status;
        }
        else
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_DESTROY, "Failed to destroy vm with id:"+vmId);
        	return status;
        }
	}
	
	
=======
	@DB
	@Override
	public InstanceGroupVO createVmGroup(String name, Long accountId) {
		final Transaction txn = Transaction.currentTxn();
		AccountVO account = null;
		txn.start();
		try {
			account = _accountDao.acquire(accountId); //to ensure duplicate vm group names are not created.
			if (account == null) {
				s_logger.warn("Failed to acquire lock on account");
				return null;
			}
			InstanceGroupVO group = _vmGroupDao.findByAccountAndName(accountId, name);
			if (group == null){
				group = new InstanceGroupVO(name, accountId);
				group =  _vmGroupDao.persist(group);
			}
			return group;
		} finally {
			if (account != null) {
				_accountDao.release(accountId);
			}
			txn.commit();
		}
    }
	
    @Override
    public boolean deleteVmGroup(long groupId){
    	
    	//delete all the mappings from group_vm_map table
        List groupVmMaps = _groupVMMapDao.listByGroupId(groupId);
        for (InstanceGroupVMMapVO groupMap : groupVmMaps) {
	        SearchCriteria sc = _groupVMMapDao.createSearchCriteria();
	        sc.addAnd("instanceId", SearchCriteria.Op.EQ, groupMap.getInstanceId());
	        _groupVMMapDao.expunge(sc);
        }
    	
    	if (_vmGroupDao.remove(groupId)) {
    		return true;
    	} else {
    		return false;
    	}
    }
    
	@Override
	@DB
	public boolean addInstanceToGroup(long userVmId, String groupName) {
		
		UserVmVO vm = _vmDao.findById(userVmId);
		
        InstanceGroupVO group = _vmGroupDao.findByAccountAndName(vm.getAccountId(), groupName);
    	//Create vm group if the group doesn't exist for this account
        if (group == null) {
        	group = createVmGroup(groupName, vm.getAccountId());
        }
		
		if (group != null) {
			final Transaction txn = Transaction.currentTxn();
			txn.start();
			UserVm userVm = _vmDao.acquire(userVmId);
			if (userVm == null) {
				s_logger.warn("Failed to acquire lock on user vm id=" + userVmId);
			}
			try {
				//don't let the group be deleted when we are assigning vm to it.
				InstanceGroupVO ngrpLock = _vmGroupDao.lock(group.getId(), false);
				if (ngrpLock == null) {
					s_logger.warn("Failed to acquire lock on vm group id=" + group.getId() + " name=" + group.getName());
					txn.rollback();
					return false;
				}
				
				//Currently don't allow to assign a vm to more than one group
				if (_groupVMMapDao.listByInstanceId(userVmId) != null) {
					//Delete all mappings from group_vm_map table
			        List groupVmMaps = _groupVMMapDao.listByInstanceId(userVmId);
			        for (InstanceGroupVMMapVO groupMap : groupVmMaps) {
				        SearchCriteria sc = _groupVMMapDao.createSearchCriteria();
				        sc.addAnd("instanceId", SearchCriteria.Op.EQ, groupMap.getInstanceId());
				        _groupVMMapDao.expunge(sc);
			        }
				}
				InstanceGroupVMMapVO groupVmMapVO = new InstanceGroupVMMapVO(group.getId(), userVmId);
				_groupVMMapDao.persist(groupVmMapVO);
				
				txn.commit();
				return true;
			} finally {
				if (userVm != null) {
					_vmDao.release(userVmId);
				}
			}
	    }
		return false;
	}
	
	@Override
	public InstanceGroupVO getGroupForVm(long vmId) {
		//TODO - in future releases vm can be assigned to multiple groups; but currently return just one group per vm
		try {
			List groupsToVmMap =  _groupVMMapDao.listByInstanceId(vmId);

            if(groupsToVmMap != null && groupsToVmMap.size() != 0){
            	InstanceGroupVO group = _vmGroupDao.findById(groupsToVmMap.get(0).getGroupId());
            	return group;
            } else {
            	return null;
            }
		}
		catch (Exception e){
			s_logger.warn("Error trying to get group for a vm: "+e);
			return null;
		}
	}
	
	public void removeInstanceFromGroup(long vmId) {
		try {
			List groupVmMaps = _groupVMMapDao.listByInstanceId(vmId);
	        for (InstanceGroupVMMapVO groupMap : groupVmMaps) {
		        SearchCriteria sc = _groupVMMapDao.createSearchCriteria();
		        sc.addAnd("instanceId", SearchCriteria.Op.EQ, groupMap.getInstanceId());
		        _groupVMMapDao.expunge(sc);
	        }
		} catch (Exception e){
			s_logger.warn("Error trying to remove vm from group: "+e);
		}
	}
	
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
        _vmDao.updateVM(id, displayName, ha);
    	}
    }

	private static boolean isAdmin(short accountType) {
	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
	            (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
	}
	
    @Override
    public void updateVirtualMachine(UpdateVMCmd cmd) {
        String displayName = cmd.getDisplayName();
        Boolean ha = cmd.getHaEnable();
        Long id = cmd.getId();
        Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
    
        //Input validation
        UserVmVO vmInstance = null;
        
        // Verify input parameters
        try 
        {
        	vmInstance = _vmDao.findById(id.longValue());
        } 
        catch (Exception ex1) 
        {
        	throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "unable to find virtual machine by id");
        }

        if (vmInstance == null) {
            throw new ServerApiException(BaseCmd.PARAM_ERROR, "unable to find virtual machine with id " + id);
        }

        userId = accountAndUserValidation(id, account, userId,vmInstance);  

    	if (displayName == null) {
    		displayName = vmInstance.getDisplayName();
    	}
    	
    	if (ha == null) {
    		ha = vmInstance.isHaEnabled();
    	}

    	long accountId = vmInstance.getAccountId();
        UserVmVO vm = _vmDao.findById(id);
        if (vm == null) {
            throw new CloudRuntimeException("Unable to find virual machine with id " + id);
        }

        boolean haEnabled = vm.isHaEnabled();
        if (haEnabled != ha) {
            String description = null;
            String type = null;
            if (ha) {
                description = "Successfully enabled HA for virtual machine " + vm.getName();
                type = EventTypes.EVENT_VM_ENABLE_HA;
            } else {
                description = "Successfully disabled HA for virtual machine " + vm.getName();
                type = EventTypes.EVENT_VM_DISABLE_HA;
            }
            // create a event for the change in HA Enabled flag
            EventUtils.saveEvent(userId, accountId, EventVO.LEVEL_INFO, type, description, null);
        }
    }

	@Override
	public boolean stopVirtualMachine(StopVMCmd cmd) throws ServerApiException{
		
		//Input validation
		Account account = (Account)UserContext.current().getAccountObject();
		Long userId = UserContext.current().getUserId();
		Long id = cmd.getId();
		
        //if account is removed, return error
        if(account!=null && account.getRemoved() != null)
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account " + account.getId()+" is removed");
        		
        UserVmVO vmInstance = _vmDao.findById(id.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + id);
        }
        
        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_STOP, "stopping Vm with Id: "+id);
        
        userId = accountAndUserValidation(id, account, userId, vmInstance);
   
        return stopVirtualMachine(userId, id, eventId);
	}

	@Override
	public UserVmVO startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, ExecutionException, ConcurrentOperationException {
		//Input validation
		Account account = (Account)UserContext.current().getAccountObject();
		Long userId = UserContext.current().getUserId();
		Long id = cmd.getId();
		
        //if account is removed, return error
        if(account!=null && account.getRemoved() != null)
        	throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "The account " + account.getId()+" is removed");
        		
        UserVmVO vmInstance = _vmDao.findById(id.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + id);
        }

        long eventId = EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_START, "Starting Vm with Id: "+id);
        
        userId = accountAndUserValidation(id, account, userId, vmInstance);
        
        return startVirtualMachine(userId, id, null, null, eventId);
		
	}

	@Override
	public boolean rebootVirtualMachine(RebootVMCmd cmd) {
        Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long vmId = cmd.getId();
        
        //Verify input parameters
        UserVmVO vmInstance = _vmDao.findById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        userId = accountAndUserValidation(vmId, account, userId, vmInstance);
        
        EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Rebooting Vm with Id: "+vmId);
        
        boolean status = rebootVirtualMachine(userId, vmId);
        
        if(status)
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Successfully rebooted vm with id:"+vmId);
        	return status;
        }
        else
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Failed to reboot vm with id:"+vmId);
        	return status;
        }
	}

	@Override
	public boolean destroyVm(DestroyVMCmd cmd) {
	
        Account account = (Account)UserContext.current().getAccountObject();
        Long userId = UserContext.current().getUserId();
        Long vmId = cmd.getId();
        
        //Verify input parameters
        UserVmVO vmInstance = _vmDao.findById(vmId.longValue());
        if (vmInstance == null) {
        	throw new ServerApiException(BaseCmd.VM_INVALID_PARAM_ERROR, "unable to find a virtual machine with id " + vmId);
        }

        userId = accountAndUserValidation(vmId, account, userId, vmInstance);
        
        EventUtils.saveScheduledEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_DESTROY, "Destroying Vm with Id: "+vmId);
        
        boolean status = destroyVirtualMachine(userId, vmId);
        
        if(status)
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_DESTROY, "Successfully destroyed vm with id:"+vmId);
        	return status;
        }
        else
        {
        	EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_DESTROY, "Failed to destroy vm with id:"+vmId);
        	return status;
        }
	}

    @Override @DB
    public InstanceGroupVO createVmGroup(CreateVMGroupCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long domainId = cmd.getDomainId();
        String accountName = cmd.getAccountName();
        Long accountId = null;
        String groupName = cmd.getGroupName();

        if (account != null) {
            if (isAdmin(account.getType())) {
                if ((domainId != null) && (accountName != null)) {
                    if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
                        throw new PermissionDeniedException("Unable to create vm group in domain " + domainId + ", permission denied.");
                    }

                    Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
                    if (userAccount != null) {
                        accountId = userAccount.getId();
                    } else {
                        throw new InvalidParameterValueException("Failed to create vm group " + groupName + ", unable to find account " + accountName + " in domain " + domainId);
                    }
                } else {
                    // the admin must be creating the vm group
                    accountId = account.getId();
                }
            } else {
                accountId = account.getId();
            }
        }

        if (accountId == null) {
            throw new InvalidParameterValueException("Failed to create vm group " + groupName + ", unable to find account for which to create a group.");
        }

        //Check if name is already in use by this account
        boolean isNameInUse = _vmGroupDao.isNameInUse(accountId, groupName);

        if (isNameInUse) {
            throw new InvalidParameterValueException("Unable to create vm group, a group with name " + groupName + " already exisits for account " + accountId);
        }

        return createVmGroup(groupName, accountId);
    }

    @DB
	private InstanceGroupVO createVmGroup(String groupName, long accountId) {
        Account account = null;
	    final Transaction txn = Transaction.currentTxn();
		txn.start();
		try {
			account = _accountDao.acquire(accountId); //to ensure duplicate vm group names are not created.
			if (account == null) {
				s_logger.warn("Failed to acquire lock on account");
				return null;
			}
			InstanceGroupVO group = _vmGroupDao.findByAccountAndName(accountId, groupName);
			if (group == null){
				group = new InstanceGroupVO(groupName, accountId);
				group =  _vmGroupDao.persist(group);
			}
			return group;
		} finally {
			if (account != null) {
				_accountDao.release(accountId);
			}
			txn.commit();
		}
    }

    @Override
    public boolean deleteVmGroup(DeleteVMGroupCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
        Account account = (Account)UserContext.current().getAccountObject();
        Long groupId = cmd.getId();

        // Verify input parameters
        InstanceGroupVO group = _vmGroupDao.findById(groupId);
        if ((group == null) || (group.getRemoved() != null)) {
            throw new InvalidParameterValueException("unable to find a vm group with id " + groupId);
        }

        if (account != null) {
            Account tempAccount = _accountDao.findById(group.getAccountId());
            if (!isAdmin(account.getType()) && (account.getId() != group.getAccountId())) {
                throw new PermissionDeniedException("unable to find a group with id " + groupId);
            } else if (!_domainDao.isChildDomain(account.getDomainId(), tempAccount.getDomainId())) {
                throw new PermissionDeniedException("Invalid group id (" + groupId + ") given, unable to update the group.");
            }
        }

        return deleteVmGroup(groupId);
    }

    @Override
    public boolean deleteVmGroup(long groupId) {    	
    	//delete all the mappings from group_vm_map table
        List groupVmMaps = _groupVMMapDao.listByGroupId(groupId);
        for (InstanceGroupVMMapVO groupMap : groupVmMaps) {
	        SearchCriteria sc = _groupVMMapDao.createSearchCriteria();
	        sc.addAnd("instanceId", SearchCriteria.Op.EQ, groupMap.getInstanceId());
	        _groupVMMapDao.expunge(sc);
        }
    	
    	if (_vmGroupDao.remove(groupId)) {
    		return true;
    	} else {
    		return false;
    	}
    }

	@Override @DB
	public boolean addInstanceToGroup(long userVmId, String groupName) {		
		UserVmVO vm = _vmDao.findById(userVmId);

        InstanceGroupVO group = _vmGroupDao.findByAccountAndName(vm.getAccountId(), groupName);
    	//Create vm group if the group doesn't exist for this account
        if (group == null) {
        	group = createVmGroup(groupName, vm.getAccountId());
        }

		if (group != null) {
			final Transaction txn = Transaction.currentTxn();
			txn.start();
			UserVm userVm = _vmDao.acquire(userVmId);
			if (userVm == null) {
				s_logger.warn("Failed to acquire lock on user vm id=" + userVmId);
			}
			try {
				//don't let the group be deleted when we are assigning vm to it.
				InstanceGroupVO ngrpLock = _vmGroupDao.lock(group.getId(), false);
				if (ngrpLock == null) {
					s_logger.warn("Failed to acquire lock on vm group id=" + group.getId() + " name=" + group.getName());
					txn.rollback();
					return false;
				}
				
				//Currently don't allow to assign a vm to more than one group
				if (_groupVMMapDao.listByInstanceId(userVmId) != null) {
					//Delete all mappings from group_vm_map table
			        List groupVmMaps = _groupVMMapDao.listByInstanceId(userVmId);
			        for (InstanceGroupVMMapVO groupMap : groupVmMaps) {
				        SearchCriteria sc = _groupVMMapDao.createSearchCriteria();
				        sc.addAnd("instanceId", SearchCriteria.Op.EQ, groupMap.getInstanceId());
				        _groupVMMapDao.expunge(sc);
			        }
				}
				InstanceGroupVMMapVO groupVmMapVO = new InstanceGroupVMMapVO(group.getId(), userVmId);
				_groupVMMapDao.persist(groupVmMapVO);
				
				txn.commit();
				return true;
			} finally {
				if (userVm != null) {
					_vmDao.release(userVmId);
				}
			}
	    }
		return false;
	}
	
	@Override
	public InstanceGroupVO getGroupForVm(long vmId) {
		//TODO - in future releases vm can be assigned to multiple groups; but currently return just one group per vm
		try {
			List groupsToVmMap =  _groupVMMapDao.listByInstanceId(vmId);

            if(groupsToVmMap != null && groupsToVmMap.size() != 0){
            	InstanceGroupVO group = _vmGroupDao.findById(groupsToVmMap.get(0).getGroupId());
            	return group;
            } else {
            	return null;
            }
		}
		catch (Exception e){
			s_logger.warn("Error trying to get group for a vm: "+e);
			return null;
		}
	}
	
	public void removeInstanceFromGroup(long vmId) {
		try {
			List groupVmMaps = _groupVMMapDao.listByInstanceId(vmId);
	        for (InstanceGroupVMMapVO groupMap : groupVmMaps) {
		        SearchCriteria sc = _groupVMMapDao.createSearchCriteria();
		        sc.addAnd("instanceId", SearchCriteria.Op.EQ, groupMap.getInstanceId());
		        _groupVMMapDao.expunge(sc);
	        }
		} catch (Exception e){
			s_logger.warn("Error trying to remove vm from group: "+e);
		}
	}
}
File
UserVmManagerImpl.java
Developer's decision
Manual
Kind of conflict
Annotation
Method declaration
Chunk
Conflicting content
    public static final long OperationTimedoutException = Base | 0x18;
    public static final long StorageUnavailableException = Base | 0x19;
    public static final long InfficientVirtualNetworkCapacityException = Base | 0x1a;
<<<<<<< HEAD
    public static final long DiscoveryException = Base | 0x1b;
    public static final long CloudAuthenticationException = Base | 0x1c;
    public static final long AsyncCommandQueued = Base | 0x1d;
=======
    public static final long DiscoveryException = Base | 0x1b;
    public static final long ConflictingNetworkSettingException = Base | 0x1c;
>>>>>>> 9228088ce371c22211fbc77683abe1ffae3e7590
}
Solution content
    public static final long OperationTimedoutException = Base | 0x18;
    public static final long StorageUnavailableException = Base | 0x19;
    public static final long InfficientVirtualNetworkCapacityException = Base | 0x1a;
    public static final long DiscoveryException = Base | 0x1b;
    public static final long ConflictingNetworkSettingException = Base | 0x1c;
    public static final long CloudAuthenticationException = Base | 0x1d;
    public static final long AsyncCommandQueued = Base | 0x1e;
}
File
SerialVersionUID.java
Developer's decision
Manual
Kind of conflict
Attribute