Projects >> CloudStack-archive >>e5ed6cd26477f8632f452302e6ab4c53fd51881d

Chunk
Conflicting content
<<<<<<< HEAD
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.api;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import com.cloud.acl.ControlledEntity;
import com.cloud.acl.ControlledEntity.ACLType;
import com.cloud.api.ApiConstants.HostDetails;
import com.cloud.api.ApiConstants.VMDetails;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.response.AccountResponse;
import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.api.response.AsyncJobResponse;
import com.cloud.api.response.AutoScalePolicyResponse;
import com.cloud.api.response.AutoScaleVmGroupResponse;
import com.cloud.api.response.AutoScaleVmProfileResponse;
import com.cloud.api.response.CapabilityResponse;
import com.cloud.api.response.CapacityResponse;
import com.cloud.api.response.ClusterResponse;
import com.cloud.api.response.ConditionResponse;
import com.cloud.api.response.ConfigurationResponse;
import com.cloud.api.response.ControlledEntityResponse;
import com.cloud.api.response.CounterResponse;
import com.cloud.api.response.CreateCmdResponse;
import com.cloud.api.response.DiskOfferingResponse;
import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.DomainRouterResponse;
import com.cloud.api.response.EventResponse;
import com.cloud.api.response.ExtractResponse;
import com.cloud.api.response.FirewallResponse;
import com.cloud.api.response.FirewallRuleResponse;
import com.cloud.api.response.HostResponse;
import com.cloud.api.response.HypervisorCapabilitiesResponse;
import com.cloud.api.response.IPAddressResponse;
import com.cloud.api.response.InstanceGroupResponse;
import com.cloud.api.response.IpForwardingRuleResponse;
import com.cloud.api.response.LBStickinessPolicyResponse;
import com.cloud.api.response.LBStickinessResponse;
import com.cloud.api.response.LDAPConfigResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.LoadBalancerResponse;
import com.cloud.api.response.NetworkACLResponse;
import com.cloud.api.response.NetworkOfferingResponse;
import com.cloud.api.response.NetworkResponse;
import com.cloud.api.response.NicResponse;
import com.cloud.api.response.PhysicalNetworkResponse;
import com.cloud.api.response.PodResponse;
    }
import com.cloud.api.response.PrivateGatewayResponse;
import com.cloud.api.response.ProjectAccountResponse;
import com.cloud.api.response.ProjectInvitationResponse;
import com.cloud.api.response.ProjectResponse;
import com.cloud.api.response.ProviderResponse;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.api.response.ResourceCountResponse;
import com.cloud.api.response.ResourceLimitResponse;
import com.cloud.api.response.ResourceTagResponse;
import com.cloud.api.response.SecurityGroupResponse;
import com.cloud.api.response.SecurityGroupResultObject;
import com.cloud.api.response.SecurityGroupRuleResponse;
import com.cloud.api.response.SecurityGroupRuleResultObject;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.api.response.ServiceResponse;
import com.cloud.api.response.Site2SiteCustomerGatewayResponse;
import com.cloud.api.response.Site2SiteVpnConnectionResponse;
import com.cloud.api.response.Site2SiteVpnGatewayResponse;
import com.cloud.api.response.SnapshotPolicyResponse;
import com.cloud.api.response.SnapshotResponse;
import com.cloud.api.response.StaticRouteResponse;
import com.cloud.api.response.StorageNetworkIpRangeResponse;
import com.cloud.api.response.StoragePoolResponse;
import com.cloud.api.response.SwiftResponse;
import com.cloud.api.response.SystemVmInstanceResponse;
import com.cloud.api.response.SystemVmResponse;
import com.cloud.api.response.TemplatePermissionsResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.api.response.TrafficTypeResponse;
import com.cloud.api.response.UserResponse;
import com.cloud.api.response.UserVmResponse;
import com.cloud.api.response.VirtualRouterProviderResponse;
import com.cloud.api.response.VlanIpRangeResponse;
import com.cloud.api.response.VolumeResponse;
import com.cloud.api.response.VpcOfferingResponse;
import com.cloud.api.response.VpcResponse;
import com.cloud.api.response.VpnUsersResponse;
import com.cloud.api.response.ZoneResponse;
import com.cloud.async.AsyncJob;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
import com.cloud.configuration.Configuration;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.configuration.Resource.ResourceOwnerType;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimit;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.Pod;
import com.cloud.dc.StorageNetworkIpRange;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.domain.Domain;
import com.cloud.event.Event;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.HostStats;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.HypervisorCapabilities;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkProfile;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.Site2SiteCustomerGateway;
import com.cloud.network.Site2SiteCustomerGatewayVO;
import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.Site2SiteVpnGateway;
import com.cloud.network.Site2SiteVpnGatewayVO;
import com.cloud.network.VirtualRouterProvider;
import com.cloud.network.VpnUser;
import com.cloud.network.as.AutoScalePolicy;
import com.cloud.network.as.AutoScaleVmGroup;
import com.cloud.network.as.AutoScaleVmProfile;
import com.cloud.network.as.Condition;
import com.cloud.network.as.ConditionVO;
import com.cloud.network.as.Counter;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNatRule;
import com.cloud.network.rules.StickinessPolicy;
import com.cloud.network.security.SecurityGroup;
import com.cloud.network.security.SecurityGroupRules;
import com.cloud.network.security.SecurityGroupVO;
import com.cloud.network.security.SecurityRule;
import com.cloud.network.security.SecurityRule.SecurityRuleType;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.StaticRoute;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectAccount;
import com.cloud.projects.ProjectInvitation;
import com.cloud.server.Criteria;
import com.cloud.server.ResourceTag;
import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Swift;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateSwiftVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.test.PodZoneConfig;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.InstanceGroup;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VmStats;
import com.cloud.vm.dao.UserVmData;
import com.cloud.vm.dao.UserVmData.NicData;
import com.cloud.vm.dao.UserVmData.SecurityGroupData;

public class ApiResponseHelper implements ResponseGenerator {

    public final Logger s_logger = Logger.getLogger(ApiResponseHelper.class);
    private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##");

    @Override
    public UserResponse createUserResponse(User user) {
        UserResponse userResponse = new UserResponse();
        Account account = ApiDBUtils.findAccountById(user.getAccountId());
        userResponse.setAccountName(account.getAccountName());
        userResponse.setAccountType(account.getType());
        userResponse.setCreated(user.getCreated());
        userResponse.setDomainId(account.getDomainId());
        userResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());
        userResponse.setEmail(user.getEmail());
        userResponse.setFirstname(user.getFirstname());
        userResponse.setId(user.getId());
        userResponse.setLastname(user.getLastname());
        userResponse.setState(user.getState().toString());
        userResponse.setTimezone(user.getTimezone());
        userResponse.setUsername(user.getUsername());
        userResponse.setApiKey(user.getApiKey());
        userResponse.setSecretKey(user.getSecretKey());
        userResponse.setObjectName("user");

        return userResponse;
    }

    // this method is used for response generation via createAccount (which creates an account + user)
    @Override
    public AccountResponse createUserAccountResponse(UserAccount user) {
        return createAccountResponse(ApiDBUtils.findAccountById(user.getAccountId()));
    }

    @Override
    public AccountResponse createAccountResponse(Account account) {
        boolean accountIsAdmin = (account.getType() == Account.ACCOUNT_TYPE_ADMIN);
        AccountResponse accountResponse = new AccountResponse();
        accountResponse.setId(account.getId());
        accountResponse.setName(account.getAccountName());
        accountResponse.setAccountType(account.getType());
        accountResponse.setDomainId(account.getDomainId());
        accountResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());
        accountResponse.setState(account.getState().toString());
        accountResponse.setNetworkDomain(account.getNetworkDomain());
        accountResponse.setDefaultZone(account.getDefaultZoneId());

        // get network stat
        List stats = ApiDBUtils.listUserStatsBy(account.getId());
        if (stats == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching for user stats");
        }

        Long bytesSent = 0L;
        Long bytesReceived = 0L;
        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);
        }
        accountResponse.setBytesReceived(bytesReceived);
        accountResponse.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);
        accountResponse.setVmLimit(vmLimitDisplay);
        accountResponse.setVmTotal(vmTotal);
        accountResponse.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());

        Long ips = ipLimit - ipTotal;
        // check how many free ips are left, and if it's less than max allowed number of ips from account - use this
        // value
        Long ipsLeft = ApiDBUtils.countFreePublicIps();
        boolean unlimited = true;
        if (ips.longValue() > ipsLeft.longValue()) {
            ips = ipsLeft;
            unlimited = false;
        }

        String ipAvail = ((accountIsAdmin || ipLimit == -1) && unlimited) ? "Unlimited" : String.valueOf(ips);

        accountResponse.setIpLimit(ipLimitDisplay);
        accountResponse.setIpTotal(ipTotal);
        accountResponse.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);
        accountResponse.setVolumeLimit(volumeLimitDisplay);
        accountResponse.setVolumeTotal(volumeTotal);

        accountResponse.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);
        accountResponse.setSnapshotLimit(snapshotLimitDisplay);
        accountResponse.setSnapshotTotal(snapshotTotal);
        accountResponse.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);
        accountResponse.setTemplateLimit(templateLimitDisplay);
        accountResponse.setTemplateTotal(templateTotal);
        accountResponse.setTemplateAvailable(templateAvail);

        // Get stopped and running VMs
        int vmStopped = 0;
        int vmRunning = 0;

        List permittedAccounts = new ArrayList();
        permittedAccounts.add(account.getId());

        List virtualMachines = ApiDBUtils.searchForUserVMs(new Criteria(), permittedAccounts);

        // 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++;
            }
        }

        accountResponse.setVmStopped(vmStopped);
        accountResponse.setVmRunning(vmRunning);
        accountResponse.setObjectName("account");


        //get resource limits for projects
        Long projectLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.project, account.getId());
        String projectLimitDisplay = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit);
        Long projectTotal = ApiDBUtils.getResourceCount(ResourceType.project, account.getId());
        String projectAvail = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit - projectTotal);
        accountResponse.setProjectLimit(projectLimitDisplay);
        accountResponse.setProjectTotal(projectTotal);
        accountResponse.setProjectAvailable(projectAvail);

        //get resource limits for networks
        Long networkLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.network, account.getId());
        String networkLimitDisplay = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit);
        Long networkTotal = ApiDBUtils.getResourceCount(ResourceType.network, account.getId());
        String networkAvail = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit - networkTotal);
        accountResponse.setNetworkLimit(networkLimitDisplay);
        accountResponse.setNetworkTotal(networkTotal);
        accountResponse.setNetworkAvailable(networkAvail);

        // adding all the users for an account as part of the response obj
        List usersForAccount = ApiDBUtils.listUsersByAccount(account.getAccountId());
        List userResponseList = new ArrayList();
        for (UserVO user : usersForAccount) {
            UserResponse userResponse = createUserResponse(user);
            userResponseList.add(userResponse);
        }

        accountResponse.setUsers(userResponseList);
        accountResponse.setDetails(ApiDBUtils.getAccountDetails(account.getId()));
        return accountResponse;
    }

    @Override
    public UserResponse createUserResponse(UserAccount user) {
        UserResponse userResponse = new UserResponse();
        userResponse.setAccountName(user.getAccountName());
        userResponse.setAccountType(user.getType());
        userResponse.setCreated(user.getCreated());
        userResponse.setDomainId(user.getDomainId());
        userResponse.setDomainName(ApiDBUtils.findDomainById(user.getDomainId()).getName());
        userResponse.setEmail(user.getEmail());
        userResponse.setFirstname(user.getFirstname());
        userResponse.setId(user.getId());
        userResponse.setLastname(user.getLastname());
        userResponse.setState(user.getState());
        userResponse.setTimezone(user.getTimezone());
        userResponse.setUsername(user.getUsername());
        userResponse.setApiKey(user.getApiKey());
        userResponse.setSecretKey(user.getSecretKey());
        userResponse.setAccountId((user.getAccountId()));
        userResponse.setObjectName("user");

        return userResponse;
    }

    @Override
    public DomainResponse createDomainResponse(Domain domain) {
        DomainResponse domainResponse = new DomainResponse();
        domainResponse.setDomainName(domain.getName());
        domainResponse.setId(domain.getId());
        domainResponse.setLevel(domain.getLevel());
        domainResponse.setNetworkDomain(domain.getNetworkDomain());
        domainResponse.setParentDomainId(domain.getParent());
        StringBuilder domainPath = new StringBuilder("ROOT");
        (domainPath.append(domain.getPath())).deleteCharAt(domainPath.length() - 1);
        domainResponse.setPath(domainPath.toString());
        if (domain.getParent() != null) {
            domainResponse.setParentDomainName(ApiDBUtils.findDomainById(domain.getParent()).getName());
        }
        if (domain.getChildCount() > 0) {
            domainResponse.setHasChild(true);
        }
        domainResponse.setObjectName("domain");
        return domainResponse;
    }

    @Override
    public DiskOfferingResponse createDiskOfferingResponse(DiskOffering offering) {
        DiskOfferingResponse diskOfferingResponse = new DiskOfferingResponse();
        diskOfferingResponse.setId(offering.getId());
        diskOfferingResponse.setName(offering.getName());
        diskOfferingResponse.setDisplayText(offering.getDisplayText());
        diskOfferingResponse.setCreated(offering.getCreated());
        diskOfferingResponse.setDiskSize(offering.getDiskSize() / (1024 * 1024 * 1024));
        if (offering.getDomainId() != null) {
            diskOfferingResponse.setDomain(ApiDBUtils.findDomainById(offering.getDomainId()).getName());
            diskOfferingResponse.setDomainId(offering.getDomainId());
        }
        diskOfferingResponse.setTags(offering.getTags());
        diskOfferingResponse.setCustomized(offering.isCustomized());
        diskOfferingResponse.setObjectName("diskoffering");
        return diskOfferingResponse;
    }

    @Override
    public ResourceLimitResponse createResourceLimitResponse(ResourceLimit limit) {
        ResourceLimitResponse resourceLimitResponse = new ResourceLimitResponse();
        if (limit.getResourceOwnerType() == ResourceOwnerType.Domain) {
            populateDomain(resourceLimitResponse, limit.getOwnerId());
        } else if (limit.getResourceOwnerType() == ResourceOwnerType.Account) {
            Account accountTemp = ApiDBUtils.findAccountById(limit.getOwnerId());
            populateAccount(resourceLimitResponse, limit.getOwnerId());
            populateDomain(resourceLimitResponse, accountTemp.getDomainId());
        }
        resourceLimitResponse.setResourceType(Integer.valueOf(limit.getType().getOrdinal()).toString());
        resourceLimitResponse.setMax(limit.getMax());
        resourceLimitResponse.setObjectName("resourcelimit");

        return resourceLimitResponse;
    }

    @Override
    public ResourceCountResponse createResourceCountResponse(ResourceCount resourceCount) {
        ResourceCountResponse resourceCountResponse = new ResourceCountResponse();

        if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Account) {
            Account accountTemp = ApiDBUtils.findAccountById(resourceCount.getOwnerId());
            if (accountTemp != null) {
                populateAccount(resourceCountResponse, accountTemp.getId());
                populateDomain(resourceCountResponse, accountTemp.getDomainId());
            }
        } else if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Domain) {
            populateDomain(resourceCountResponse, resourceCount.getOwnerId());
        }

        resourceCountResponse.setResourceType(Integer.valueOf(resourceCount.getType().getOrdinal()).toString());
        resourceCountResponse.setResourceCount(resourceCount.getCount());
        resourceCountResponse.setObjectName("resourcecount");
        return resourceCountResponse;
    }

    @Override
    public ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering) {
        ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();
        offeringResponse.setId(offering.getId());
        offeringResponse.setName(offering.getName());
        offeringResponse.setIsSystemOffering(offering.getSystemUse());
        offeringResponse.setDefaultUse(offering.getDefaultUse());
        offeringResponse.setSystemVmType(offering.getSystemVmType());
        offeringResponse.setDisplayText(offering.getDisplayText());
        offeringResponse.setCpuNumber(offering.getCpu());
        offeringResponse.setCpuSpeed(offering.getSpeed());
        offeringResponse.setMemory(offering.getRamSize());
        offeringResponse.setCreated(offering.getCreated());
        offeringResponse.setStorageType(offering.getUseLocalStorage() ? ServiceOffering.StorageType.local.toString() : ServiceOffering.StorageType.shared.toString());
        offeringResponse.setOfferHa(offering.getOfferHA());
        offeringResponse.setLimitCpuUse(offering.getLimitCpuUse());
        offeringResponse.setTags(offering.getTags());
        if (offering.getDomainId() != null) {
            offeringResponse.setDomain(ApiDBUtils.findDomainById(offering.getDomainId()).getName());
            offeringResponse.setDomainId(offering.getDomainId());
        }
        offeringResponse.setNetworkRate(offering.getRateMbps());
        offeringResponse.setHostTag(offering.getHostTag());
        offeringResponse.setObjectName("serviceoffering");

        return offeringResponse;
    }

    @Override
    public ConfigurationResponse createConfigurationResponse(Configuration cfg) {
        ConfigurationResponse cfgResponse = new ConfigurationResponse();
        cfgResponse.setCategory(cfg.getCategory());
        cfgResponse.setDescription(cfg.getDescription());
        cfgResponse.setName(cfg.getName());
        cfgResponse.setValue(cfg.getValue());
        cfgResponse.setObjectName("configuration");

        return cfgResponse;
    }

    @Override
    public SnapshotResponse createSnapshotResponse(Snapshot snapshot) {
        SnapshotResponse snapshotResponse = new SnapshotResponse();
        snapshotResponse.setId(snapshot.getId());

        populateOwner(snapshotResponse, snapshot);

        VolumeVO volume = findVolumeById(snapshot.getVolumeId());
        String snapshotTypeStr = snapshot.getType().name();
        snapshotResponse.setSnapshotType(snapshotTypeStr);
        snapshotResponse.setVolumeId(snapshot.getVolumeId());
        if (volume != null) {
            snapshotResponse.setVolumeName(volume.getName());
            snapshotResponse.setVolumeType(volume.getVolumeType().name());
        }
        snapshotResponse.setCreated(snapshot.getCreated());
        snapshotResponse.setName(snapshot.getName());
        snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId()));
        snapshotResponse.setState(snapshot.getStatus());

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Snapshot, snapshot.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        snapshotResponse.setTags(tagResponses);

        snapshotResponse.setObjectName("snapshot");
        return snapshotResponse;
    @Override
    public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) {
        SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse();
        policyResponse.setId(policy.getId());
        policyResponse.setVolumeId(policy.getVolumeId());
        policyResponse.setSchedule(policy.getSchedule());
        policyResponse.setIntervalType(policy.getInterval());
        policyResponse.setMaxSnaps(policy.getMaxSnaps());
        policyResponse.setTimezone(policy.getTimezone());
        policyResponse.setObjectName("snapshotpolicy");

        return policyResponse;
    }

    @Override
    public HostResponse createHostResponse(Host host) {
        return createHostResponse(host, EnumSet.of(HostDetails.all));
    }

    @Override
    public HostResponse createHostResponse(Host host, EnumSet details) {
        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.setRemoved(host.getRemoved());
        hostResponse.setCpuSpeed(host.getSpeed());
        hostResponse.setState(host.getStatus());
        hostResponse.setIpAddress(host.getPrivateIpAddress());
        hostResponse.setVersion(host.getVersion());
        hostResponse.setCreated(host.getCreated());

        if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)
                || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) {

            GuestOSCategoryVO guestOSCategory = ApiDBUtils.getHostGuestOSCategory(host.getId());
            if (guestOSCategory != null) {
                hostResponse.setOsCategoryId(guestOSCategory.getId());
                hostResponse.setOsCategoryName(guestOSCategory.getName());
            }
            hostResponse.setZoneName(ApiDBUtils.findZoneById(host.getDataCenterId()).getName());

            if (host.getPodId() != null) {
                HostPodVO pod = ApiDBUtils.findPodById(host.getPodId());
                if (pod != null) {
                    hostResponse.setPodName(pod.getName());
                }
            }

            if (host.getClusterId() != null) {
                ClusterVO cluster = ApiDBUtils.findClusterById(host.getClusterId());
                hostResponse.setClusterName(cluster.getName());
                hostResponse.setClusterType(cluster.getClusterType().toString());
            }
        }

        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        if (host.getType() == Host.Type.Routing) {
            if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) {
                // set allocated capacities
                Long mem = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_MEMORY);
                Long cpu = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_CPU);

                hostResponse.setMemoryAllocated(mem);
                hostResponse.setMemoryTotal(host.getTotalMemory());
                String hostTags = ApiDBUtils.getHostTags(host.getId());
                hostResponse.setHostTags(hostTags);

                String haTag = ApiDBUtils.getHaTag();
                if (haTag != null && !haTag.isEmpty() && hostTags != null && !hostTags.isEmpty()) {
                    if (haTag.equalsIgnoreCase(hostTags)) {
                        hostResponse.setHaHost(true);
                    } else {
                        hostResponse.setHaHost(false);
                    }
                } else {
                    hostResponse.setHaHost(false);
                }

                hostResponse.setHypervisorVersion(host.getHypervisorVersion());

                String cpuAlloc = decimalFormat.format(((float) cpu / (float) (host.getCpus() * host.getSpeed())) * 100f) + "%";
                hostResponse.setCpuAllocated(cpuAlloc);
                String cpuWithOverprovisioning = new Float(host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor()).toString();
                hostResponse.setCpuWithOverprovisioning(cpuWithOverprovisioning);
            }

            if (details.contains(HostDetails.all) || details.contains(HostDetails.stats)) {
                // set CPU/RAM/Network stats
                String cpuUsed = null;
                HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId());
                if (hostStats != null) {
                    float cpuUtil = (float) hostStats.getCpuUtilization();
                    cpuUsed = decimalFormat.format(cpuUtil) + "%";
                    hostResponse.setCpuUsed(cpuUsed);
                    hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue());
                    hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue());
                    hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue());

                }
            }

        } else if (host.getType() == Host.Type.SecondaryStorage) {
            StorageStats secStorageStats = ApiDBUtils.getSecondaryStorageStatistics(host.getId());
            if (secStorageStats != null) {
                hostResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes());
                hostResponse.setDiskSizeAllocated(secStorageStats.getByteUsed());
            }
        }

        hostResponse.setLocalStorageActive(ApiDBUtils.isLocalStorageActiveOnHost(host));

        if (details.contains(HostDetails.all) || details.contains(HostDetails.events)) {
            Set possibleEvents = host.getStatus().getPossibleEvents();
            if ((possibleEvents != null) && !possibleEvents.isEmpty()) {
                String events = "";
                Iterator iter = possibleEvents.iterator();
                while (iter.hasNext()) {
                    com.cloud.host.Status.Event event = iter.next();
                    events += event.toString();
                    if (iter.hasNext()) {
                        events += "; ";
                    }
                }
                hostResponse.setEvents(events);
            }
        }

        hostResponse.setResourceState(host.getResourceState().toString());
        hostResponse.setObjectName("host");

        return hostResponse;
    }

    @Override
    public SwiftResponse createSwiftResponse(Swift swift) {
        SwiftResponse swiftResponse = new SwiftResponse();
        swiftResponse.setId(swift.getId());
        swiftResponse.setUrl(swift.getUrl());
        swiftResponse.setAccount(swift.getAccount());
        swiftResponse.setUsername(swift.getUserName());
        swiftResponse.setObjectName("swift");
        return swiftResponse;
    }

    @Override
    public VlanIpRangeResponse createVlanIpRangeResponse(Vlan vlan) {
        Long podId = ApiDBUtils.getPodIdForVlan(vlan.getId());

        VlanIpRangeResponse vlanResponse = new VlanIpRangeResponse();
        vlanResponse.setId(vlan.getId());
        vlanResponse.setForVirtualNetwork(vlan.getVlanType().equals(VlanType.VirtualNetwork));
        vlanResponse.setVlan(vlan.getVlanTag());
        vlanResponse.setZoneId(vlan.getDataCenterId());

        if (podId != null) {
            HostPodVO pod = ApiDBUtils.findPodById(podId);
            vlanResponse.setPodId(podId);
            if (pod != null) {
                vlanResponse.setPodName(pod.getName());
            }
        }

        vlanResponse.setGateway(vlan.getVlanGateway());
        vlanResponse.setNetmask(vlan.getVlanNetmask());

        // get start ip and end ip of corresponding vlan
        String ipRange = vlan.getIpRange();
        String[] range = ipRange.split("-");
        vlanResponse.setStartIp(range[0]);
        vlanResponse.setEndIp(range[1]);

        vlanResponse.setNetworkId(vlan.getNetworkId());
        Account owner = ApiDBUtils.getVlanAccount(vlan.getId());
        if (owner != null) {
            populateAccount(vlanResponse, owner.getId());
            populateDomain(vlanResponse, owner.getDomainId());
        }

        vlanResponse.setPhysicalNetworkId(vlan.getPhysicalNetworkId());

        vlanResponse.setObjectName("vlan");
        return vlanResponse;
    }

    @Override
    public IPAddressResponse createIPAddressResponse(IpAddress ipAddr) {
        VlanVO vlan = ApiDBUtils.findVlanById(ipAddr.getVlanId());
        boolean forVirtualNetworks = vlan.getVlanType().equals(VlanType.VirtualNetwork);
        long zoneId = ipAddr.getDataCenterId();

        IPAddressResponse ipResponse = new IPAddressResponse();
        ipResponse.setId(ipAddr.getId());
        ipResponse.setIpAddress(ipAddr.getAddress().toString());
        if (ipAddr.getAllocatedTime() != null) {
            ipResponse.setAllocated(ipAddr.getAllocatedTime());
        }
        ipResponse.setZoneId(zoneId);
        ipResponse.setZoneName(ApiDBUtils.findZoneById(ipAddr.getDataCenterId()).getName());
        ipResponse.setSourceNat(ipAddr.isSourceNat());
        ipResponse.setIsSystem(ipAddr.getSystem());

        // get account information
        populateOwner(ipResponse, ipAddr);

        ipResponse.setForVirtualNetwork(forVirtualNetworks);
        ipResponse.setStaticNat(ipAddr.isOneToOneNat());

        if (ipAddr.getAssociatedWithVmId() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(ipAddr.getAssociatedWithVmId());
            ipResponse.setVirtualMachineId(vm.getId());
            ipResponse.setVirtualMachineName(vm.getHostName());
            if (vm.getDisplayName() != null) {
                ipResponse.setVirtualMachineDisplayName(vm.getDisplayName());
            } else {
                ipResponse.setVirtualMachineDisplayName(vm.getHostName());
            }
        }

        ipResponse.setAssociatedNetworkId(ipAddr.getAssociatedWithNetworkId());
        ipResponse.setVpcId(ipAddr.getVpcId());

        // Network id the ip is associated with (if associated networkId is null, try to get this information from vlan)
        Long vlanNetworkId = ApiDBUtils.getVlanNetworkId(ipAddr.getVlanId());

        // Network id the ip belongs to
        Long networkId;
        if (vlanNetworkId != null) {
            networkId = vlanNetworkId;
        } else {
            networkId = ApiDBUtils.getPublicNetworkIdByZone(zoneId);
        }

        ipResponse.setNetworkId(networkId);
        ipResponse.setState(ipAddr.getState().toString());
        ipResponse.setPhysicalNetworkId(ipAddr.getPhysicalNetworkId());

        // show this info to admin only
        Account account = UserContext.current().getCaller();
        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            ipResponse.setVlanId(ipAddr.getVlanId());
            ipResponse.setVlanName(ApiDBUtils.findVlanById(ipAddr.getVlanId()).getVlanTag());
        }

        if (ipAddr.getSystem()) {
            if (ipAddr.isOneToOneNat()) {
                ipResponse.setPurpose(IpAddress.Purpose.StaticNat.toString());
            } else {
                ipResponse.setPurpose(IpAddress.Purpose.Lb.toString());
            }
        }

        //set tag information

        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PublicIpAddress, ipAddr.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        ipResponse.setTags(tagResponses);

        ipResponse.setObjectName("ipaddress");
        return ipResponse;
    }

    @Override
    public LoadBalancerResponse createLoadBalancerResponse(LoadBalancer loadBalancer) {
        LoadBalancerResponse lbResponse = new LoadBalancerResponse();
        lbResponse.setId(loadBalancer.getId());
        lbResponse.setName(loadBalancer.getName());
        lbResponse.setDescription(loadBalancer.getDescription());
        List cidrs = ApiDBUtils.findFirewallSourceCidrs(loadBalancer.getId());
        lbResponse.setCidrList(StringUtils.join(cidrs, ","));

        IPAddressVO publicIp = ApiDBUtils.findIpAddressById(loadBalancer.getSourceIpAddressId());
        lbResponse.setPublicIpId(publicIp.getId());
        lbResponse.setPublicIp(publicIp.getAddress().addr());
        lbResponse.setPublicPort(Integer.toString(loadBalancer.getSourcePortStart()));
        lbResponse.setPrivatePort(Integer.toString(loadBalancer.getDefaultPortStart()));
        lbResponse.setAlgorithm(loadBalancer.getAlgorithm());
        FirewallRule.State state = loadBalancer.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        lbResponse.setState(stateToSet);
        populateOwner(lbResponse, loadBalancer);
        lbResponse.setZoneId(publicIp.getDataCenterId());

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, loadBalancer.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        lbResponse.setTags(tagResponses);
        lbResponse.setObjectName("loadbalancer");
        return lbResponse;
    }

    @Override
    public PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
        String[] ipRange = new String[2];
        if (pod.getDescription() != null && pod.getDescription().length() > 0) {
            ipRange = pod.getDescription().split("-");
        } else {
            ipRange[0] = pod.getDescription();
        }

        PodResponse podResponse = new PodResponse();
        podResponse.setId(pod.getId());
        podResponse.setName(pod.getName());
        podResponse.setZoneId(pod.getDataCenterId());
        podResponse.setZoneName(PodZoneConfig.getZoneName(pod.getDataCenterId()));
        podResponse.setNetmask(NetUtils.getCidrNetmask(pod.getCidrSize()));
        podResponse.setStartIp(ipRange[0]);
        podResponse.setEndIp(((ipRange.length > 1) && (ipRange[1] != null)) ? ipRange[1] : "");
        podResponse.setGateway(pod.getGateway());
        podResponse.setAllocationState(pod.getAllocationState().toString());
        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, pod.getId(), null);
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
        }
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, pod.getId(), null);
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, null, pod.getId(), pod.getDataCenterId()));
            podResponse.setCapacitites(new ArrayList(capacityResponses));
        }
        podResponse.setObjectName("pod");
        return podResponse;
    }

    @Override
    public ZoneResponse createZoneResponse(DataCenter dataCenter, Boolean showCapacities) {
        Account account = UserContext.current().getCaller();
        ZoneResponse zoneResponse = new ZoneResponse();
        zoneResponse.setId(dataCenter.getId());
        zoneResponse.setName(dataCenter.getName());
        zoneResponse.setSecurityGroupsEnabled(ApiDBUtils.isSecurityGroupEnabledInZone(dataCenter.getId()));

        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());
            // FIXME zoneResponse.setVlan(dataCenter.get.getVnet());
            zoneResponse.setGuestCidrAddress(dataCenter.getGuestNetworkCidr());
        }

                }
        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(dataCenter.getId(), null, null);
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(dataCenter.getId(), null, null);
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, null, null, dataCenter.getId()));

            zoneResponse.setCapacitites(new ArrayList(capacityResponses));
        }

        // set network domain info
        zoneResponse.setDomain(dataCenter.getDomain());
        // set domain info
        Long domainId = dataCenter.getDomainId();
        if (domainId != null) {
            Domain domain = ApiDBUtils.findDomainById(domainId);
            zoneResponse.setDomainId(domain.getId());
            zoneResponse.setDomainName(domain.getName());
        }

        zoneResponse.setType(dataCenter.getNetworkType().toString());
        zoneResponse.setAllocationState(dataCenter.getAllocationState().toString());
        zoneResponse.setZoneToken(dataCenter.getZoneToken());
        zoneResponse.setDhcpProvider(dataCenter.getDhcpProvider());
        zoneResponse.setObjectName("zone");
        return zoneResponse;
    }

    private List getStatsCapacityresponse(Long poolId, Long clusterId, Long podId, Long zoneId) {
        List capacities = new ArrayList();
        capacities.add(ApiDBUtils.getStoragePoolUsedStats(poolId, clusterId, podId, zoneId));
        if (clusterId == null && podId == null) {
            capacities.add(ApiDBUtils.getSecondaryStorageUsedStats(poolId, zoneId));
        }

        List capacityResponses = new ArrayList();
        for (CapacityVO capacity : capacities) {
            CapacityResponse capacityResponse = new CapacityResponse();
            capacityResponse.setCapacityType(capacity.getCapacityType());
            capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
            capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
            if (capacityResponse.getCapacityTotal() != 0) {
                capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
            } else {
                capacityResponse.setPercentUsed(s_percentFormat.format(0L));
            }
            capacityResponses.add(capacityResponse);
        }

        return capacityResponses;
    }

    @Override
    public VolumeResponse createVolumeResponse(Volume volume) {
        VolumeResponse volResponse = new VolumeResponse();
        volResponse.setId(volume.getId());

        if (volume.getName() != null) {
            volResponse.setName(volume.getName());
        } else {
            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 && volume.getState() != Volume.State.Destroy) {
            VMInstanceVO vm = ApiDBUtils.findVMInstanceById(instanceId);
            if (vm != null) {
                volResponse.setVirtualMachineId(vm.getId());
                volResponse.setVirtualMachineName(vm.getHostName());
                UserVm userVm = ApiDBUtils.findUserVmById(vm.getId());
                if (userVm != null) {
                    if (userVm.getDisplayName() != null) {
                        volResponse.setVirtualMachineDisplayName(userVm.getDisplayName());
                    } else {
                        volResponse.setVirtualMachineDisplayName(userVm.getHostName());
                    }
                    volResponse.setVirtualMachineState(vm.getState().toString());
                } else {
                    s_logger.error("User Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
                }
            } else {
                s_logger.error("Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
            }
        }

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

        volResponse.setCreated(volume.getCreated());
        volResponse.setState(volume.getState().toString());
        if(volume.getState() == Volume.State.UploadOp){

            com.cloud.storage.VolumeHostVO volumeHostRef = ApiDBUtils.findVolumeHostRef(volume.getId(), volume.getDataCenterId());
            volResponse.setSize(volumeHostRef.getSize());
            volResponse.setCreated(volumeHostRef.getCreated());
            Account caller = UserContext.current().getCaller();
            if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)
                volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volumeHostRef.getFormat()).toString());
            if (volumeHostRef.getDownloadState() != Status.DOWNLOADED) {
                String volumeStatus = "Processing";
                if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                    if (volumeHostRef.getDownloadPercent() == 100) {
                        volumeStatus = "Checking Volume";
                    } else {
                        volumeStatus = volumeHostRef.getDownloadPercent() + "% Uploaded";
                    }
                    volResponse.setState("Uploading");
                } else {
                    volumeStatus = volumeHostRef.getErrorString();
                    if(volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.NOT_DOWNLOADED){
                        volResponse.setState("UploadNotStarted");
                    }else {
                        volResponse.setState("UploadError");
                    }
                }
                volResponse.setStatus(volumeStatus);
            } else if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                volResponse.setStatus("Upload Complete");
                volResponse.setState("Uploaded");
            } else {
                volResponse.setStatus("Successfully Installed");
            }
        }

        populateOwner(volResponse, volume);

        String storageType;
        try {
            if (volume.getPoolId() == null) {
                if (volume.getState() == Volume.State.Allocated || volume.getState() == Volume.State.UploadOp) {
                    /* set it as shared, so the UI can attach it to VM */
                    storageType = "shared";
                } else {
                    storageType = "unknown";
            } else {
                storageType = ApiDBUtils.volumeIsOnSharedStorage(volume.getId()) ? ServiceOffering.StorageType.shared.toString() : ServiceOffering.StorageType.local.toString();
            }
        } catch (InvalidParameterValueException e) {
            s_logger.error(e.getMessage(), e);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Volume " + volume.getName() + " does not have a valid ID");
        }

        volResponse.setStorageType(storageType);
        if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
            volResponse.setServiceOfferingId(volume.getDiskOfferingId());
        } else {
            volResponse.setDiskOfferingId(volume.getDiskOfferingId());
        }

        DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
        if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
            volResponse.setServiceOfferingName(diskOffering.getName());
            volResponse.setServiceOfferingDisplayText(diskOffering.getDisplayText());
        } else {
            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.setSourceId(volume.getSourceId());
        // if (volume.getSourceType() != null) {
        // volResponse.setSourceType(volume.getSourceType().toString());
        // }

        // return hypervisor for ROOT and Resource domain only
        Account caller = UserContext.current().getCaller();
        if ((caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) && volume.getState() != Volume.State.UploadOp) {
        clusterResponse.setId(cluster.getId());
            volResponse.setHypervisor(ApiDBUtils.getVolumeHyperType(volume.getId()).toString());
        }

        volResponse.setAttached(volume.getAttached());
        volResponse.setDestroyed(volume.getState() == Volume.State.Destroy);
        boolean isExtractable = true;
        if (volume.getVolumeType() != Volume.Type.DATADISK) { // Datadisk dont have any template dependence.
            VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
            if (template != null) { // For ISO based volumes template = null and we allow extraction of all ISO based
                // volumes
                isExtractable = template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
            }
        }

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Volume, volume.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        volResponse.setTags(tagResponses);

        volResponse.setExtractable(isExtractable);
        volResponse.setObjectName("volume");
        return volResponse;
    }

    @Override
    public InstanceGroupResponse createInstanceGroupResponse(InstanceGroup group) {
        InstanceGroupResponse groupResponse = new InstanceGroupResponse();
        groupResponse.setId(group.getId());
        groupResponse.setName(group.getName());
        groupResponse.setCreated(group.getCreated());

        populateOwner(groupResponse, group);

        groupResponse.setObjectName("instancegroup");
        return groupResponse;
    }

    @Override
    public StoragePoolResponse createStoragePoolResponse(StoragePool pool) {
        StoragePoolResponse poolResponse = new StoragePoolResponse();
        poolResponse.setId(pool.getId());
        poolResponse.setName(pool.getName());
        poolResponse.setState(pool.getStatus());
        poolResponse.setPath(pool.getPath());
        poolResponse.setIpAddress(pool.getHostAddress());
        poolResponse.setZoneId(pool.getDataCenterId());
        poolResponse.setZoneName(ApiDBUtils.findZoneById(pool.getDataCenterId()).getName());
        if (pool.getPoolType() != null) {
            poolResponse.setType(pool.getPoolType().toString());
        }
        if (pool.getPodId() != null) {
            poolResponse.setPodId(pool.getPodId());
            HostPodVO pod = ApiDBUtils.findPodById(pool.getPodId());
            if (pod != null) {
                poolResponse.setPodName(pod.getName());
            }
        }
        if (pool.getCreated() != null) {
            poolResponse.setCreated(pool.getCreated());
        }

        StorageStats stats = ApiDBUtils.getStoragePoolStatistics(pool.getId());
        long allocatedSize = ApiDBUtils.getStorageCapacitybyPool(pool.getId(), Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED);
        poolResponse.setDiskSizeTotal(pool.getCapacityBytes());
        poolResponse.setDiskSizeAllocated(allocatedSize);

        if (stats != null) {
            Long used = stats.getByteUsed();
            poolResponse.setDiskSizeUsed(used);
        }

        if (pool.getClusterId() != null) {
            ClusterVO cluster = ApiDBUtils.findClusterById(pool.getClusterId());
            poolResponse.setClusterId(cluster.getId());
            poolResponse.setClusterName(cluster.getName());
        }
        poolResponse.setTags(ApiDBUtils.getStoragePoolTags(pool.getId()));
        poolResponse.setObjectName("storagepool");
        return poolResponse;
    }

    @Override
    public ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities) {
        ClusterResponse clusterResponse = new ClusterResponse();
        clusterResponse.setName(cluster.getName());
        clusterResponse.setPodId(cluster.getPodId());
        clusterResponse.setZoneId(cluster.getDataCenterId());
        clusterResponse.setHypervisorType(cluster.getHypervisorType().toString());
        clusterResponse.setClusterType(cluster.getClusterType().toString());
        clusterResponse.setAllocationState(cluster.getAllocationState().toString());
        clusterResponse.setManagedState(cluster.getManagedState().toString());
        HostPodVO pod = ApiDBUtils.findPodById(cluster.getPodId());
        if (pod != null) {
            clusterResponse.setPodName(pod.getName());
        }
        DataCenterVO zone = ApiDBUtils.findZoneById(cluster.getDataCenterId());
        clusterResponse.setZoneName(zone.getName());
        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, null, cluster.getId());
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());

                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, null, cluster.getId());
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, cluster.getId(), pod.getId(), pod.getDataCenterId()));
            clusterResponse.setCapacitites(new ArrayList(capacityResponses));
        }
        clusterResponse.setObjectName("cluster");
        return clusterResponse;
    }

    @Override
    public FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRule fwRule) {
        FirewallRuleResponse response = new FirewallRuleResponse();
        response.setId(fwRule.getId());
        response.setPrivateStartPort(Integer.toString(fwRule.getDestinationPortStart()));
        response.setPrivateEndPort(Integer.toString(fwRule.getDestinationPortEnd()));
        response.setProtocol(fwRule.getProtocol());
        response.setPublicStartPort(Integer.toString(fwRule.getSourcePortStart()));
        response.setPublicEndPort(Integer.toString(fwRule.getSourcePortEnd()));
        List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        if (ip != null && fwRule.getDestinationIpAddress() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(fwRule.getVirtualMachineId());
            if (vm != null) {
                response.setVirtualMachineId(vm.getId());
                response.setVirtualMachineName(vm.getHostName());

                if (vm.getDisplayName() != null) {
                    response.setVirtualMachineDisplayName(vm.getDisplayName());
                } else {
                    response.setVirtualMachineDisplayName(vm.getHostName());
                }
            }
        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PortForwardingRule, fwRule.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setState(stateToSet);
        response.setObjectName("portforwardingrule");
        return response;
    }

    @Override
    public IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule) {
        IpForwardingRuleResponse response = new IpForwardingRuleResponse();
        response.setId(fwRule.getId());
        response.setProtocol(fwRule.getProtocol());

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        if (ip != null && fwRule.getDestIpAddress() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(ip.getAssociatedWithVmId());
            if (vm != null) {// vm might be destroyed
                response.setVirtualMachineId(vm.getId());
                response.setVirtualMachineName(vm.getHostName());
                if (vm.getDisplayName() != null) {
                    response.setVirtualMachineDisplayName(vm.getDisplayName());
                } else {
                    response.setVirtualMachineDisplayName(vm.getHostName());
                }
            }
        }
        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setStartPort(fwRule.getSourcePortStart());
        response.setEndPort(fwRule.getSourcePortEnd());
        response.setProtocol(fwRule.getProtocol());
        response.setState(stateToSet);
        response.setObjectName("ipforwardingrule");
        return response;
    }

    @Override
    public List createUserVmResponse(String objectName, EnumSet details, UserVm... userVms) {
        Account caller = UserContext.current().getCaller();
        Map dataCenters = new HashMap();
        Map hosts = new HashMap();
        Map templates = new HashMap();
        Map serviceOfferings = new HashMap();
        Map networks = new HashMap();

        List vmResponses = new ArrayList();

        for (UserVm userVm : userVms) {
            UserVmResponse userVmResponse = new UserVmResponse();
            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.setId(userVm.getId());
            userVmResponse.setName(userVm.getHostName());
            userVmResponse.setCreated(userVm.getCreated());

            userVmResponse.setHaEnable(userVm.isHaEnabled());

            if (userVm.getDisplayName() != null) {
                userVmResponse.setDisplayName(userVm.getDisplayName());
            } else {
                userVmResponse.setDisplayName(userVm.getHostName());
            }

            if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {
                userVmResponse.setInstanceName(userVm.getInstanceName());
            }

            if (userVm.getPassword() != null) {
                userVmResponse.setPassword(userVm.getPassword());
            }

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

            }

            // Data Center Info
            DataCenter zone = dataCenters.get(userVm.getDataCenterIdToDeployIn());
            if (zone == null) {
                zone = ApiDBUtils.findZoneById(userVm.getDataCenterIdToDeployIn());
                dataCenters.put(zone.getId(), zone);
            }

            userVmResponse.setZoneId(zone.getId());
            userVmResponse.setZoneName(zone.getName());

            // if user is an admin, display host id
            if (((caller == null) || (caller.getType() == Account.ACCOUNT_TYPE_ADMIN)) && (userVm.getHostId() != null)) {
                Host host = hosts.get(userVm.getHostId());

                if (host == null) {
                    host = ApiDBUtils.findHostById(userVm.getHostId());
                    hosts.put(host.getId(), host);
                }

                userVmResponse.setHostId(host.getId());
                userVmResponse.setHostName(host.getName());
            }

            if (userVm.getState() != null) {
                if (userVm.getHostId() != null) {
                    Host host = hosts.get(userVm.getHostId());

                    if (host == null) {
                        host = ApiDBUtils.findHostById(userVm.getHostId());
                        hosts.put(host.getId(), host);
                    }
                    if (host.getStatus() != com.cloud.host.Status.Up) {
                        userVmResponse.setState(VirtualMachine.State.Unknown.toString());
                    } else {
                        userVmResponse.setState(userVm.getState().toString());
                    }
                } else {
                    userVmResponse.setState(userVm.getState().toString());
                }
            }

            if (userVm.getHypervisorType() != null) {
                userVmResponse.setHypervisor(userVm.getHypervisorType().toString());
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.tmpl)) {
                // Template Info
                VMTemplateVO template = templates.get(userVm.getTemplateId());
                if (template == null) {
                    template = ApiDBUtils.findTemplateById(userVm.getTemplateId());
                    if (template != null) {
                        templates.put(template.getId(), template);
                    }
                }

                if (template != null) {
                    userVmResponse.setTemplateId(userVm.getTemplateId());
                    userVmResponse.setTemplateName(template.getName());
                    userVmResponse.setTemplateDisplayText(template.getDisplayText());
                    userVmResponse.setPasswordEnabled(template.getEnablePassword());
                } else {
                    userVmResponse.setTemplateId(-1L);
                    userVmResponse.setTemplateName("ISO Boot");
                    userVmResponse.setTemplateDisplayText("ISO Boot");
                    userVmResponse.setPasswordEnabled(false);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.iso)) {
                // ISO Info
                VMTemplateVO iso = templates.get(userVm.getIsoId());
                if (iso == null) {
                    iso = ApiDBUtils.findTemplateById(userVm.getIsoId());
                    if (iso != null) {
                        templates.put(iso.getId(), iso);
                    }
                }

                if (iso != null) {
                    userVmResponse.setIsoId(iso.getId());
                    userVmResponse.setIsoName(iso.getName());
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.servoff)) {
                // Service Offering Info
                ServiceOffering offering = serviceOfferings.get(userVm.getServiceOfferingId());

                if (offering == null) {
                    offering = ApiDBUtils.findServiceOfferingById(userVm.getServiceOfferingId());
                    serviceOfferings.put(offering.getId(), offering);
                }

                userVmResponse.setServiceOfferingId(offering.getId());
                userVmResponse.setServiceOfferingName(offering.getName());
                userVmResponse.setCpuNumber(offering.getCpu());
                userVmResponse.setCpuSpeed(offering.getSpeed());
                userVmResponse.setMemory(offering.getRamSize());
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.volume)) {
                VolumeVO rootVolume = ApiDBUtils.findRootVolume(userVm.getId());
                if (rootVolume != null) {
                    userVmResponse.setRootDeviceId(rootVolume.getDeviceId());
                    String rootDeviceType = "Not created";
                    if (rootVolume.getPoolId() != null) {
                        StoragePoolVO storagePool = ApiDBUtils.findStoragePoolById(rootVolume.getPoolId());
                        rootDeviceType = storagePool.getPoolType().toString();
                    }
                    userVmResponse.setRootDeviceType(rootDeviceType);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.stats)) {
                // stats calculation
                DecimalFormat decimalFormat = new DecimalFormat("#.##");
                String cpuUsed = null;
                VmStats vmStats = ApiDBUtils.getVmStatistics(userVm.getId());
                if (vmStats != null) {
                    float cpuUtil = (float) vmStats.getCPUUtilization();
                    cpuUsed = decimalFormat.format(cpuUtil) + "%";
                    userVmResponse.setCpuUsed(cpuUsed);

                    Double networkKbRead = Double.valueOf(vmStats.getNetworkReadKBs());
                    userVmResponse.setNetworkKbsRead(networkKbRead.longValue());

                    Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
                    userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
                }
            }

            userVmResponse.setGuestOsId(userVm.getGuestOSId());

            if (details.contains(VMDetails.all) || details.contains(VMDetails.secgrp)) {
                // security groups - list only when zone is security group enabled
                if (zone.isSecurityGroupEnabled()) {
                    List securityGroups = ApiDBUtils.getSecurityGroupsForVm(userVm.getId());
                    List securityGroupResponse = new ArrayList();
                    for (SecurityGroupVO grp : securityGroups) {
                        SecurityGroupResponse resp = new SecurityGroupResponse();
                        resp.setId(grp.getId());
                        resp.setName(grp.getName());
                        resp.setDescription(grp.getDescription());
                        resp.setObjectName("securitygroup");
                        securityGroupResponse.add(resp);
                    }
                    userVmResponse.setSecurityGroupList(securityGroupResponse);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.nics)) {
                List nicProfiles = ApiDBUtils.getNics(userVm);
                List nicResponses = new ArrayList();
        }
                for (NicProfile singleNicProfile : nicProfiles) {
                    NicResponse nicResponse = new NicResponse();
                    nicResponse.setId(singleNicProfile.getId());
                    nicResponse.setIpaddress(singleNicProfile.getIp4Address());
                    nicResponse.setGateway(singleNicProfile.getGateway());
                    nicResponse.setNetmask(singleNicProfile.getNetmask());
                    nicResponse.setNetworkid(singleNicProfile.getNetworkId());
                    if (acct.getType() == Account.ACCOUNT_TYPE_ADMIN) {
                        if (singleNicProfile.getBroadCastUri() != null) {
                            nicResponse.setBroadcastUri(singleNicProfile.getBroadCastUri().toString());
                        }
                        if (singleNicProfile.getIsolationUri() != null) {
                            nicResponse.setIsolationUri(singleNicProfile.getIsolationUri().toString());
                        }
                    }

                    // Long networkId = singleNicProfile.getNetworkId();
                    Network network = networks.get(singleNicProfile.getNetworkId());
                    if (network == null) {
                        network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                        networks.put(singleNicProfile.getNetworkId(), network);
                    }

                    nicResponse.setTrafficType(network.getTrafficType().toString());
                    nicResponse.setType(network.getGuestType().toString());
                    nicResponse.setIsDefault(singleNicProfile.isDefaultNic());
                    nicResponse.setObjectName("nic");
                    nicResponses.add(nicResponse);
                }
                userVmResponse.setNics(nicResponses);
            }

            //set tag information
            List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, userVm.getId());
            List tagResponses = new ArrayList();
            for (ResourceTag tag : tags) {
                ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                tagResponses.add(tagResponse);
            }
            userVmResponse.setTags(tagResponses);

            IpAddress ip = ApiDBUtils.findIpByAssociatedVmId(userVm.getId());
                }
            if (ip != null) {
                userVmResponse.setPublicIpId(ip.getId());
                userVmResponse.setPublicIp(ip.getAddress().addr());
            }

            userVmResponse.setObjectName(objectName);
            vmResponses.add(userVmResponse);
        }

        return vmResponses;
    }

    @Override
    public List createUserVmResponse(String objectName, UserVm... userVms) {
        Account caller = UserContext.current().getCaller();
        boolean caller_is_admin = ((caller == null) || (caller.getType() == Account.ACCOUNT_TYPE_ADMIN));

        Hashtable vmDataList = new Hashtable();
        // Initialise the vmdatalist with the input data
        for (UserVm userVm : userVms) {
            UserVmData userVmData = newUserVmData(userVm);
            vmDataList.put(userVm.getId(), userVmData);
        }

        vmDataList = ApiDBUtils.listVmDetails(vmDataList);

        // initialize vmresponse from vmdatalist
        List vmResponses = new ArrayList();
        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        for (UserVmData uvd : vmDataList.values()) {
            UserVmResponse userVmResponse = newUserVmResponse(uvd, caller_is_admin);

            // stats calculation
            String cpuUsed = null;
            // VmStats vmStats = ApiDBUtils.getVmStatistics(userVmResponse.getId());
            VmStats vmStats = ApiDBUtils.getVmStatistics(uvd.getId());
            if (vmStats != null) {
                float cpuUtil = (float) vmStats.getCPUUtilization();
                cpuUsed = decimalFormat.format(cpuUtil) + "%";
                userVmResponse.setCpuUsed(cpuUsed);

                Double networkKbRead = Double.valueOf(vmStats.getNetworkReadKBs());
                userVmResponse.setNetworkKbsRead(networkKbRead.longValue());

                Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
                userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
            }
            userVmResponse.setObjectName(objectName);

            vmResponses.add(userVmResponse);
        }
        return vmResponses;
    }

    @Override
    public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) {
        Account caller = UserContext.current().getCaller();
        Map serviceOfferings = new HashMap();

        DomainRouterResponse routerResponse = new DomainRouterResponse();
        routerResponse.setId(router.getId());
        routerResponse.setZoneId(router.getDataCenterIdToDeployIn());
        routerResponse.setName(router.getHostName());
        routerResponse.setTemplateId(router.getTemplateId());
        routerResponse.setCreated(router.getCreated());
        routerResponse.setState(router.getState());
        routerResponse.setIsRedundantRouter(router.getIsRedundantRouter());
        routerResponse.setRedundantState(router.getRedundantState().toString());

        if (caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            if (router.getHostId() != null) {
                routerResponse.setHostId(router.getHostId());
                routerResponse.setHostName(ApiDBUtils.findHostById(router.getHostId()).getName());
            }
            routerResponse.setPodId(router.getPodIdToDeployIn());
            List nicProfiles = ApiDBUtils.getNics(router);
            for (NicProfile singleNicProfile : nicProfiles) {
                Network network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                if (network != null) {
                    if (network.getTrafficType() == TrafficType.Public) {
                        routerResponse.setPublicIp(singleNicProfile.getIp4Address());
                        routerResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setPublicNetmask(singleNicProfile.getNetmask());
        response.setFormat(result.getFormat());
                        routerResponse.setGateway(singleNicProfile.getGateway());
                        routerResponse.setPublicNetworkId(singleNicProfile.getNetworkId());
                    } else if (network.getTrafficType() == TrafficType.Control) {
                        routerResponse.setLinkLocalIp(singleNicProfile.getIp4Address());
                        routerResponse.setLinkLocalMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setLinkLocalNetmask(singleNicProfile.getNetmask());
                        routerResponse.setLinkLocalNetworkId(singleNicProfile.getNetworkId());
                    } else if (network.getTrafficType() == TrafficType.Guest) {
                        routerResponse.setGuestIpAddress(singleNicProfile.getIp4Address());
                        routerResponse.setGuestMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setGuestNetmask(singleNicProfile.getNetmask());
                        routerResponse.setGuestNetworkId(singleNicProfile.getNetworkId());
                        routerResponse.setNetworkDomain(network.getNetworkDomain());
                    }
                }
            }
        }

        // Service Offering Info
        ServiceOffering offering = serviceOfferings.get(router.getServiceOfferingId());

        if (offering == null) {
            offering = ApiDBUtils.findServiceOfferingById(router.getServiceOfferingId());
            serviceOfferings.put(offering.getId(), offering);
        }
        routerResponse.setServiceOfferingId(offering.getId());
        routerResponse.setServiceOfferingName(offering.getName());

        populateOwner(routerResponse, router);

        DataCenter zone = ApiDBUtils.findZoneById(router.getDataCenterIdToDeployIn());
        if (zone != null) {
            routerResponse.setZoneName(zone.getName());
            routerResponse.setDns1(zone.getDns1());
            routerResponse.setDns2(zone.getDns2());
        }

        routerResponse.setVpcId(router.getVpcId());

        routerResponse.setObjectName("domainrouter");
        return routerResponse;
    }

    @Override
    public SystemVmResponse createSystemVmResponse(VirtualMachine vm) {
        SystemVmResponse vmResponse = new SystemVmResponse();
        if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy) {
            // SystemVm vm = (SystemVm) systemVM;
            vmResponse.setId(vm.getId());
            vmResponse.setObjectId(vm.getId());
            vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
            vmResponse.setZoneId(vm.getDataCenterIdToDeployIn());

            vmResponse.setName(vm.getHostName());
            vmResponse.setPodId(vm.getPodIdToDeployIn());
            vmResponse.setTemplateId(vm.getTemplateId());
            vmResponse.setCreated(vm.getCreated());

            if (vm.getHostId() != null) {
                vmResponse.setHostId(vm.getHostId());
                vmResponse.setHostName(ApiDBUtils.findHostById(vm.getHostId()).getName());
            }

            if (vm.getState() != null) {
                vmResponse.setState(vm.getState().toString());
            }

            // for console proxies, add the active sessions
            if (vm.getType() == Type.ConsoleProxy) {
                ConsoleProxyVO proxy = ApiDBUtils.findConsoleProxy(vm.getId());
                // proxy can be already destroyed
                if (proxy != null) {
                    vmResponse.setActiveViewerSessions(proxy.getActiveSession());
                }
            }

            DataCenter zone = ApiDBUtils.findZoneById(vm.getDataCenterIdToDeployIn());
            if (zone != null) {
                vmResponse.setZoneName(zone.getName());
                vmResponse.setDns1(zone.getDns1());
                vmResponse.setDns2(zone.getDns2());
            }

            List nicProfiles = ApiDBUtils.getNics(vm);
            for (NicProfile singleNicProfile : nicProfiles) {
                Network network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                if (network != null) {
                    if (network.getTrafficType() == TrafficType.Management) {
                        vmResponse.setPrivateIp(singleNicProfile.getIp4Address());
                        vmResponse.setPrivateMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setPrivateNetmask(singleNicProfile.getNetmask());
                    } else if (network.getTrafficType() == TrafficType.Control) {
                        vmResponse.setLinkLocalIp(singleNicProfile.getIp4Address());
                        vmResponse.setLinkLocalMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setLinkLocalNetmask(singleNicProfile.getNetmask());
                    } else if (network.getTrafficType() == TrafficType.Public || network.getTrafficType() == TrafficType.Guest) {
                        /*In basic zone, public ip has TrafficType.Guest*/
                        vmResponse.setPublicIp(singleNicProfile.getIp4Address());
                        vmResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setPublicNetmask(singleNicProfile.getNetmask());
                        vmResponse.setGateway(singleNicProfile.getGateway());
                    }
                }
            }
        }
        vmResponse.setObjectName("systemvm");
        return vmResponse;
    }

    @Override
    public Host findHostById(Long hostId) {
        return ApiDBUtils.findHostById(hostId);
    }

    @Override
    public User findUserById(Long userId) {
        return ApiDBUtils.findUserById(userId);
    }

    @Override
    public UserVm findUserVmById(Long vmId) {
        return ApiDBUtils.findUserVmById(vmId);

    }

    @Override
    public VolumeVO findVolumeById(Long volumeId) {
        return ApiDBUtils.findVolumeById(volumeId);
    }

    @Override
    public Account findAccountByNameDomain(String accountName, Long domainId) {
        return ApiDBUtils.findAccountByNameDomain(accountName, domainId);
    }

    @Override
    public VirtualMachineTemplate findTemplateById(Long templateId) {
        return ApiDBUtils.findTemplateById(templateId);
    }

    @Override
    public VpnUsersResponse createVpnUserResponse(VpnUser vpnUser) {
        VpnUsersResponse vpnResponse = new VpnUsersResponse();
        vpnResponse.setId(vpnUser.getId());
        vpnResponse.setUserName(vpnUser.getUsername());

        populateOwner(vpnResponse, vpnUser);

        vpnResponse.setObjectName("vpnuser");
        return vpnResponse;
    }

    @Override
    public RemoteAccessVpnResponse createRemoteAccessVpnResponse(RemoteAccessVpn vpn) {
        RemoteAccessVpnResponse vpnResponse = new RemoteAccessVpnResponse();
        vpnResponse.setPublicIpId(vpn.getServerAddressId());
        vpnResponse.setPublicIp(ApiDBUtils.findIpAddressById(vpn.getServerAddressId()).getAddress().addr());
        vpnResponse.setIpRange(vpn.getIpRange());
        vpnResponse.setPresharedKey(vpn.getIpsecPresharedKey());
        vpnResponse.setDomainId(vpn.getDomainId());

        populateOwner(vpnResponse, vpn);

        vpnResponse.setState(vpn.getState().toString());
        vpnResponse.setObjectName("remoteaccessvpn");

        return vpnResponse;
    }

    @Override
    public TemplateResponse createIsoResponse(VirtualMachineTemplate result) {
        TemplateResponse response = new TemplateResponse();
        response.setId(result.getId());
        response.setName(result.getName());
        response.setDisplayText(result.getDisplayText());
        response.setPublic(result.isPublicTemplate());
        response.setCreated(result.getCreated());
        response.setOsTypeId(result.getGuestOSId());
        response.setOsTypeName(ApiDBUtils.findGuestOSById(result.getGuestOSId()).getDisplayName());
        response.setDetails(result.getDetails());
        Account caller = UserContext.current().getCaller();

        if (result.getFormat() == ImageFormat.ISO) { // Templates are always bootable
            response.setBootable(result.isBootable());
        } else {
            response.setHypervisor(result.getHypervisorType().toString());// hypervisors are associated with templates
        }

        // add account ID and name
        Account owner = ApiDBUtils.findAccountById(result.getAccountId());
        populateAccount(response, owner.getId());
        populateDomain(response, owner.getDomainId());

        //set tag information
        List tags = null;
        if (result.getFormat() == ImageFormat.ISO) {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, result.getId());
        } else {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, result.getId());
        }

        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("iso");
        return response;
    }

    @Override
    public List createTemplateResponses(long templateId, Long zoneId, boolean readyOnly) {
        if (zoneId == null || zoneId == -1) {
            List responses = new ArrayList();
        // Add the zone ID
            List dcs = new ArrayList();
            responses = createSwiftTemplateResponses(templateId);
            if (!responses.isEmpty()) {
                return responses;
            }
            dcs.addAll(ApiDBUtils.listZones());
            for (DataCenterVO dc : dcs) {
                responses.addAll(createTemplateResponses(templateId, dc.getId(), readyOnly));
            }
            return responses;
        } else {
            return createTemplateResponses(templateId, zoneId.longValue(), readyOnly);
        }
    }

    private List createSwiftTemplateResponses(long templateId) {
        VirtualMachineTemplate template = findTemplateById(templateId);
        List responses = new ArrayList();
        VMTemplateSwiftVO templateSwiftRef = ApiDBUtils.findTemplateSwiftRef(templateId);
        if (templateSwiftRef == null) {
            return responses;
        }

        TemplateResponse templateResponse = new TemplateResponse();
        templateResponse.setId(template.getId());
        templateResponse.setName(template.getName());
        templateResponse.setDisplayText(template.getDisplayText());
        templateResponse.setPublic(template.isPublicTemplate());
        templateResponse.setCreated(templateSwiftRef.getCreated());

        templateResponse.setReady(true);
        templateResponse.setFeatured(template.isFeatured());
        templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM));
        templateResponse.setPasswordEnabled(template.getEnablePassword());
        templateResponse.setCrossZones(template.isCrossZones());
        templateResponse.setFormat(template.getFormat());
        templateResponse.setDetails(template.getDetails());
        if (template.getTemplateType() != null) {
            templateResponse.setTemplateType(template.getTemplateType().toString());
        }

        templateResponse.setHypervisor(template.getHypervisorType().toString());

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

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId());
        populateAccount(templateResponse, account.getId());
        populateDomain(templateResponse, account.getDomainId());

        Account caller = UserContext.current().getCaller();
        boolean isAdmin = false;
        if (BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }

        // If the user is an Admin, add the template download status
        if (isAdmin || caller.getId() == template.getAccountId()) {
            // add download status
            templateResponse.setStatus("Successfully Installed");
        }

        Long templateSize = templateSwiftRef.getSize();
        if (templateSize > 0) {
            templateResponse.setSize(templateSize);
        }

        templateResponse.setChecksum(template.getChecksum());
        templateResponse.setSourceTemplateId(template.getSourceTemplateId());

        templateResponse.setChecksum(template.getChecksum());

        templateResponse.setTemplateTag(template.getTemplateTag());

        templateResponse.setObjectName("template");
        responses.add(templateResponse);
        return responses;
    }

    @Override
    public List createTemplateResponses(long templateId, long zoneId, boolean readyOnly) {
        VirtualMachineTemplate template = findTemplateById(templateId);
        List responses = new ArrayList();
        VMTemplateHostVO templateHostRef = ApiDBUtils.findTemplateHostRef(templateId, zoneId, readyOnly);
        if (templateHostRef == null) {
            return responses;
        }

        HostVO host = ApiDBUtils.findHostById(templateHostRef.getHostId());
        if (host.getType() == Host.Type.LocalSecondaryStorage && host.getStatus() != com.cloud.host.Status.Up) {
            return responses;
        }

        TemplateResponse templateResponse = new TemplateResponse();
        templateResponse.setId(template.getId());
        templateResponse.setName(template.getName());
        templateResponse.setDisplayText(template.getDisplayText());
        templateResponse.setPublic(template.isPublicTemplate());
        templateResponse.setCreated(templateHostRef.getCreated());

        templateResponse.setReady(templateHostRef.getDownloadState() == Status.DOWNLOADED);
        templateResponse.setFeatured(template.isFeatured());
        templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM));
        templateResponse.setPasswordEnabled(template.getEnablePassword());
        templateResponse.setCrossZones(template.isCrossZones());
        templateResponse.setFormat(template.getFormat());
        if (template.getTemplateType() != null) {
            templateResponse.setTemplateType(template.getTemplateType().toString());
        }

        templateResponse.setHypervisor(template.getHypervisorType().toString());
        templateResponse.setDetails(template.getDetails());

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

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId());
        populateAccount(templateResponse, account.getId());
        populateDomain(templateResponse, account.getDomainId());

            // add account ID and name
        DataCenterVO datacenter = ApiDBUtils.findZoneById(zoneId);

        // Add the zone ID
        templateResponse.setZoneId(zoneId);
        templateResponse.setZoneName(datacenter.getName());

        boolean isAdmin = false;
        Account caller = UserContext.current().getCaller();
        if ((caller == null) || BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }

        // If the user is an Admin, add the template download status
        if (isAdmin || caller.getId() == template.getAccountId()) {
            // add download status
            if (templateHostRef.getDownloadState() != Status.DOWNLOADED) {
                String templateStatus = "Processing";
                if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                    if (templateHostRef.getDownloadPercent() == 100) {
                        templateStatus = "Installing Template";
                    } else {
                        templateStatus = templateHostRef.getDownloadPercent() + "% Downloaded";
                    }
                } else {
                    templateStatus = templateHostRef.getErrorString();
                }
                templateResponse.setStatus(templateStatus);
            } else if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                templateResponse.setStatus("Download Complete");
            } else {
                templateResponse.setStatus("Successfully Installed");
            }
        }

        Long templateSize = templateHostRef.getSize();
        if (templateSize > 0) {
            templateResponse.setSize(templateSize);
        }

        templateResponse.setChecksum(template.getChecksum());
        templateResponse.setSourceTemplateId(template.getSourceTemplateId());
        templateResponse.setChecksum(template.getChecksum());

        templateResponse.setTemplateTag(template.getTemplateTag());

        //set tag information
        List tags = null;
        if (template.getFormat() == ImageFormat.ISO) {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, template.getId());
        } else {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, template.getId());
        }
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        templateResponse.setTags(tagResponses);

        templateResponse.setObjectName("template");
        responses.add(templateResponse);
        return responses;
    }

    @Override
    public List createIsoResponses(long isoId, Long zoneId, boolean readyOnly) {

        List isoResponses = new ArrayList();
        VirtualMachineTemplate iso = findTemplateById(isoId);
        if (iso.getTemplateType() == TemplateType.PERHOST) {
            TemplateResponse isoResponse = new TemplateResponse();
            isoResponse.setId(iso.getId());
            isoResponse.setName(iso.getName());
            isoResponse.setDisplayText(iso.getDisplayText());
            isoResponse.setPublic(iso.isPublicTemplate());
            isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
            isoResponse.setReady(true);
            isoResponse.setBootable(iso.isBootable());
            isoResponse.setFeatured(iso.isFeatured());
            isoResponse.setCrossZones(iso.isCrossZones());
            isoResponse.setPublic(iso.isPublicTemplate());
            isoResponse.setCreated(iso.getCreated());
            isoResponse.setChecksum(iso.getChecksum());
            isoResponse.setPasswordEnabled(false);
            isoResponse.setDetails(iso.getDetails());

                // an
            Account owner = ApiDBUtils.findAccountById(iso.getAccountId());
            populateAccount(isoResponse, owner.getId());
            populateDomain(isoResponse, owner.getDomainId());

            //set tag information
            List tags =  ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId());
            List tagResponses = new ArrayList();
            for (ResourceTag tag : tags) {
                ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                tagResponses.add(tagResponse);
            }
            isoResponse.setTags(tagResponses);

            isoResponse.setObjectName("iso");
            isoResponses.add(isoResponse);
            return isoResponses;
        } else {
            if (zoneId == null || zoneId == -1) {
                isoResponses = createSwiftIsoResponses(iso);
                if (!isoResponses.isEmpty()) {
                    return isoResponses;
                }
                List dcs = new ArrayList();
                dcs.addAll(ApiDBUtils.listZones());
                for (DataCenterVO dc : dcs) {
                    isoResponses.addAll(createIsoResponses(iso, dc.getId(), readyOnly));
                }
                return isoResponses;
            } else {
                return createIsoResponses(iso, zoneId, readyOnly);
            }
        }
    }

    private List createSwiftIsoResponses(VirtualMachineTemplate iso) {
        long isoId = iso.getId();
        List isoResponses = new ArrayList();
        VMTemplateSwiftVO isoSwift = ApiDBUtils.findTemplateSwiftRef(isoId);
        if (isoSwift == null) {
            return isoResponses;
        TemplateResponse isoResponse = new TemplateResponse();
        isoResponse.setId(iso.getId());
        isoResponse.setName(iso.getName());
        isoResponse.setDisplayText(iso.getDisplayText());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
        isoResponse.setCreated(isoSwift.getCreated());
        isoResponse.setReady(true);
        isoResponse.setBootable(iso.isBootable());
        isoResponse.setFeatured(iso.isFeatured());
        isoResponse.setCrossZones(iso.isCrossZones());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setChecksum(iso.getChecksum());
        isoResponse.setDetails(iso.getDetails());

        // TODO: implement
        GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId());
        if (os != null) {
            isoResponse.setOsTypeId(os.getId());
            isoResponse.setOsTypeName(os.getDisplayName());
        } else {
            isoResponse.setOsTypeId(-1L);
            isoResponse.setOsTypeName("");
        }
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(iso.getAccountId());
        populateAccount(isoResponse, account.getId());
        populateDomain(isoResponse, account.getDomainId());
        boolean isAdmin = false;
        if ((account == null) || BaseCmd.isAdmin(account.getType())) {
            isAdmin = true;
        }

        // If the user is an admin, add the template download status
        if (isAdmin || account.getId() == iso.getAccountId()) {
            // add download status
            isoResponse.setStatus("Successfully Installed");
        }
        Long isoSize = isoSwift.getSize();
        if (isoSize > 0) {
            isoResponse.setSize(isoSize);
        }
        isoResponse.setObjectName("iso");
        isoResponses.add(isoResponse);
        return isoResponses;
    }

    @Override
    public List createIsoResponses(VirtualMachineTemplate iso, long zoneId, boolean readyOnly) {
        long isoId = iso.getId();
        List isoResponses = new ArrayList();
        VMTemplateHostVO isoHost = ApiDBUtils.findTemplateHostRef(isoId, zoneId, readyOnly);
        if (isoHost == null) {
            return isoResponses;
        }
        TemplateResponse isoResponse = new TemplateResponse();
        isoResponse.setId(iso.getId());
        isoResponse.setName(iso.getName());
        isoResponse.setDisplayText(iso.getDisplayText());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
        isoResponse.setCreated(isoHost.getCreated());
        isoResponse.setReady(isoHost.getDownloadState() == Status.DOWNLOADED);
        isoResponse.setBootable(iso.isBootable());
        isoResponse.setFeatured(iso.isFeatured());
        isoResponse.setCrossZones(iso.isCrossZones());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setChecksum(iso.getChecksum());
        isoResponse.setDetails(iso.getDetails());

        // TODO: implement
        GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId());
        if (os != null) {
            isoResponse.setOsTypeId(os.getId());
            isoResponse.setOsTypeName(os.getDisplayName());
        } else {
            isoResponse.setOsTypeId(-1L);
            isoResponse.setOsTypeName("");
        }

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(iso.getAccountId());
        populateAccount(isoResponse, account.getId());
        populateDomain(isoResponse, account.getDomainId());

        Account caller = UserContext.current().getCaller();
        boolean isAdmin = false;
        if ((caller == null) || BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }
        DataCenterVO datacenter = ApiDBUtils.findZoneById(zoneId);
        isoResponse.setZoneId(zoneId);
        isoResponse.setZoneName(datacenter.getName());

        // If the user is an admin, add the template download status
        if (isAdmin || caller.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();
        if (isoSize > 0) {
            isoResponse.setSize(isoSize);
        }

        //set tag information
        List tags =  ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId());

        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        isoResponse.setTags(tagResponses);

        isoResponse.setObjectName("iso");
        isoResponses.add(isoResponse);
        return isoResponses;
    }

    @Override
    public ListResponse createSecurityGroupResponses(

            List networkGroups) {
        List groupResultObjs = SecurityGroupResultObject
        .transposeNetworkGroups(networkGroups);

        ListResponse response = new ListResponse();
        List netGrpResponses = new ArrayList();
        for (SecurityGroupResultObject networkGroup : groupResultObjs) {
            SecurityGroupResponse netGrpResponse = new SecurityGroupResponse();
            netGrpResponse.setId(networkGroup.getId());
            netGrpResponse.setName(networkGroup.getName());
            netGrpResponse.setDescription(networkGroup.getDescription());

            populateOwner(netGrpResponse, networkGroup);

            List securityGroupRules = networkGroup
            .getSecurityGroupRules();
            if ((securityGroupRules != null) && !securityGroupRules.isEmpty()) {
                List ingressRulesResponse = new ArrayList();
                List egressRulesResponse = new ArrayList();
                for (SecurityGroupRuleResultObject securityGroupRule : securityGroupRules) {
                    SecurityGroupRuleResponse ruleData = new SecurityGroupRuleResponse();
                    ruleData.setRuleId(securityGroupRule.getId());
                    ruleData.setProtocol(securityGroupRule.getProtocol());

                    if ("icmp".equalsIgnoreCase(securityGroupRule.getProtocol())) {
                        ruleData.setIcmpType(securityGroupRule.getStartPort());
                        ruleData.setIcmpCode(securityGroupRule.getEndPort());
                    } else {
                        ruleData.setStartPort(securityGroupRule.getStartPort());
                        ruleData.setEndPort(securityGroupRule.getEndPort());
                    }

                    if (securityGroupRule.getAllowedSecurityGroup() != null) {
                        ruleData.setSecurityGroupName(securityGroupRule
                                .getAllowedSecurityGroup());
                        ruleData.setAccountName(securityGroupRule
                                .getAllowedSecGroupAcct());
                    } else {
                        ruleData.setCidr(securityGroupRule
                                .getAllowedSourceIpCidr());
                    }

                    if (securityGroupRule.getRuleType() == SecurityRuleType.IngressRule) {
                        ruleData.setObjectName("ingressrule");
                        ingressRulesResponse.add(ruleData);
                    } else {
                        ruleData.setObjectName("egressrule");
                        egressRulesResponse.add(ruleData);
                    }
                }
                //set tag information
                List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, networkGroup.getId());
                List tagResponses = new ArrayList();
                for (ResourceTag tag : tags) {
                    ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                    tagResponses.add(tagResponse);
                }
                netGrpResponse.setTags(tagResponses);

                netGrpResponse
                .setSecurityGroupIngressRules(ingressRulesResponse);
                netGrpResponse.setSecurityGroupEgressRules(egressRulesResponse);
            }
            netGrpResponse.setObjectName("securitygroup");
            netGrpResponses.add(netGrpResponse);
        }

        response.setResponses(netGrpResponses);
        return response;
    }

    @Override
    public SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group) {
        SecurityGroupResponse response = new SecurityGroupResponse();

        populateOwner(response, group);

        response.setDescription(group.getDescription());
        response.setId(group.getId());
        response.setName(group.getName());

        response.setObjectName("securitygroup");
        return response;

    }

    @Override
    public ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode) {
        UploadVO uploadInfo = ApiDBUtils.findUploadById(uploadId);
        ExtractResponse response = new ExtractResponse();
        response.setObjectName("template");
        response.setId(id);
        response.setName(ApiDBUtils.findTemplateById(id).getName());
        if (zoneId != null) {
            response.setZoneId(zoneId);
            response.setZoneName(ApiDBUtils.findZoneById(zoneId).getName());
        }
        response.setMode(mode);
        response.setUploadId(uploadId);
        response.setState(uploadInfo.getUploadState().toString());
        response.setAccountId(accountId);
        response.setUrl(uploadInfo.getUploadUrl());
        return response;

    }

    @Override
    public String toSerializedString(CreateCmdResponse response, String responseType) {
        return ApiResponseSerializer.toSerializedString(response, responseType);
    }

    @Override
    public AsyncJobResponse createAsyncJobResponse(AsyncJob job) {
        AsyncJobResponse jobResponse = new AsyncJobResponse();
        jobResponse.setAccountId(job.getAccountId());
        jobResponse.setUserId(job.getUserId());
        jobResponse.setCmd(job.getCmd());
        jobResponse.setCreated(job.getCreated());
        jobResponse.setJobId(job.getId());
        jobResponse.setJobStatus(job.getStatus());
        jobResponse.setJobProcStatus(job.getProcessStatus());

        if (job.getInstanceType() != null && job.getInstanceId() != null) {
            jobResponse.setJobInstanceType(job.getInstanceType().toString());
            jobResponse.setJobInstanceId(job.getInstanceId());
        }
        jobResponse.setJobResultCode(job.getResultCode());

        boolean savedValue = SerializationContext.current().getUuidTranslation();
        SerializationContext.current().setUuidTranslation(false);

        Object resultObject = ApiSerializerHelper.fromSerializedString(job.getResult());
        jobResponse.setJobResult((ResponseObject) resultObject);
        SerializationContext.current().setUuidTranslation(savedValue);

        if (resultObject != null) {
            Class clz = resultObject.getClass();
            if (clz.isPrimitive() || clz.getSuperclass() == Number.class || clz == String.class || clz == Date.class) {
                jobResponse.setJobResultType("text");
            } else {
                jobResponse.setJobResultType("object");
            }
        }

        jobResponse.setObjectName("asyncjobs");
        return jobResponse;
    }

    @Override
    public List createTemplateResponses(long templateId, Long snapshotId, Long volumeId, boolean readyOnly) {
        VolumeVO volume = null;
        if (snapshotId != null) {
            Snapshot snapshot = ApiDBUtils.findSnapshotById(snapshotId);
            volume = findVolumeById(snapshot.getVolumeId());
        } else {
            volume = findVolumeById(volumeId);
        }
        return createTemplateResponses(templateId, volume.getDataCenterId(), readyOnly);
    }

    @Override
    public List createTemplateResponses(long templateId, Long vmId) {
        UserVm vm = findUserVmById(vmId);
        Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
        Host host = findHostById(hostId);
        return createTemplateResponses(templateId, host.getDataCenterId(), true);
    }

    @Override
    public EventResponse createEventResponse(Event event) {
        EventResponse responseEvent = new EventResponse();
        responseEvent.setCreated(event.getCreateDate());
        responseEvent.setDescription(event.getDescription());
        responseEvent.setEventType(event.getType());
        responseEvent.setId(event.getId());
        responseEvent.setLevel(event.getLevel());
        responseEvent.setParentId(event.getStartId());
        responseEvent.setState(event.getState());

        populateOwner(responseEvent, event);

        User user = ApiDBUtils.findUserById(event.getUserId());
        if (user != null) {
            responseEvent.setUsername(user.getUsername());
        }

        responseEvent.setObjectName("event");
        return responseEvent;
    }

    private List sumCapacities(List hostCapacities) {
        Map totalCapacityMap = new HashMap();
        Map usedCapacityMap = new HashMap();

        Set poolIdsToIgnore = new HashSet();
        Criteria c = new Criteria();
        // TODO: implement
        List allStoragePools = ApiDBUtils.searchForStoragePools(c);
        for (StoragePoolVO pool : allStoragePools) {
            StoragePoolType poolType = pool.getPoolType();
            if (!(poolType.isShared())) {// All the non shared storages shouldn't show up in the capacity calculation
                poolIdsToIgnore.add(pool.getId());
            }
        }

        float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

        // collect all the capacity types, sum allocated/used and sum total...get one capacity number for each
        for (Capacity capacity : hostCapacities) {

            // check if zone exist
            DataCenter zone = ApiDBUtils.findZoneById(capacity.getDataCenterId());
            if (zone == null) {
                continue;
            }

            short capacityType = capacity.getCapacityType();

            // If local storage then ignore
            if ((capacityType == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED || capacityType == Capacity.CAPACITY_TYPE_STORAGE)
                    && poolIdsToIgnore.contains(capacity.getHostOrPoolId())) {
                continue;
            }

            String key = capacity.getCapacityType() + "_" + capacity.getDataCenterId();
            String keyForPodTotal = key + "_-1";

            boolean sumPodCapacity = false;
            if (capacity.getPodId() != null) {
                key += "_" + capacity.getPodId();
                sumPodCapacity = true;
            }

            Long totalCapacity = totalCapacityMap.get(key);
            Long usedCapacity = usedCapacityMap.get(key);

            // reset overprovisioning factor to 1
            float overprovisioningFactor = 1;
            if (capacityType == Capacity.CAPACITY_TYPE_CPU) {
                overprovisioningFactor = cpuOverprovisioningFactor;
            }

            if (totalCapacity == null) {
                totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor));
            } else {
                totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity;
            }

            if (usedCapacity == null) {
                usedCapacity = new Long(capacity.getUsedCapacity());
            } else {
                usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity);
            }

            if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved
                // Capacity
                // accounts
                // for
                // stopped
                // vms
                // that
                // have been
                // stopped
                // within
                // interval
                usedCapacity += capacity.getReservedCapacity();
            }

            totalCapacityMap.put(key, totalCapacity);
            usedCapacityMap.put(key, usedCapacity);

            if (sumPodCapacity) {
                totalCapacity = totalCapacityMap.get(keyForPodTotal);
                usedCapacity = usedCapacityMap.get(keyForPodTotal);

                overprovisioningFactor = 1;
                if (capacityType == Capacity.CAPACITY_TYPE_CPU) {
                    overprovisioningFactor = cpuOverprovisioningFactor;
                }

                if (totalCapacity == null) {
                    totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor));
                } else {
                    totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity;
                }

                if (usedCapacity == null) {
                    usedCapacity = new Long(capacity.getUsedCapacity());
                } else {
                    usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity);
                }

                if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved
                    // Capacity
                    // accounts
                    // for
                    // stopped
                    // vms
                    // that
                    // have
                    // been
                    // stopped
                    // within
                    // an
                    // interval
                    usedCapacity += capacity.getReservedCapacity();
                }

                totalCapacityMap.put(keyForPodTotal, totalCapacity);
                usedCapacityMap.put(keyForPodTotal, usedCapacity);
            }
        }

        List summedCapacities = new ArrayList();
        for (String key : totalCapacityMap.keySet()) {
            CapacityVO summedCapacity = new CapacityVO();

            StringTokenizer st = new StringTokenizer(key, "_");
            summedCapacity.setCapacityType(Short.parseShort(st.nextToken()));
            summedCapacity.setDataCenterId(Long.parseLong(st.nextToken()));
            if (st.hasMoreTokens()) {
                summedCapacity.setPodId(Long.parseLong(st.nextToken()));
            }

            summedCapacity.setTotalCapacity(totalCapacityMap.get(key));
            summedCapacity.setUsedCapacity(usedCapacityMap.get(key));

            summedCapacities.add(summedCapacity);
        }
        return summedCapacities;
    }

    @Override
    public List createCapacityResponse(List result, DecimalFormat format) {
        List capacityResponses = new ArrayList();

        for (Capacity summedCapacity : result) {
            CapacityResponse capacityResponse = new CapacityResponse();
            capacityResponse.setCapacityTotal(summedCapacity.getTotalCapacity());
            capacityResponse.setCapacityType(summedCapacity.getCapacityType());
            capacityResponse.setCapacityUsed(summedCapacity.getUsedCapacity());
            if (summedCapacity.getPodId() != null) {
                capacityResponse.setPodId(summedCapacity.getPodId());
                HostPodVO pod = ApiDBUtils.findPodById(summedCapacity.getPodId());
                if (pod != null) {
                    capacityResponse.setPodName(pod.getName());
                }
            }
            if (summedCapacity.getClusterId() != null) {
                capacityResponse.setClusterId(summedCapacity.getClusterId());
                ClusterVO cluster = ApiDBUtils.findClusterById(summedCapacity.getClusterId());
                if (cluster != null) {
                    capacityResponse.setClusterName(cluster.getName());
                    if (summedCapacity.getPodId() == null) {
                        long podId = cluster.getPodId();
                        capacityResponse.setPodId(podId);
                        capacityResponse.setPodName(ApiDBUtils.findPodById(podId).getName());
                    }
                }
            }
            capacityResponse.setZoneId(summedCapacity.getDataCenterId());
            capacityResponse.setZoneName(ApiDBUtils.findZoneById(summedCapacity.getDataCenterId()).getName());
            if (summedCapacity.getUsedPercentage() != null){
                capacityResponse.setPercentUsed(format.format(summedCapacity.getUsedPercentage() * 100f));
            } else if (summedCapacity.getTotalCapacity() != 0) {
                capacityResponse.setPercentUsed(format.format((float) summedCapacity.getUsedCapacity() / (float) summedCapacity.getTotalCapacity() * 100f));
            } else {
                capacityResponse.setPercentUsed(format.format(0L));
            }

            capacityResponse.setObjectName("capacity");
            capacityResponses.add(capacityResponse);
        }

        return capacityResponses;
    }

    @Override
    public TemplatePermissionsResponse createTemplatePermissionsResponse(List accountNames, Long id, boolean isAdmin) {
        Long templateOwnerDomain = null;
        VirtualMachineTemplate template = ApiDBUtils.findTemplateById(id);
        Account templateOwner = ApiDBUtils.findAccountById(template.getAccountId());
        if (isAdmin) {
            // FIXME: we have just template id and need to get template owner from that
            if (templateOwner != null) {
                templateOwnerDomain = templateOwner.getDomainId();
            }
        }

        TemplatePermissionsResponse response = new TemplatePermissionsResponse();
    @Override
        }
        response.setId(template.getId());
        response.setPublicTemplate(template.isPublicTemplate());
        if (isAdmin && (templateOwnerDomain != null)) {
            response.setDomainId(templateOwnerDomain);
        }

        // Set accounts
        List projectIds = new ArrayList();
        List regularAccounts = new ArrayList();
        for (String accountName : accountNames) {
            Account account = ApiDBUtils.findAccountByNameDomain(accountName, templateOwner.getDomainId());
            if (account.getType() != Account.ACCOUNT_TYPE_PROJECT) {
                regularAccounts.add(accountName);
            } else {
                // convert account to projectIds
                Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());

                if (project.getUuid() != null && !project.getUuid().isEmpty())
                    projectIds.add(project.getUuid());
                else
                    projectIds.add(String.valueOf(project.getId()));
            }
        }

        if (!projectIds.isEmpty()) {
            response.setProjectIds(projectIds);
        }

        if (!regularAccounts.isEmpty()) {
            response.setAccountNames(regularAccounts);
        }

        response.setObjectName("templatepermission");
        return response;
    }

    @Override
    public AsyncJobResponse queryJobResult(QueryAsyncJobResultCmd cmd) {
        AsyncJob result = ApiDBUtils._asyncMgr.queryAsyncJobResult(cmd);
        return createAsyncJobResponse(result);
    }

    @Override
    public SecurityGroupResponse createSecurityGroupResponseFromSecurityGroupRule(List securityRules) {
        SecurityGroupResponse response = new SecurityGroupResponse();
        Map securiytGroupAccounts = new HashMap();
        Map allowedSecurityGroups = new HashMap();
        Map allowedSecuriytGroupAccounts = new HashMap();

        response.setId(network.getId());
        if ((securityRules != null) && !securityRules.isEmpty()) {
            SecurityGroup securityGroup = ApiDBUtils.findSecurityGroupById(securityRules.get(0).getSecurityGroupId());
            response.setId(securityGroup.getId());
            response.setName(securityGroup.getName());
            response.setDescription(securityGroup.getDescription());

            Account account = securiytGroupAccounts.get(securityGroup.getAccountId());

            if (account == null) {
                account = ApiDBUtils.findAccountById(securityGroup.getAccountId());
                securiytGroupAccounts.put(securityGroup.getAccountId(), account);
            }

            populateAccount(response, account.getId());
            populateDomain(response, account.getDomainId());

            List egressResponses = new ArrayList();
            List ingressResponses = new ArrayList();
            for (SecurityRule securityRule : securityRules) {
                SecurityGroupRuleResponse securityGroupData = new SecurityGroupRuleResponse();

                securityGroupData.setRuleId(securityRule.getId());
                securityGroupData.setProtocol(securityRule.getProtocol());
                if ("icmp".equalsIgnoreCase(securityRule.getProtocol())) {
                    securityGroupData.setIcmpType(securityRule.getStartPort());
                    securityGroupData.setIcmpCode(securityRule.getEndPort());
                } else {
                    securityGroupData.setStartPort(securityRule.getStartPort());
                    securityGroupData.setEndPort(securityRule.getEndPort());
                }

                Long allowedSecurityGroupId = securityRule.getAllowedNetworkId();
                if (allowedSecurityGroupId != null) {
                    SecurityGroup allowedSecurityGroup = allowedSecurityGroups.get(allowedSecurityGroupId);
                    if (allowedSecurityGroup == null) {
                        allowedSecurityGroup = ApiDBUtils.findSecurityGroupById(allowedSecurityGroupId);
                        allowedSecurityGroups.put(allowedSecurityGroupId, allowedSecurityGroup);
                    }

                    securityGroupData.setSecurityGroupName(allowedSecurityGroup.getName());

                    Account allowedAccount = allowedSecuriytGroupAccounts.get(allowedSecurityGroup.getAccountId());
                    if (allowedAccount == null) {
                        allowedAccount = ApiDBUtils.findAccountById(allowedSecurityGroup.getAccountId());
                        allowedSecuriytGroupAccounts.put(allowedAccount.getId(), allowedAccount);
                    }

                    securityGroupData.setAccountName(allowedAccount.getAccountName());
                } else {
                    securityGroupData.setCidr(securityRule.getAllowedSourceIpCidr());
                }
                if (securityRule.getRuleType() == SecurityRuleType.IngressRule) {
                    securityGroupData.setObjectName("ingressrule");
                    ingressResponses.add(securityGroupData);
                } else {
                    securityGroupData.setObjectName("egressrule");
                    egressResponses.add(securityGroupData);
                }

            }
            response.setSecurityGroupIngressRules(ingressResponses);
            response.setSecurityGroupEgressRules(egressResponses);
            response.setObjectName("securitygroup");

        }
        return response;
    }

    @Override
    public NetworkOfferingResponse createNetworkOfferingResponse(NetworkOffering offering) {
        NetworkOfferingResponse response = new NetworkOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setTags(offering.getTags());
        response.setTrafficType(offering.getTrafficType().toString());
        response.setIsDefault(offering.isDefault());
        response.setSpecifyVlan(offering.getSpecifyVlan());
        response.setConserveMode(offering.isConserveMode());
        response.setSpecifyIpRanges(offering.getSpecifyIpRanges());
        response.setAvailability(offering.getAvailability().toString());
        response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId()));
        if (offering.getServiceOfferingId() != null) {
            response.setServiceOfferingId(offering.getServiceOfferingId());
        } else {
            response.setServiceOfferingId(ApiDBUtils.findDefaultRouterServiceOffering());
        }
        if (offering.getGuestType() != null) {
            response.setGuestIpType(offering.getGuestType().toString());
        }

        response.setState(offering.getState().name());

        Map> serviceProviderMap = ApiDBUtils.listNetworkOfferingServices(offering.getId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            if (Service.Lb == service) {
                List lbCapResponse = new ArrayList();

                CapabilityResponse lbIsoaltion = new CapabilityResponse();
                lbIsoaltion.setName(Capability.SupportedLBIsolation.getName());
                lbIsoaltion.setValue(offering.getDedicatedLB() ? "dedicated" : "shared");
                lbCapResponse.add(lbIsoaltion);

                CapabilityResponse eLb = new CapabilityResponse();
                eLb.setName(Capability.ElasticLb.getName());
                eLb.setValue(offering.getElasticLb() ? "true" : "false");
                lbCapResponse.add(eLb);

                svcRsp.setCapabilities(lbCapResponse);
            } else if (Service.SourceNat == service) {
                List capabilities = new ArrayList();
                CapabilityResponse sharedSourceNat = new CapabilityResponse();
                sharedSourceNat.setName(Capability.SupportedSourceNatTypes.getName());
                sharedSourceNat.setValue(offering.getSharedSourceNat() ? "perzone" : "peraccount");
                capabilities.add(sharedSourceNat);

                CapabilityResponse redundantRouter = new CapabilityResponse();
                redundantRouter.setName(Capability.RedundantRouter.getName());
                redundantRouter.setValue(offering.getRedundantRouter() ? "true" : "false");
                capabilities.add(redundantRouter);

                svcRsp.setCapabilities(capabilities);
            } else if (service == Service.StaticNat) {
                List staticNatCapResponse = new ArrayList();

                CapabilityResponse eIp = new CapabilityResponse();
                eIp.setName(Capability.ElasticIp.getName());
                eIp.setValue(offering.getElasticLb() ? "true" : "false");
                staticNatCapResponse.add(eIp);

                svcRsp.setCapabilities(staticNatCapResponse);
            }

            serviceResponses.add(svcRsp);
        }
        response.setForVpc(ApiDBUtils.isOfferingForVpc(offering));

        response.setServices(serviceResponses);
        response.setObjectName("networkoffering");
        return response;
    }

    @Override
    public NetworkResponse createNetworkResponse(Network network) {
        // need to get network profile in order to retrieve dns information from there
        NetworkProfile profile = ApiDBUtils.getNetworkProfile(network.getId());
        NetworkResponse response = new NetworkResponse();
        response.setName(network.getName());
        response.setDisplaytext(network.getDisplayText());
        if (network.getBroadcastDomainType() != null) {
            response.setBroadcastDomainType(network.getBroadcastDomainType().toString());
        }

        if (network.getTrafficType() != null) {
            response.setTrafficType(network.getTrafficType().name());
        }

        if (network.getGuestType() != null) {
            response.setType(network.getGuestType().toString());
        }

        response.setGateway(network.getGateway());

        // FIXME - either set netmask or cidr
        response.setCidr(network.getCidr());
        if (network.getCidr() != null) {
            response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
        }

        if (network.getBroadcastUri() != null) {
            String broadcastUri = network.getBroadcastUri().toString();
            response.setBroadcastUri(broadcastUri);
            String vlan="N/A";
            if (broadcastUri.startsWith("vlan")) {
                vlan = broadcastUri.substring("vlan://".length(), broadcastUri.length());
            }
            response.setVlan(vlan);
        }

        DataCenter zone = ApiDBUtils.findZoneById(network.getDataCenterId());
        response.setZoneId(network.getDataCenterId());
        response.setZoneName(zone.getName());
        response.setPhysicalNetworkId(network.getPhysicalNetworkId());

        // populate network offering information
        NetworkOffering networkOffering = ApiDBUtils.findNetworkOfferingById(network.getNetworkOfferingId());
        if (networkOffering != null) {
            response.setNetworkOfferingId(networkOffering.getId());
            response.setNetworkOfferingName(networkOffering.getName());
            response.setNetworkOfferingDisplayText(networkOffering.getDisplayText());
            response.setIsSystem(networkOffering.isSystemOnly());
            response.setNetworkOfferingAvailability(networkOffering.getAvailability().toString());
        }

        if (network.getAclType() != null) {
            response.setAclType(network.getAclType().toString());
        }
        response.setState(network.getState().toString());
        response.setRestartRequired(network.isRestartRequired());
        response.setRelated(network.getRelated());
        response.setNetworkDomain(network.getNetworkDomain());

        response.setDns1(profile.getDns1());
        response.setDns2(profile.getDns2());
        // populate capability
        Map> serviceCapabilitiesMap = ApiDBUtils.getNetworkCapabilities(network.getId(), network.getDataCenterId());
        List serviceResponses = new ArrayList();
        if (serviceCapabilitiesMap != null) {
            for (Service service : serviceCapabilitiesMap.keySet()) {
                ServiceResponse serviceResponse = new ServiceResponse();
                // skip gateway service
                if (service == Service.Gateway) {
                    continue;
                }
                serviceResponse.setName(service.getName());

                // set list of capabilities for the service
                List capabilityResponses = new ArrayList();
                Map serviceCapabilities = serviceCapabilitiesMap.get(service);
                if (serviceCapabilities != null) {
                    for (Capability capability : serviceCapabilities.keySet()) {
                        CapabilityResponse capabilityResponse = new CapabilityResponse();
                        String capabilityValue = serviceCapabilities.get(capability);
                        capabilityResponse.setName(capability.getName());
                        capabilityResponse.setValue(capabilityValue);
                        capabilityResponse.setObjectName("capability");
                        capabilityResponses.add(capabilityResponse);
                    }
                    serviceResponse.setCapabilities(capabilityResponses);
                serviceResponse.setObjectName("service");
                serviceResponses.add(serviceResponse);
            }
        }
        response.setServices(serviceResponses);

        if (network.getAclType() == null || network.getAclType() == ACLType.Account) {
            populateOwner(response, network);
        } else {
            // get domain from network_domain table
            Pair domainNetworkDetails = ApiDBUtils.getDomainNetworkDetails(network.getId());
            response.setDomainId(domainNetworkDetails.first());
            response.setSubdomainAccess(domainNetworkDetails.second());
        }

        Long dedicatedDomainId = ApiDBUtils.getDedicatedNetworkDomain(network.getId());
        if (dedicatedDomainId != null) {
            Domain domain = ApiDBUtils.findDomainById(dedicatedDomainId);
            response.setDomainId(dedicatedDomainId);
            response.setDomainName(domain.getName());
        }

        response.setSpecifyIpRanges(network.getSpecifyIpRanges());
        response.setCanUseForDeploy(ApiDBUtils.canUseForDeploy(network));
        response.setVpcId(network.getVpcId());

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Network, network.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("network");
        return response;
    }

    public Long getSecurityGroupId(String groupName, long accountId) {
        SecurityGroup sg = ApiDBUtils.getSecurityGroup(groupName, accountId);
        if (sg == null) {
            return null;
        } else {
            return sg.getId();
        }
    }

    @Override
    public ProjectResponse createProjectResponse(Project project) {
        ProjectResponse response = new ProjectResponse();
        response.setId(project.getId());
        response.setName(project.getName());
        response.setDisplaytext(project.getDisplayText());
        response.setState(project.getState().toString());

        Domain domain = ApiDBUtils.findDomainById(project.getDomainId());
        response.setDomainId(domain.getId());
        response.setDomain(domain.getName());

        response.setOwner(ApiDBUtils.getProjectOwner(project.getId()).getAccountName());

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Project, project.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("project");
        return response;
    }

    @Override
    public FirewallResponse createFirewallResponse(FirewallRule fwRule) {
        FirewallResponse response = new FirewallResponse();

        response.setId(fwRule.getId());
        response.setProtocol(fwRule.getProtocol());
        if (fwRule.getSourcePortStart() != null) {
            response.setStartPort(Integer.toString(fwRule.getSourcePortStart()));
        }

        if (fwRule.getSourcePortEnd() != null) {
            response.setEndPort(Integer.toString(fwRule.getSourcePortEnd()));
        }

        List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setIcmpCode(fwRule.getIcmpCode());
        response.setIcmpType(fwRule.getIcmpType());

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.FirewallRule, fwRule.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setState(stateToSet);
        response.setObjectName("firewallrule");
        return response;
    }

    @Override
    public NetworkACLResponse createNetworkACLResponse(FirewallRule networkACL) {
        NetworkACLResponse response = new NetworkACLResponse();

        response.setId(networkACL.getId());
        response.setProtocol(networkACL.getProtocol());
        if (networkACL.getSourcePortStart() != null) {
            response.setStartPort(Integer.toString(networkACL.getSourcePortStart()));
        }

        if (networkACL.getSourcePortEnd() != null) {
            response.setEndPort(Integer.toString(networkACL.getSourcePortEnd()));

        List cidrs = ApiDBUtils.findFirewallSourceCidrs(networkACL.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        response.setTrafficType(networkACL.getTrafficType().toString());

        FirewallRule.State state = networkACL.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setIcmpCode(networkACL.getIcmpCode());
        response.setIcmpType(networkACL.getIcmpType());

        response.setState(stateToSet);

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.NetworkACL, networkACL.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("networkacl");
        return response;
    }

    public UserVmData newUserVmData(UserVm userVm) {
        UserVmData userVmData = new UserVmData();
        userVmData.setId(userVm.getId());
        userVmData.setName(userVm.getHostName());
        userVmData.setCreated(userVm.getCreated());
        userVmData.setGuestOsId(userVm.getGuestOSId());
        userVmData.setHaEnable(userVm.isHaEnabled());
        if (userVm.getState() != null) {
            userVmData.setState(userVm.getState().toString());
        }
        if (userVm.getDisplayName() != null) {
            userVmData.setDisplayName(userVm.getDisplayName());
        } else {
            userVmData.setDisplayName(userVm.getHostName());
        }
        userVmData.setInstanceName(userVm.getInstanceName());

        userVmData.setDomainId(userVm.getDomainId());

        if (userVm.getHypervisorType() != null) {
            userVmData.setHypervisor(userVm.getHypervisorType().toString());
        }

        if (userVm.getPassword() != null) {
            userVmData.setPassword(userVm.getPassword());
        }
        return userVmData;
    }

    public UserVmResponse newUserVmResponse(UserVmData userVmData, boolean caller_is_admin) {
        UserVmResponse userVmResponse = new UserVmResponse();

        userVmResponse.setHypervisor(userVmData.getHypervisor());
        userVmResponse.setId(userVmData.getId());
        userVmResponse.setName(userVmData.getName());

        userVmResponse.setDisplayName(userVmData.getDisplayName());

        populateAccount(userVmResponse, userVmData.getAccountId());
        populateDomain(userVmResponse, userVmData.getDomainId());

        userVmResponse.setCreated(userVmData.getCreated());
        userVmResponse.setState(userVmData.getState());
        userVmResponse.setHaEnable(userVmData.getHaEnable());
        userVmResponse.setGroupId(userVmData.getGroupId());
        userVmResponse.setGroup(userVmData.getGroup());
        userVmResponse.setZoneId(userVmData.getZoneId());
        userVmResponse.setZoneName(userVmData.getZoneName());
        if (caller_is_admin) {
            userVmResponse.setInstanceName(userVmData.getInstanceName());
            userVmResponse.setHostId(userVmData.getHostId());
            userVmResponse.setHostName(userVmData.getHostName());
        }
        userVmResponse.setTemplateId(userVmData.getTemplateId());
        userVmResponse.setTemplateName(userVmData.getTemplateName());
        userVmResponse.setTemplateDisplayText(userVmData.getTemplateDisplayText());
        userVmResponse.setPasswordEnabled(userVmData.getPasswordEnabled());
        userVmResponse.setIsoId(userVmData.getIsoId());
        userVmResponse.setIsoName(userVmData.getIsoName());
        userVmResponse.setIsoDisplayText(userVmData.getIsoDisplayText());
        userVmResponse.setServiceOfferingId(userVmData.getServiceOfferingId());
        userVmResponse.setServiceOfferingName(userVmData.getServiceOfferingName());
        userVmResponse.setCpuNumber(userVmData.getCpuNumber());
        userVmResponse.setCpuSpeed(userVmData.getCpuSpeed());
        userVmResponse.setMemory(userVmData.getMemory());
        userVmResponse.setCpuUsed(userVmData.getCpuUsed());
        userVmResponse.setNetworkKbsRead(userVmData.getNetworkKbsRead());
        userVmResponse.setNetworkKbsWrite(userVmData.getNetworkKbsWrite());
        userVmResponse.setGuestOsId(userVmData.getGuestOsId());
        userVmResponse.setRootDeviceId(userVmData.getRootDeviceId());
        userVmResponse.setRootDeviceType(userVmData.getRootDeviceType());
        userVmResponse.setPassword(userVmData.getPassword());
        userVmResponse.setJobId(userVmData.getJobId());
        userVmResponse.setJobStatus(userVmData.getJobStatus());
        userVmResponse.setForVirtualNetwork(userVmData.getForVirtualNetwork());

        Set securityGroupResponse = new HashSet();
        for (SecurityGroupData sgd : userVmData.getSecurityGroupList()) {
            if (sgd.getId() != null) {
                SecurityGroupResponse sgr = new SecurityGroupResponse();
                sgr.setId(sgd.getId());
                sgr.setName(sgd.getName());
                sgr.setDescription(sgd.getDescription());

                Account account = ApiDBUtils.findAccountByNameDomain(sgd.getAccountName(), sgd.getDomainId());
                if (account != null) {
                    populateAccount(sgr, account.getId());
                    populateDomain(sgr, account.getDomainId());
                }

                sgr.setObjectName(sgd.getObjectName());
                securityGroupResponse.add(sgr);
            }
        }
        userVmResponse.setSecurityGroupList(new ArrayList(securityGroupResponse));

        Set nicResponses = new HashSet();
        for (NicData nd : userVmData.getNics()) {
            NicResponse nr = new NicResponse();
            nr.setId(nd.getId());
            nr.setNetworkid(nd.getNetworkid());
            nr.setNetmask(nd.getNetmask());
            nr.setGateway(nd.getGateway());
            nr.setIpaddress(nd.getIpaddress());
            nr.setIsolationUri(nd.getIsolationUri());
            nr.setBroadcastUri(nd.getBroadcastUri());
            nr.setTrafficType(nd.getTrafficType());
            nr.setType(nd.getType());
            nr.setIsDefault(nd.getIsDefault());
            nr.setMacAddress(nd.getMacAddress());
            nr.setObjectName(nd.getObjectName());
            nicResponses.add(nr);
        }
        userVmResponse.setNics(new ArrayList(nicResponses));
        userVmResponse.setPublicIpId(userVmData.getPublicIpId());
        userVmResponse.setPublicIp(userVmData.getPublicIp());

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, userVmData.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        userVmResponse.setTags(tagResponses);

        return userVmResponse;
    }

    @Override
    public HypervisorCapabilitiesResponse createHypervisorCapabilitiesResponse(HypervisorCapabilities hpvCapabilities) {
        HypervisorCapabilitiesResponse hpvCapabilitiesResponse = new HypervisorCapabilitiesResponse();
        hpvCapabilitiesResponse.setId(hpvCapabilities.getId());
        hpvCapabilitiesResponse.setHypervisor(hpvCapabilities.getHypervisorType());
        hpvCapabilitiesResponse.setHypervisorVersion(hpvCapabilities.getHypervisorVersion());
        hpvCapabilitiesResponse.setIsSecurityGroupEnabled(hpvCapabilities.isSecurityGroupEnabled());
        hpvCapabilitiesResponse.setMaxGuestsLimit(hpvCapabilities.getMaxGuestsLimit());
        return hpvCapabilitiesResponse;
    }

    private void populateOwner(ControlledEntityResponse response, ControlledEntity object) {
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(object.getAccountId());

        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
            // find the project
            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
            response.setProjectId(project.getId());
            response.setProjectName(project.getName());
        } else {
            response.setAccountName(account.getAccountName());
        }

        Domain domain = ApiDBUtils.findDomainById(object.getDomainId());
        response.setDomainId(domain.getId());
        response.setDomainName(domain.getName());
    }

    private void populateAccount(ControlledEntityResponse response, long accountId) {
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(accountId);
        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
            // find the project
            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
            response.setProjectId(project.getId());
            response.setProjectName(project.getName());
        } else {
            response.setAccountName(account.getAccountName());
        }
    }

    private void populateDomain(ControlledEntityResponse response, long domainId) {
        Domain domain = ApiDBUtils.findDomainById(domainId);

        response.setDomainId(domain.getId());
        response.setDomainName(domain.getName());
    }

    @Override
    public ProjectAccountResponse createProjectAccountResponse(ProjectAccount projectAccount) {
        Account account = ApiDBUtils.findAccountById(projectAccount.getAccountId());
        ProjectAccountResponse projectAccountResponse = new ProjectAccountResponse();

        long projectId = projectAccount.getProjectId();
        projectAccountResponse.setProjectId(projectId);
        projectAccountResponse.setProjectName(ApiDBUtils.findProjectById(projectId).getName());

        projectAccountResponse.setId(account.getId());
        projectAccountResponse.setAccountName(account.getAccountName());
        projectAccountResponse.setAccountType(account.getType());
        projectAccountResponse.setRole(projectAccount.getAccountRole().toString());
        populateDomain(projectAccountResponse, account.getDomainId());

        // add all the users for an account as part of the response obj
        List usersForAccount = ApiDBUtils.listUsersByAccount(account.getAccountId());
        List userResponseList = new ArrayList();
        for (UserVO user : usersForAccount) {
            UserResponse userResponse = createUserResponse(user);
            userResponseList.add(userResponse);
        }

        projectAccountResponse.setUsers(userResponseList);
        projectAccountResponse.setObjectName("projectaccount");

        return projectAccountResponse;
    }

    @Override
    public ProjectInvitationResponse createProjectInvitationResponse(ProjectInvitation invite) {
        ProjectInvitationResponse response = new ProjectInvitationResponse();
        response.setId(invite.getId());
        response.setProjectId(invite.getProjectId());
        response.setProjectName(ApiDBUtils.findProjectById(invite.getProjectId()).getName());
        response.setInvitationState(invite.getState().toString());

        if (invite.getForAccountId() != null) {
            Account account = ApiDBUtils.findAccountById(invite.getForAccountId());
            response.setAccountName(account.getAccountName());

        } else {
            response.setEmail(invite.getEmail());
        }

        populateDomain(response, invite.getInDomainId());

        response.setObjectName("projectinvitation");
        return response;
    }

    @Override

    public SystemVmInstanceResponse createSystemVmInstanceResponse(VirtualMachine vm) {
        SystemVmInstanceResponse vmResponse = new SystemVmInstanceResponse();
        vmResponse.setId(vm.getId());
        vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
        vmResponse.setName(vm.getHostName());
        if (vm.getHostId() != null) {
            vmResponse.setHostId(vm.getHostId());
        }
        if (vm.getState() != null) {
            vmResponse.setState(vm.getState().toString());
        }
        if (vm.getType() == Type.DomainRouter) {
            VirtualRouter router = (VirtualRouter) vm;
            if (router.getRole() != null) {
                vmResponse.setRole(router.getRole().toString());
            }
        }
        vmResponse.setObjectName("systemvminstance");
        return vmResponse;
    }

    @Override
    public PhysicalNetworkResponse createPhysicalNetworkResponse(PhysicalNetwork result) {
        PhysicalNetworkResponse response = new PhysicalNetworkResponse();

        response.setZoneId(result.getDataCenterId());
        response.setNetworkSpeed(result.getSpeed());
        response.setVlan(result.getVnet());
        response.setDomainId(result.getDomainId());
        response.setId(result.getUuid());
        if (result.getBroadcastDomainRange() != null) {
            response.setBroadcastDomainRange(result.getBroadcastDomainRange().toString());
        }
        response.setIsolationMethods(result.getIsolationMethods());
        response.setTags(result.getTags());
        if (result.getState() != null) {
            response.setState(result.getState().toString());
        }

        response.setName(result.getName());

        response.setObjectName("physicalnetwork");
        return response;
    }

    @Override
    public ServiceResponse createNetworkServiceResponse(Service service) {
        ServiceResponse response = new ServiceResponse();
        response.setName(service.getName());

        // set list of capabilities required for the service
        List capabilityResponses = new ArrayList();
        Capability[] capabilities = service.getCapabilities();
        for (Capability cap : capabilities) {
            CapabilityResponse capabilityResponse = new CapabilityResponse();
            capabilityResponse.setName(cap.getName());
            capabilityResponse.setObjectName("capability");
            if (cap.getName().equals(Capability.SupportedLBIsolation.getName()) ||
                    cap.getName().equals(Capability.SupportedSourceNatTypes.getName()) ||
                    cap.getName().equals(Capability.RedundantRouter.getName())) {
                capabilityResponse.setCanChoose(true);
            } else {
                capabilityResponse.setCanChoose(false);
            }
            capabilityResponses.add(capabilityResponse);
        }
        response.setCapabilities(capabilityResponses);

        // set list of providers providing this service
        List serviceProviders = ApiDBUtils.getProvidersForService(service);
        List serviceProvidersResponses = new ArrayList();
        for (Network.Provider serviceProvider : serviceProviders) {
            // return only Virtual Router/JuniperSRX as a provider for the firewall
            if (service == Service.Firewall && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX)) {
                continue;
            }

            ProviderResponse serviceProviderResponse = createServiceProviderResponse(serviceProvider);
            serviceProvidersResponses.add(serviceProviderResponse);
        }
        response.setProviders(serviceProvidersResponses);

        response.setObjectName("networkservice");
        return response;

    }

    private ProviderResponse createServiceProviderResponse(Provider serviceProvider) {
        ProviderResponse response = new ProviderResponse();
        response.setName(serviceProvider.getName());
        boolean canEnableIndividualServices = ApiDBUtils.canElementEnableIndividualServices(serviceProvider);
        response.setCanEnableIndividualServices(canEnableIndividualServices);
        return response;
    }

    @Override
    public ProviderResponse createNetworkServiceProviderResponse(PhysicalNetworkServiceProvider result) {
        ProviderResponse response = new ProviderResponse();
        response.setId(result.getUuid());
        response.setName(result.getProviderName());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        response.setDestinationPhysicalNetworkId(result.getDestinationPhysicalNetworkId());
        response.setState(result.getState().toString());

        // set enabled services
        List services = new ArrayList();
        for (Service service : result.getEnabledServices()) {
            services.add(service.getName());
        }
        response.setServices(services);

        response.setObjectName("networkserviceprovider");
        return response;
    }

    @Override
    public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType result) {
        TrafficTypeResponse response = new TrafficTypeResponse();
        response.setId(result.getUuid());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        response.setTrafficType(result.getTrafficType().toString());
        response.setXenLabel(result.getXenNetworkLabel());
        response.setKvmLabel(result.getKvmNetworkLabel());
        response.setVmwareLabel(result.getVmwareNetworkLabel());

        response.setObjectName("traffictype");
        return response;
    }

    @Override
    public VirtualRouterProviderResponse createVirtualRouterProviderResponse(VirtualRouterProvider result) {
        VirtualRouterProviderResponse response = new VirtualRouterProviderResponse();
        response.setId(result.getId());
        response.setNspId(result.getNspId());
        response.setEnabled(result.isEnabled());
        response.setObjectName("virtualrouterelement");
        return response;
    }

    @Override
    public LBStickinessResponse createLBStickinessPolicyResponse(
            StickinessPolicy stickinessPolicy, LoadBalancer lb) {
        LBStickinessResponse spResponse = new LBStickinessResponse();

        spResponse.setlbRuleId(lb.getId());
        Account accountTemp = ApiDBUtils.findAccountById(lb.getAccountId());
        if (accountTemp != null) {
            spResponse.setAccountName(accountTemp.getAccountName());
            spResponse.setDomainId(accountTemp.getDomainId());
            spResponse.setDomainName(ApiDBUtils.findDomainById(
                    accountTemp.getDomainId()).getName());
        }

        List responses = new ArrayList();
        LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(
                stickinessPolicy);
        responses.add(ruleResponse);

        spResponse.setRules(responses);

        spResponse.setObjectName("stickinesspolicies");
        return spResponse;
    }

    @Override
    public LBStickinessResponse createLBStickinessPolicyResponse(
            List stickinessPolicies, LoadBalancer lb) {
        LBStickinessResponse spResponse = new LBStickinessResponse();

        if (lb == null) {
            return spResponse;
        }
        spResponse.setlbRuleId(lb.getId());
        Account account = ApiDBUtils.findAccountById(lb.getAccountId());
        if (account != null) {
            tagResponses.add(tagResponse);
            spResponse.setAccountName(account.getAccountName());
            spResponse.setDomainId(account.getDomainId());
            spResponse.setDomainName(ApiDBUtils.findDomainById(
                    account.getDomainId()).getName());
        }

        List responses = new ArrayList();
        for (StickinessPolicy stickinessPolicy : stickinessPolicies) {
            LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(stickinessPolicy);
            responses.add(ruleResponse);
        }
        spResponse.setRules(responses);

        spResponse.setObjectName("stickinesspolicies");
        return spResponse;
    }

    @Override
    public LDAPConfigResponse createLDAPConfigResponse(String hostname,
            Integer port, Boolean useSSL, String queryFilter,
            String searchBase, String bindDN) {
        LDAPConfigResponse lr = new LDAPConfigResponse();
        lr.setHostname(hostname);
        lr.setPort(port.toString());
        lr.setUseSSL(useSSL.toString());
        lr.setQueryFilter(queryFilter);
        lr.setBindDN(bindDN);
        lr.setSearchBase(searchBase);
        lr.setObjectName("ldapconfig");
        return lr;
    }

    @Override
    public StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result) {
        StorageNetworkIpRangeResponse response = new StorageNetworkIpRangeResponse();
        response.setUuid(result.getUuid());
        response.setVlan(result.getVlan());
        response.setEndIp(result.getEndIp());
        response.setStartIp(result.getStartIp());
        response.setPodUuid(result.getPodUuid());
        response.setZoneUuid(result.getZoneUuid());
        response.setNetworkUuid(result.getNetworkUuid());
        response.setNetmask(result.getNetmask());
        response.setGateway(result.getGateway());
        response.setObjectName("storagenetworkiprange");
        return response;
    }

    @Override
    public Long getIdentiyId(String tableName, String token) {
        return ApiDispatcher.getIdentiyId(tableName, token);
    }

    @Override
    public ResourceTagResponse createResourceTagResponse(ResourceTag resourceTag, boolean keyValueOnly) {
        ResourceTagResponse response = new ResourceTagResponse();
        response.setKey(resourceTag.getKey());
        response.setValue(resourceTag.getValue());

        if (!keyValueOnly) {
            response.setResourceType(resourceTag.getResourceType().toString());
            response.setId(ApiDBUtils.getUuid(String.valueOf(resourceTag.getResourceId()),resourceTag.getResourceType()));
            Long accountId = resourceTag.getAccountId();
            Long domainId = resourceTag.getDomainId();
            if (accountId != null) {
                Account account = ApiDBUtils.findAccountByIdIncludingRemoved(resourceTag.getAccountId());

                if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
                    // find the project
                    Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
                    response.setProjectId(project.getId());
                    response.setProjectName(project.getName());
                } else {
                    response.setAccountName(account.getAccountName());
                }
            }

            if (domainId != null) {
                response.setDomainId(domainId);
                response.setDomainName(ApiDBUtils.findDomainById(domainId).getName());
            }

            response.setCustomer(resourceTag.getCustomer());
        }

        response.setObjectName("tag");

        return response;
    }

    @Override
        }
    public VpcOfferingResponse createVpcOfferingResponse(VpcOffering offering) {
        VpcOfferingResponse response = new VpcOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setIsDefault(offering.isDefault());
        response.setState(offering.getState().name());

        Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            serviceResponses.add(svcRsp);
        }
        response.setServices(serviceResponses);
        response.setObjectName("vpcoffering");
        return response;
    }

    @Override
    public VpcResponse createVpcResponse(Vpc vpc) {
        VpcResponse response = new VpcResponse();
        response.setId(vpc.getId());
        response.setName(vpc.getName());
        response.setDisplayText(vpc.getDisplayText());
        response.setState(vpc.getState().name());
        response.setVpcOfferingId(vpc.getVpcOfferingId());
        response.setCidr(vpc.getCidr());
        response.setRestartRequired(vpc.isRestartRequired());
        response.setNetworkDomain(vpc.getNetworkDomain());

        Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            serviceResponses.add(svcRsp);
        }

        List networkResponses = new ArrayList();
        List networks = ApiDBUtils.listVpcNetworks(vpc.getId());
        for (Network network : networks) {
            NetworkResponse ntwkRsp = createNetworkResponse(network);
            networkResponses.add(ntwkRsp);
        }

        DataCenter zone = ApiDBUtils.findZoneById(vpc.getZoneId());
        response.setZoneId(vpc.getZoneId());
        response.setZoneName(zone.getName());

        response.setNetworks(networkResponses);
        response.setServices(serviceResponses);

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Vpc, vpc.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
        response.setTags(tagResponses);

        response.setObjectName("vpc");
        return response;
    }

    @Override
    public PrivateGatewayResponse createPrivateGatewayResponse(PrivateGateway result) {
        PrivateGatewayResponse response = new PrivateGatewayResponse();
        response.setId(result.getId());
        response.setVlan(result.getVlanTag());
        response.setGateway(result.getGateway());
        response.setNetmask(result.getNetmask());
        response.setVpcId(result.getVpcId());
        response.setZoneId(result.getZoneId());
        DataCenter zone = ApiDBUtils.findZoneById(result.getZoneId());
        response.setZoneName(zone.getName());
        response.setAddress(result.getIp4Address());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());

        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        response.setState(result.getState().toString());

        response.setObjectName("privategateway");
        return response;
    }

    @Override
    public AutoScaleVmProfileResponse createAutoScaleVmProfileResponse(AutoScaleVmProfile profile) {
        AutoScaleVmProfileResponse response = new AutoScaleVmProfileResponse();
        response.setId(profile.getId());
        response.setZoneId(profile.getZoneId());
        response.setServiceOfferingId(profile.getServiceOfferingId());
        response.setTemplateId(profile.getTemplateId());
        response.setOtherDeployParams(profile.getOtherDeployParams());
        response.setSnmpCommunity(profile.getSnmpCommunity());
        response.setSnmpPort(profile.getSnmpPort());
        response.setDestroyVmGraceperiod(profile.getDestroyVmGraceperiod());
        response.setAutoscaleUserId(profile.getAutoScaleUserId());
        response.setObjectName("autoscalevmprofile");

        // Populates the account information in the response
        populateOwner(response, profile);
        return response;
    }

    @Override
    public AutoScalePolicyResponse createAutoScalePolicyResponse(AutoScalePolicy policy) {
        AutoScalePolicyResponse response = new AutoScalePolicyResponse();
        response.setId(policy.getId());
        response.setDuration(policy.getDuration());
        response.setQuietTime(policy.getQuietTime());
        response.setAction(policy.getAction());
        List vos = ApiDBUtils.getAutoScalePolicyConditions(policy.getId());
        ArrayList conditions = new ArrayList(vos.size());
        for (ConditionVO vo : vos) {
            conditions.add(createConditionResponse(vo));
        }
        response.setConditions(conditions);
        response.setObjectName("autoscalepolicy");

        // Populates the account information in the response
        populateOwner(response, policy);

        return response;
    }

    @Override
    public AutoScaleVmGroupResponse createAutoScaleVmGroupResponse(AutoScaleVmGroup vmGroup) {
        AutoScaleVmGroupResponse response = new AutoScaleVmGroupResponse();
        response.setId(vmGroup.getId());
        response.setMinMembers(vmGroup.getMinMembers());
        response.setMaxMembers(vmGroup.getMaxMembers());
        response.setState(vmGroup.getState());
        response.setInterval(vmGroup.getInterval());
        response.setProfileId(vmGroup.getProfileId());
        response.setLoadBalancerId(vmGroup.getProfileId());

        List scaleUpPoliciesResponse = new ArrayList();
        List scaleDownPoliciesResponse = new ArrayList();
        response.setScaleUpPolicies(scaleUpPoliciesResponse);
        response.setScaleDownPolicies(scaleDownPoliciesResponse);
        response.setObjectName("autoscalevmgroup");

        // Fetch policies for vmgroup
        List scaleUpPolicies = new ArrayList();
        List scaleDownPolicies = new ArrayList();
        ApiDBUtils.getAutoScaleVmGroupPolicies(vmGroup.getId(), scaleUpPolicies, scaleDownPolicies);
        // populate policies
        for (AutoScalePolicy autoScalePolicy : scaleUpPolicies) {
            scaleUpPoliciesResponse.add(createAutoScalePolicyResponse(autoScalePolicy));
        }
        for (AutoScalePolicy autoScalePolicy : scaleDownPolicies) {
            scaleDownPoliciesResponse.add(createAutoScalePolicyResponse(autoScalePolicy));
        }

        return response;
    }

    @Override
    public StaticRouteResponse createStaticRouteResponse(StaticRoute result) {
        StaticRouteResponse response = new StaticRouteResponse();
        response.setId(result.getId());
        response.setVpcId(result.getVpcId());
        response.setCidr(result.getCidr());

        StaticRoute.State state = result.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        response.setState(stateToSet);
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());

        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.StaticRoute, result.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        response.setObjectName("staticroute");
        return response;
    }

    @Override
    public Site2SiteVpnGatewayResponse createSite2SiteVpnGatewayResponse(Site2SiteVpnGateway result) {
        Site2SiteVpnGatewayResponse response = new Site2SiteVpnGatewayResponse();
        response.setId(result.getId());
        response.setIp(ApiDBUtils.findIpAddressById(result.getAddrId()).getAddress().toString());
        response.setVpcId(result.getVpcId());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpngateway");

        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());

        return response;
    }

    @Override
    public Site2SiteCustomerGatewayResponse createSite2SiteCustomerGatewayResponse(Site2SiteCustomerGateway result) {
        Site2SiteCustomerGatewayResponse response = new Site2SiteCustomerGatewayResponse();
        response.setId(result.getId());
        response.setGatewayIp(result.getGatewayIp());
        response.setGuestCidrList(result.getGuestCidrList());
        response.setIpsecPsk(result.getIpsecPsk());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpncustomergateway");

        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());

        return response;
    }

    @Override
    public Site2SiteVpnConnectionResponse createSite2SiteVpnConnectionResponse(Site2SiteVpnConnection result) {
        Site2SiteVpnConnectionResponse response = new Site2SiteVpnConnectionResponse();
        response.setId(result.getId());

        response.setVpnGatewayId(result.getVpnGatewayId());
        Long vpnGatewayId = result.getVpnGatewayId();
        if(vpnGatewayId != null) {
            Site2SiteVpnGatewayVO vpnGateway = ApiDBUtils.findVpnGatewayById(vpnGatewayId);

            long ipId = vpnGateway.getAddrId();
            IPAddressVO ipObj = ApiDBUtils.findIpAddressById(ipId);
            response.setIp(ipObj.getAddress().addr());
        }

        response.setCustomerGatewayId(result.getCustomerGatewayId());
        Long customerGatewayId = result.getCustomerGatewayId();
        if(customerGatewayId != null) {
            Site2SiteCustomerGatewayVO customerGateway = ApiDBUtils.findCustomerGatewayById(customerGatewayId);
            response.setGatewayIp(customerGateway.getGatewayIp());
            response.setGuestCidrList(customerGateway.getGuestCidrList());
            response.setIpsecPsk(customerGateway.getIpsecPsk());
            response.setIkePolicy(customerGateway.getIkePolicy());
            response.setEspPolicy(customerGateway.getEspPolicy());
            response.setLifetime(customerGateway.getLifetime());
        }

        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());

        response.setState(result.getState().toString());
        response.setCreated(result.getCreated());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpnconnection");
        return response;
    }

    @Override
    public CounterResponse createCounterResponse(Counter counter) {
        CounterResponse response = new CounterResponse();
        response.setId(counter.getId());
        response.setSource(counter.getSource().toString());
        response.setName(counter.getName());
        response.setValue(counter.getValue());
        response.setObjectName("counter");
        return response;
    }

    @Override
    public ConditionResponse createConditionResponse(Condition condition) {
        ConditionResponse response = new ConditionResponse();
        response.setId(condition.getId());
        CounterResponse counter;
        counter = createCounterResponse(ApiDBUtils.getCounter(condition.getCounterid()));
        response.setCounter(counter);
        response.setRelationalOperator(condition.getRelationalOperator().toString());
        response.setThreshold(condition.getThreshold());
        response.setObjectName("condition");
        populateOwner(response, condition);
        return response;
    }
}
=======
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.

// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.api;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import com.cloud.acl.ControlledEntity;
import com.cloud.acl.ControlledEntity.ACLType;
import com.cloud.api.ApiConstants.HostDetails;
import com.cloud.api.ApiConstants.VMDetails;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.response.AccountResponse;
import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.api.response.AsyncJobResponse;
import com.cloud.api.response.CapabilityResponse;
import com.cloud.api.response.CapacityResponse;
import com.cloud.api.response.ClusterResponse;
import com.cloud.api.response.ConfigurationResponse;
import com.cloud.api.response.ControlledEntityResponse;
import com.cloud.api.response.CreateCmdResponse;
import com.cloud.api.response.DiskOfferingResponse;
import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.DomainRouterResponse;
import com.cloud.api.response.EventResponse;
import com.cloud.api.response.ExtractResponse;
import com.cloud.api.response.FirewallResponse;
import com.cloud.api.response.FirewallRuleResponse;
import com.cloud.api.response.HostResponse;
import com.cloud.api.response.HypervisorCapabilitiesResponse;
import com.cloud.api.response.IPAddressResponse;
import com.cloud.api.response.InstanceGroupResponse;
import com.cloud.api.response.IpForwardingRuleResponse;
import com.cloud.api.response.LBStickinessPolicyResponse;
import com.cloud.api.response.LBStickinessResponse;
import com.cloud.api.response.LDAPConfigResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.LoadBalancerResponse;
import com.cloud.api.response.NetworkACLResponse;
import com.cloud.api.response.NetworkOfferingResponse;
import com.cloud.api.response.NetworkResponse;
import com.cloud.api.response.NicResponse;
import com.cloud.api.response.PhysicalNetworkResponse;
import com.cloud.api.response.PodResponse;
import com.cloud.api.response.PrivateGatewayResponse;
import com.cloud.api.response.ProjectAccountResponse;
import com.cloud.api.response.ProjectInvitationResponse;
import com.cloud.api.response.ProjectResponse;
import com.cloud.api.response.ProviderResponse;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.api.response.ResourceCountResponse;
import com.cloud.api.response.ResourceLimitResponse;
import com.cloud.api.response.ResourceTagResponse;
import com.cloud.api.response.SecurityGroupResponse;
import com.cloud.api.response.SecurityGroupResultObject;
import com.cloud.api.response.SecurityGroupRuleResponse;
import com.cloud.api.response.SecurityGroupRuleResultObject;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.api.response.ServiceResponse;
import com.cloud.api.response.Site2SiteCustomerGatewayResponse;
import com.cloud.api.response.Site2SiteVpnConnectionResponse;
import com.cloud.api.response.Site2SiteVpnGatewayResponse;
import com.cloud.api.response.SnapshotPolicyResponse;
import com.cloud.api.response.SnapshotResponse;
import com.cloud.api.response.StaticRouteResponse;
import com.cloud.api.response.StorageNetworkIpRangeResponse;
import com.cloud.api.response.StoragePoolResponse;
import com.cloud.api.response.SwiftResponse;
import com.cloud.api.response.SystemVmInstanceResponse;
import com.cloud.api.response.SystemVmResponse;
import com.cloud.api.response.TemplatePermissionsResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.api.response.TrafficTypeResponse;
import com.cloud.api.response.UserResponse;
import com.cloud.api.response.UserVmResponse;
import com.cloud.api.response.VirtualRouterProviderResponse;
import com.cloud.api.response.VlanIpRangeResponse;
import com.cloud.api.response.VolumeResponse;
import com.cloud.api.response.VpcOfferingResponse;
import com.cloud.api.response.VpcResponse;
import com.cloud.api.response.VpnUsersResponse;
import com.cloud.api.response.ZoneResponse;
import com.cloud.async.AsyncJob;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
import com.cloud.configuration.Configuration;
import com.cloud.configuration.Resource.ResourceOwnerType;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimit;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.Pod;
import com.cloud.dc.StorageNetworkIpRange;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.domain.Domain;
import com.cloud.event.Event;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.HostStats;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.HypervisorCapabilities;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkProfile;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.Site2SiteCustomerGateway;
import com.cloud.network.Site2SiteCustomerGatewayVO;
import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.Site2SiteVpnGateway;
import com.cloud.network.Site2SiteVpnGatewayVO;
import com.cloud.network.VirtualRouterProvider;
import com.cloud.network.VpnUser;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNatRule;
import com.cloud.network.rules.StickinessPolicy;
import com.cloud.network.security.SecurityGroup;
import com.cloud.network.security.SecurityGroupRules;
import com.cloud.network.security.SecurityGroupVO;
import com.cloud.network.security.SecurityRule;
import com.cloud.network.security.SecurityRule.SecurityRuleType;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.StaticRoute;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectAccount;
import com.cloud.projects.ProjectInvitation;
import com.cloud.server.Criteria;
import com.cloud.server.ResourceTag;
import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Swift;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateSwiftVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.test.PodZoneConfig;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.InstanceGroup;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VmStats;
import com.cloud.vm.dao.UserVmData;
import com.cloud.vm.dao.UserVmData.NicData;
import com.cloud.vm.dao.UserVmData.SecurityGroupData;

public class ApiResponseHelper implements ResponseGenerator {

    public final Logger s_logger = Logger.getLogger(ApiResponseHelper.class);
    private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##");

    @Override
    public UserResponse createUserResponse(User user) {
        UserResponse userResponse = new UserResponse();
        Account account = ApiDBUtils.findAccountById(user.getAccountId());
        userResponse.setAccountName(account.getAccountName());
        userResponse.setAccountType(account.getType());
        userResponse.setCreated(user.getCreated());
        userResponse.setDomainId(account.getDomainId());
        userResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());
        userResponse.setEmail(user.getEmail());
        userResponse.setFirstname(user.getFirstname());
        userResponse.setId(user.getId());
        userResponse.setLastname(user.getLastname());
        userResponse.setState(user.getState().toString());
        userResponse.setTimezone(user.getTimezone());
        userResponse.setUsername(user.getUsername());
        userResponse.setApiKey(user.getApiKey());
        userResponse.setSecretKey(user.getSecretKey());
        userResponse.setObjectName("user");

        return userResponse;
    }

    // this method is used for response generation via createAccount (which creates an account + user)
    @Override
    public AccountResponse createUserAccountResponse(UserAccount user) {
        return createAccountResponse(ApiDBUtils.findAccountById(user.getAccountId()));
    }

    @Override
    public AccountResponse createAccountResponse(Account account) {
        boolean accountIsAdmin = (account.getType() == Account.ACCOUNT_TYPE_ADMIN);
        AccountResponse accountResponse = new AccountResponse();
        accountResponse.setId(account.getId());
        accountResponse.setName(account.getAccountName());
        accountResponse.setAccountType(account.getType());
        accountResponse.setDomainId(account.getDomainId());
        accountResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());
        accountResponse.setState(account.getState().toString());
        accountResponse.setNetworkDomain(account.getNetworkDomain());
        accountResponse.setDefaultZone(account.getDefaultZoneId());

        // get network stat
        List stats = ApiDBUtils.listUserStatsBy(account.getId());
            }
        if (stats == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching for user stats");
        }

        Long bytesSent = 0L;
        Long bytesReceived = 0L;
        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);
        }
        accountResponse.setBytesReceived(bytesReceived);
        accountResponse.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);
        accountResponse.setVmLimit(vmLimitDisplay);
        accountResponse.setVmTotal(vmTotal);
        accountResponse.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());

        Long ips = ipLimit - ipTotal;
        // check how many free ips are left, and if it's less than max allowed number of ips from account - use this
        // value
        Long ipsLeft = ApiDBUtils.countFreePublicIps();
        boolean unlimited = true;
        if (ips.longValue() > ipsLeft.longValue()) {
            ips = ipsLeft;
            unlimited = false;
        }

        String ipAvail = ((accountIsAdmin || ipLimit == -1) && unlimited) ? "Unlimited" : String.valueOf(ips);

        accountResponse.setIpLimit(ipLimitDisplay);
        accountResponse.setIpTotal(ipTotal);
        accountResponse.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);
        accountResponse.setVolumeLimit(volumeLimitDisplay);
        accountResponse.setVolumeTotal(volumeTotal);
        accountResponse.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);
        accountResponse.setSnapshotLimit(snapshotLimitDisplay);
        accountResponse.setSnapshotTotal(snapshotTotal);
        accountResponse.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);
        accountResponse.setTemplateLimit(templateLimitDisplay);
        accountResponse.setTemplateTotal(templateTotal);
        accountResponse.setTemplateAvailable(templateAvail);

        // Get stopped and running VMs
        int vmStopped = 0;
        int vmRunning = 0;

        List permittedAccounts = new ArrayList();
        permittedAccounts.add(account.getId());

        List virtualMachines = ApiDBUtils.searchForUserVMs(new Criteria(), permittedAccounts);
        // 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++;
            }
        }

        accountResponse.setVmStopped(vmStopped);
        accountResponse.setVmRunning(vmRunning);
        accountResponse.setObjectName("account");
        
        //get resource limits for projects
        Long projectLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.project, account.getId());
        String projectLimitDisplay = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit);
        Long projectTotal = ApiDBUtils.getResourceCount(ResourceType.project, account.getId());
        String projectAvail = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit - projectTotal);
        accountResponse.setProjectLimit(projectLimitDisplay);
        accountResponse.setProjectTotal(projectTotal);
        accountResponse.setProjectAvailable(projectAvail);
        
        //get resource limits for networks
        Long networkLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.network, account.getId());
        String networkLimitDisplay = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit);
        Long networkTotal = ApiDBUtils.getResourceCount(ResourceType.network, account.getId());
        String networkAvail = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit - networkTotal);
        accountResponse.setNetworkLimit(networkLimitDisplay);
        accountResponse.setNetworkTotal(networkTotal);
        accountResponse.setNetworkAvailable(networkAvail);
      
        // adding all the users for an account as part of the response obj
        List usersForAccount = ApiDBUtils.listUsersByAccount(account.getAccountId());
        List userResponseList = new ArrayList();
        for (UserVO user : usersForAccount) {
            UserResponse userResponse = createUserResponse(user);
            userResponseList.add(userResponse);
        }

        accountResponse.setUsers(userResponseList);
        accountResponse.setDetails(ApiDBUtils.getAccountDetails(account.getId()));
        return accountResponse;
    }

    @Override
    public UserResponse createUserResponse(UserAccount user) {
        UserResponse userResponse = new UserResponse();
        userResponse.setAccountName(user.getAccountName());
        userResponse.setAccountType(user.getType());
        userResponse.setCreated(user.getCreated());
        userResponse.setDomainId(user.getDomainId());
        userResponse.setDomainName(ApiDBUtils.findDomainById(user.getDomainId()).getName());
        userResponse.setEmail(user.getEmail());
        userResponse.setFirstname(user.getFirstname());
        userResponse.setId(user.getId());
        userResponse.setLastname(user.getLastname());
        userResponse.setState(user.getState());
        userResponse.setTimezone(user.getTimezone());
        userResponse.setUsername(user.getUsername());
        userResponse.setApiKey(user.getApiKey());
        userResponse.setSecretKey(user.getSecretKey());
        userResponse.setAccountId((user.getAccountId()));
        userResponse.setObjectName("user");

        return userResponse;
    }

    @Override
    public DomainResponse createDomainResponse(Domain domain) {
        DomainResponse domainResponse = new DomainResponse();
        domainResponse.setDomainName(domain.getName());
        domainResponse.setId(domain.getId());
        domainResponse.setLevel(domain.getLevel());
        domainResponse.setNetworkDomain(domain.getNetworkDomain());
        domainResponse.setParentDomainId(domain.getParent());
        StringBuilder domainPath = new StringBuilder("ROOT");  
        (domainPath.append(domain.getPath())).deleteCharAt(domainPath.length() - 1);
        domainResponse.setPath(domainPath.toString());
        if (domain.getParent() != null) {
            domainResponse.setParentDomainName(ApiDBUtils.findDomainById(domain.getParent()).getName());
        }
        if (domain.getChildCount() > 0) {
            domainResponse.setHasChild(true);
        }
        domainResponse.setObjectName("domain");
        return domainResponse;
    }

    @Override
    public DiskOfferingResponse createDiskOfferingResponse(DiskOffering offering) {
        DiskOfferingResponse diskOfferingResponse = new DiskOfferingResponse();
        diskOfferingResponse.setId(offering.getId());
        diskOfferingResponse.setName(offering.getName());
        diskOfferingResponse.setDisplayText(offering.getDisplayText());
        diskOfferingResponse.setCreated(offering.getCreated());
        diskOfferingResponse.setDiskSize(offering.getDiskSize() / (1024 * 1024 * 1024));
        if (offering.getDomainId() != null) {
            diskOfferingResponse.setDomain(ApiDBUtils.findDomainById(offering.getDomainId()).getName());
            diskOfferingResponse.setDomainId(offering.getDomainId());
        }
        diskOfferingResponse.setTags(offering.getTags());
        diskOfferingResponse.setCustomized(offering.isCustomized());
        diskOfferingResponse.setObjectName("diskoffering");
        return diskOfferingResponse;
    }

    @Override
    public ResourceLimitResponse createResourceLimitResponse(ResourceLimit limit) {
        ResourceLimitResponse resourceLimitResponse = new ResourceLimitResponse();
        if (limit.getResourceOwnerType() == ResourceOwnerType.Domain) {
            populateDomain(resourceLimitResponse, limit.getOwnerId());
        } else if (limit.getResourceOwnerType() == ResourceOwnerType.Account) {
            Account accountTemp = ApiDBUtils.findAccountById(limit.getOwnerId());
            populateAccount(resourceLimitResponse, limit.getOwnerId());
        }
            populateDomain(resourceLimitResponse, accountTemp.getDomainId());
        }
        resourceLimitResponse.setResourceType(Integer.valueOf(limit.getType().getOrdinal()).toString());
        resourceLimitResponse.setMax(limit.getMax());
        resourceLimitResponse.setObjectName("resourcelimit");

        return resourceLimitResponse;
    }

    @Override
    public ResourceCountResponse createResourceCountResponse(ResourceCount resourceCount) {
        ResourceCountResponse resourceCountResponse = new ResourceCountResponse();

        if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Account) {
            Account accountTemp = ApiDBUtils.findAccountById(resourceCount.getOwnerId());
            if (accountTemp != null) {
                populateAccount(resourceCountResponse, accountTemp.getId());
                populateDomain(resourceCountResponse, accountTemp.getDomainId());
            }
        } else if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Domain) {
            populateDomain(resourceCountResponse, resourceCount.getOwnerId());
        }

        resourceCountResponse.setResourceType(Integer.valueOf(resourceCount.getType().getOrdinal()).toString());
        resourceCountResponse.setResourceCount(resourceCount.getCount());
        resourceCountResponse.setObjectName("resourcecount");
        return resourceCountResponse;
    }

    @Override
    public ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering) {
        ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();
        offeringResponse.setId(offering.getId());
        offeringResponse.setName(offering.getName());
        offeringResponse.setIsSystemOffering(offering.getSystemUse());
        offeringResponse.setDefaultUse(offering.getDefaultUse());
        offeringResponse.setSystemVmType(offering.getSystemVmType());
        offeringResponse.setDisplayText(offering.getDisplayText());
        offeringResponse.setCpuNumber(offering.getCpu());
        offeringResponse.setCpuSpeed(offering.getSpeed());
        offeringResponse.setMemory(offering.getRamSize());
        offeringResponse.setCreated(offering.getCreated());
        offeringResponse.setStorageType(offering.getUseLocalStorage() ? ServiceOffering.StorageType.local.toString() : ServiceOffering.StorageType.shared.toString());
        offeringResponse.setOfferHa(offering.getOfferHA());
        offeringResponse.setLimitCpuUse(offering.getLimitCpuUse());
        offeringResponse.setTags(offering.getTags());
        if (offering.getDomainId() != null) {
            offeringResponse.setDomain(ApiDBUtils.findDomainById(offering.getDomainId()).getName());
            offeringResponse.setDomainId(offering.getDomainId());
        }
        offeringResponse.setNetworkRate(offering.getRateMbps());
        offeringResponse.setHostTag(offering.getHostTag());
        offeringResponse.setObjectName("serviceoffering");

        return offeringResponse;
    }

    @Override
    public ConfigurationResponse createConfigurationResponse(Configuration cfg) {
        ConfigurationResponse cfgResponse = new ConfigurationResponse();
        cfgResponse.setCategory(cfg.getCategory());
        cfgResponse.setDescription(cfg.getDescription());
        cfgResponse.setName(cfg.getName());
        cfgResponse.setValue(cfg.getValue());
        cfgResponse.setObjectName("configuration");

        return cfgResponse;
    }

    @Override
    public SnapshotResponse createSnapshotResponse(Snapshot snapshot) {
        SnapshotResponse snapshotResponse = new SnapshotResponse();
        snapshotResponse.setId(snapshot.getId());

        populateOwner(snapshotResponse, snapshot);

        VolumeVO volume = findVolumeById(snapshot.getVolumeId());
        String snapshotTypeStr = snapshot.getType().name();
        snapshotResponse.setSnapshotType(snapshotTypeStr);
        snapshotResponse.setVolumeId(snapshot.getVolumeId());
        if (volume != null) {
            snapshotResponse.setVolumeName(volume.getName());
            snapshotResponse.setVolumeType(volume.getVolumeType().name());
        snapshotResponse.setCreated(snapshot.getCreated());
        snapshotResponse.setName(snapshot.getName());
        snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId()));
        snapshotResponse.setState(snapshot.getStatus());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Snapshot, snapshot.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        snapshotResponse.setTags(tagResponses);
        
        snapshotResponse.setObjectName("snapshot");
        return snapshotResponse;
    }

    @Override
    public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) {
        SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse();
        policyResponse.setId(policy.getId());
        policyResponse.setVolumeId(policy.getVolumeId());
        policyResponse.setSchedule(policy.getSchedule());
        policyResponse.setIntervalType(policy.getInterval());
        policyResponse.setMaxSnaps(policy.getMaxSnaps());
        policyResponse.setTimezone(policy.getTimezone());
        policyResponse.setObjectName("snapshotpolicy");

        return policyResponse;
    }

    @Override
    public HostResponse createHostResponse(Host host) {
        return createHostResponse(host, EnumSet.of(HostDetails.all));
    }

    @Override
    public HostResponse createHostResponse(Host host, EnumSet details) {
        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.setRemoved(host.getRemoved());
        hostResponse.setCpuSpeed(host.getSpeed());
        hostResponse.setState(host.getStatus());
        hostResponse.setIpAddress(host.getPrivateIpAddress());
        hostResponse.setVersion(host.getVersion());
        hostResponse.setCreated(host.getCreated());

        if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)
                || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) {

            GuestOSCategoryVO guestOSCategory = ApiDBUtils.getHostGuestOSCategory(host.getId());
            if (guestOSCategory != null) {
                hostResponse.setOsCategoryId(guestOSCategory.getId());
                hostResponse.setOsCategoryName(guestOSCategory.getName());
            }
            hostResponse.setZoneName(ApiDBUtils.findZoneById(host.getDataCenterId()).getName());

            if (host.getPodId() != null) {
                HostPodVO pod = ApiDBUtils.findPodById(host.getPodId());
                if (pod != null) {
                    hostResponse.setPodName(pod.getName());
                }
            }

            if (host.getClusterId() != null) {
                ClusterVO cluster = ApiDBUtils.findClusterById(host.getClusterId());
                hostResponse.setClusterName(cluster.getName());
                hostResponse.setClusterType(cluster.getClusterType().toString());
            }
        }

        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        if (host.getType() == Host.Type.Routing) {
            if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) {
                // set allocated capacities
                Long mem = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_MEMORY);
                Long cpu = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_CPU);

                hostResponse.setMemoryAllocated(mem);
                hostResponse.setMemoryTotal(host.getTotalMemory());
                String hostTags = ApiDBUtils.getHostTags(host.getId());
                hostResponse.setHostTags(hostTags);
                
                String haTag = ApiDBUtils.getHaTag();
                if (haTag != null && !haTag.isEmpty() && hostTags != null && !hostTags.isEmpty()) {
                    if (haTag.equalsIgnoreCase(hostTags)) {
                        hostResponse.setHaHost(true);
                    } else {
                        hostResponse.setHaHost(false);
                    }
                } else {
                    hostResponse.setHaHost(false);
                }
                
                hostResponse.setHypervisorVersion(host.getHypervisorVersion());

                String cpuAlloc = decimalFormat.format(((float) cpu / (float) (host.getCpus() * host.getSpeed())) * 100f) + "%";
                hostResponse.setCpuAllocated(cpuAlloc);
                String cpuWithOverprovisioning = new Float(host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor()).toString();
                hostResponse.setCpuWithOverprovisioning(cpuWithOverprovisioning);
            }

            if (details.contains(HostDetails.all) || details.contains(HostDetails.stats)) {
                // set CPU/RAM/Network stats
                String cpuUsed = null;
                HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId());
                if (hostStats != null) {
                    float cpuUtil = (float) hostStats.getCpuUtilization();
                    cpuUsed = decimalFormat.format(cpuUtil) + "%";
                    hostResponse.setCpuUsed(cpuUsed);
                    hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue());
                    hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue());
                    hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue());

                }
        } else if (host.getType() == Host.Type.SecondaryStorage) {
            StorageStats secStorageStats = ApiDBUtils.getSecondaryStorageStatistics(host.getId());
            if (secStorageStats != null) {
                hostResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes());
                hostResponse.setDiskSizeAllocated(secStorageStats.getByteUsed());
            }
        }

        hostResponse.setLocalStorageActive(ApiDBUtils.isLocalStorageActiveOnHost(host));

        if (details.contains(HostDetails.all) || details.contains(HostDetails.events)) {
            Set possibleEvents = host.getStatus().getPossibleEvents();
            if ((possibleEvents != null) && !possibleEvents.isEmpty()) {
                String events = "";
                Iterator iter = possibleEvents.iterator();
                while (iter.hasNext()) {
                    com.cloud.host.Status.Event event = iter.next();
                    events += event.toString();
                    if (iter.hasNext()) {
                        events += "; ";
                    }
                }
                hostResponse.setEvents(events);
            }
        }

        hostResponse.setResourceState(host.getResourceState().toString());
        hostResponse.setObjectName("host");

        return hostResponse;
    }

    @Override
    public SwiftResponse createSwiftResponse(Swift swift) {
        SwiftResponse swiftResponse = new SwiftResponse();
        swiftResponse.setId(swift.getId());
        swiftResponse.setUrl(swift.getUrl());
        swiftResponse.setAccount(swift.getAccount());
                }
        swiftResponse.setUsername(swift.getUserName());
        swiftResponse.setObjectName("swift");
        return swiftResponse;
    }

    @Override
    public VlanIpRangeResponse createVlanIpRangeResponse(Vlan vlan) {
        Long podId = ApiDBUtils.getPodIdForVlan(vlan.getId());

        VlanIpRangeResponse vlanResponse = new VlanIpRangeResponse();
        vlanResponse.setId(vlan.getId());
        vlanResponse.setForVirtualNetwork(vlan.getVlanType().equals(VlanType.VirtualNetwork));
        vlanResponse.setVlan(vlan.getVlanTag());
        vlanResponse.setZoneId(vlan.getDataCenterId());

        if (podId != null) {
            HostPodVO pod = ApiDBUtils.findPodById(podId);
            vlanResponse.setPodId(podId);
            if (pod != null) {
                vlanResponse.setPodName(pod.getName());
            }
        }

        vlanResponse.setGateway(vlan.getVlanGateway());
        vlanResponse.setNetmask(vlan.getVlanNetmask());

        // get start ip and end ip of corresponding vlan
        String ipRange = vlan.getIpRange();
        String[] range = ipRange.split("-");
        vlanResponse.setStartIp(range[0]);
        vlanResponse.setEndIp(range[1]);

        vlanResponse.setNetworkId(vlan.getNetworkId());
        Account owner = ApiDBUtils.getVlanAccount(vlan.getId());
        if (owner != null) {
            populateAccount(vlanResponse, owner.getId());
            populateDomain(vlanResponse, owner.getDomainId());
        }

        vlanResponse.setPhysicalNetworkId(vlan.getPhysicalNetworkId());

        vlanResponse.setObjectName("vlan");
        return vlanResponse;
    }

    @Override
    public IPAddressResponse createIPAddressResponse(IpAddress ipAddr) {
        VlanVO vlan = ApiDBUtils.findVlanById(ipAddr.getVlanId());
        boolean forVirtualNetworks = vlan.getVlanType().equals(VlanType.VirtualNetwork);
        long zoneId = ipAddr.getDataCenterId();

        IPAddressResponse ipResponse = new IPAddressResponse();
        ipResponse.setId(ipAddr.getId());
        ipResponse.setIpAddress(ipAddr.getAddress().toString());
        if (ipAddr.getAllocatedTime() != null) {
            ipResponse.setAllocated(ipAddr.getAllocatedTime());
        }
        ipResponse.setZoneId(zoneId);
        ipResponse.setZoneName(ApiDBUtils.findZoneById(ipAddr.getDataCenterId()).getName());
        ipResponse.setSourceNat(ipAddr.isSourceNat());
        ipResponse.setIsSystem(ipAddr.getSystem());

        // get account information
        if (ipAddr.getAllocatedToAccountId() != null) {
            populateOwner(ipResponse, ipAddr);
        }

        ipResponse.setForVirtualNetwork(forVirtualNetworks);
        ipResponse.setStaticNat(ipAddr.isOneToOneNat());

        if (ipAddr.getAssociatedWithVmId() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(ipAddr.getAssociatedWithVmId());
            ipResponse.setVirtualMachineId(vm.getId());
            ipResponse.setVirtualMachineName(vm.getHostName());
            if (vm.getDisplayName() != null) {
                ipResponse.setVirtualMachineDisplayName(vm.getDisplayName());
            } else {
                ipResponse.setVirtualMachineDisplayName(vm.getHostName());
            }
        }

        ipResponse.setAssociatedNetworkId(ipAddr.getAssociatedWithNetworkId());
        ipResponse.setVpcId(ipAddr.getVpcId());

        // Network id the ip is associated with (if associated networkId is null, try to get this information from vlan)
        Long vlanNetworkId = ApiDBUtils.getVlanNetworkId(ipAddr.getVlanId());

        // Network id the ip belongs to
        Long networkId;
        if (vlanNetworkId != null) {
            networkId = vlanNetworkId;
        } else {

            networkId = ApiDBUtils.getPublicNetworkIdByZone(zoneId);
        }

        ipResponse.setNetworkId(networkId);
        ipResponse.setState(ipAddr.getState().toString());
        ipResponse.setPhysicalNetworkId(ipAddr.getPhysicalNetworkId());

        // show this info to admin only
        Account account = UserContext.current().getCaller();
        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            ipResponse.setVlanId(ipAddr.getVlanId());
            ipResponse.setVlanName(ApiDBUtils.findVlanById(ipAddr.getVlanId()).getVlanTag());
        }
        
        if (ipAddr.getSystem()) {
            if (ipAddr.isOneToOneNat()) {
                ipResponse.setPurpose(IpAddress.Purpose.StaticNat.toString());
            } else {
                ipResponse.setPurpose(IpAddress.Purpose.Lb.toString());
            }
        }
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PublicIpAddress, ipAddr.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        ipResponse.setTags(tagResponses);
        
        ipResponse.setObjectName("ipaddress");
        return ipResponse;
    }

    @Override
    public LoadBalancerResponse createLoadBalancerResponse(LoadBalancer loadBalancer) {
        LoadBalancerResponse lbResponse = new LoadBalancerResponse();
        lbResponse.setId(loadBalancer.getId());
        lbResponse.setName(loadBalancer.getName());
        lbResponse.setDescription(loadBalancer.getDescription());
        List cidrs = ApiDBUtils.findFirewallSourceCidrs(loadBalancer.getId());
        lbResponse.setCidrList(StringUtils.join(cidrs, ","));

        IPAddressVO publicIp = ApiDBUtils.findIpAddressById(loadBalancer.getSourceIpAddressId());
        lbResponse.setPublicIpId(publicIp.getId());
        lbResponse.setPublicIp(publicIp.getAddress().addr());
        lbResponse.setPublicPort(Integer.toString(loadBalancer.getSourcePortStart()));
        lbResponse.setPrivatePort(Integer.toString(loadBalancer.getDefaultPortStart()));
        lbResponse.setAlgorithm(loadBalancer.getAlgorithm());
        FirewallRule.State state = loadBalancer.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        lbResponse.setState(stateToSet);
        populateOwner(lbResponse, loadBalancer);
        lbResponse.setZoneId(publicIp.getDataCenterId());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, loadBalancer.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        lbResponse.setTags(tagResponses);

        lbResponse.setObjectName("loadbalancer");
        return lbResponse;
    }

    @Override
    public PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
        String[] ipRange = new String[2];
        if (pod.getDescription() != null && pod.getDescription().length() > 0) {
            ipRange = pod.getDescription().split("-");
        } else {
            ipRange[0] = pod.getDescription();
        }

        PodResponse podResponse = new PodResponse();
        podResponse.setId(pod.getId());
        podResponse.setName(pod.getName());
        podResponse.setZoneId(pod.getDataCenterId());
        podResponse.setZoneName(PodZoneConfig.getZoneName(pod.getDataCenterId()));
        podResponse.setNetmask(NetUtils.getCidrNetmask(pod.getCidrSize()));
        podResponse.setStartIp(ipRange[0]);
        podResponse.setEndIp(((ipRange.length > 1) && (ipRange[1] != null)) ? ipRange[1] : "");
        podResponse.setGateway(pod.getGateway());
        podResponse.setAllocationState(pod.getAllocationState().toString());
        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, pod.getId(), null);
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, pod.getId(), null);
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, null, pod.getId(), pod.getDataCenterId()));
            podResponse.setCapacitites(new ArrayList(capacityResponses));
        }
        podResponse.setObjectName("pod");
        return podResponse;
    }

    @Override
    public ZoneResponse createZoneResponse(DataCenter dataCenter, Boolean showCapacities) {
        volResponse.setObjectName("volume");
        Account account = UserContext.current().getCaller();
        ZoneResponse zoneResponse = new ZoneResponse();
        zoneResponse.setId(dataCenter.getId());
        zoneResponse.setName(dataCenter.getName());
        zoneResponse.setSecurityGroupsEnabled(ApiDBUtils.isSecurityGroupEnabledInZone(dataCenter.getId()));

        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());
            // FIXME zoneResponse.setVlan(dataCenter.get.getVnet());
            zoneResponse.setGuestCidrAddress(dataCenter.getGuestNetworkCidr());
        }

        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(dataCenter.getId(), null, null);
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(dataCenter.getId(), null, null);
                UserVm userVm = ApiDBUtils.findUserVmById(vm.getId());
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, null, null, dataCenter.getId()));

            zoneResponse.setCapacitites(new ArrayList(capacityResponses));
        }

        // set network domain info
        zoneResponse.setDomain(dataCenter.getDomain());

        // set domain info
        Long domainId = dataCenter.getDomainId();
        if (domainId != null) {
            Domain domain = ApiDBUtils.findDomainById(domainId);
            zoneResponse.setDomainId(domain.getId());
            zoneResponse.setDomainName(domain.getName());
        }

        zoneResponse.setType(dataCenter.getNetworkType().toString());
        zoneResponse.setAllocationState(dataCenter.getAllocationState().toString());
        zoneResponse.setZoneToken(dataCenter.getZoneToken());
        zoneResponse.setDhcpProvider(dataCenter.getDhcpProvider());
        zoneResponse.setObjectName("zone");
        return zoneResponse;
    }

    private List getStatsCapacityresponse(Long poolId, Long clusterId, Long podId, Long zoneId) {
        List capacities = new ArrayList();
        capacities.add(ApiDBUtils.getStoragePoolUsedStats(poolId, clusterId, podId, zoneId));
        if (clusterId == null && podId == null) {
            capacities.add(ApiDBUtils.getSecondaryStorageUsedStats(poolId, zoneId));
        }

        return volResponse;
        List capacityResponses = new ArrayList();
        for (CapacityVO capacity : capacities) {
            CapacityResponse capacityResponse = new CapacityResponse();
            capacityResponse.setCapacityType(capacity.getCapacityType());
            capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
            capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
            if (capacityResponse.getCapacityTotal() != 0) {
                capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
            } else {
                capacityResponse.setPercentUsed(s_percentFormat.format(0L));
            }
            capacityResponses.add(capacityResponse);
        }

        return capacityResponses;
    }

    @Override
    public VolumeResponse createVolumeResponse(Volume volume) {
        VolumeResponse volResponse = new VolumeResponse();
        volResponse.setId(volume.getId());

        if (volume.getName() != null) {
            volResponse.setName(volume.getName());
        } else {
            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 && volume.getState() != Volume.State.Destroy) {
            VMInstanceVO vm = ApiDBUtils.findVMInstanceById(instanceId);
            if (vm != null) {
                volResponse.setVirtualMachineId(vm.getId());
                volResponse.setVirtualMachineName(vm.getHostName());
                if (userVm != null) {
                    if (userVm.getDisplayName() != null) {
                        volResponse.setVirtualMachineDisplayName(userVm.getDisplayName());
                    } else {
                        volResponse.setVirtualMachineDisplayName(userVm.getHostName());
                    }
                    volResponse.setVirtualMachineState(vm.getState().toString());
                } else {
                    s_logger.error("User Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
                }
            } else {
                s_logger.error("Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
            }
        }

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

        volResponse.setCreated(volume.getCreated());
        volResponse.setState(volume.getState().toString());
        if(volume.getState() == Volume.State.UploadOp){
            com.cloud.storage.VolumeHostVO volumeHostRef = ApiDBUtils.findVolumeHostRef(volume.getId(), volume.getDataCenterId());
            volResponse.setSize(volumeHostRef.getSize());
            volResponse.setCreated(volumeHostRef.getCreated());
            Account caller = UserContext.current().getCaller();
            if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)
            volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volumeHostRef.getFormat()).toString());
            if (volumeHostRef.getDownloadState() != Status.DOWNLOADED) {
                String volumeStatus = "Processing";
                if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                    if (volumeHostRef.getDownloadPercent() == 100) {
                        volumeStatus = "Checking Volume";
                    } else {
                        volumeStatus = volumeHostRef.getDownloadPercent() + "% Uploaded";
                    }
                    volResponse.setState("Uploading");
                } else {
                    volumeStatus = volumeHostRef.getErrorString();
                    if(volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.NOT_DOWNLOADED){
                        volResponse.setState("UploadNotStarted");
                    }else {
                        volResponse.setState("UploadError");
                    }
                }
                volResponse.setStatus(volumeStatus);
            } else if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                volResponse.setStatus("Upload Complete");
                volResponse.setState("Uploaded");
            } else {
                volResponse.setStatus("Successfully Installed");
            }            
        }
        
        populateOwner(volResponse, volume);

        String storageType;
        try {
            if (volume.getPoolId() == null) {
                if (volume.getState() == Volume.State.Allocated || volume.getState() == Volume.State.UploadOp) {
                    /* set it as shared, so the UI can attach it to VM */
                    storageType = "shared";
                } else {
                    storageType = "unknown";
                }
            } else {
                storageType = ApiDBUtils.volumeIsOnSharedStorage(volume.getId()) ? ServiceOffering.StorageType.shared.toString() : ServiceOffering.StorageType.local.toString();
            }
        } catch (InvalidParameterValueException e) {
            s_logger.error(e.getMessage(), e);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Volume " + volume.getName() + " does not have a valid ID");
        }

        volResponse.setStorageType(storageType);
        if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
            volResponse.setServiceOfferingId(volume.getDiskOfferingId());
        } else {
            volResponse.setDiskOfferingId(volume.getDiskOfferingId());
        }

        DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
        if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
            volResponse.setServiceOfferingName(diskOffering.getName());
            volResponse.setServiceOfferingDisplayText(diskOffering.getDisplayText());
        } else {
            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.setSourceId(volume.getSourceId());
        // if (volume.getSourceType() != null) {
        // volResponse.setSourceType(volume.getSourceType().toString());
        // }

        // return hypervisor for ROOT and Resource domain only
        Account caller = UserContext.current().getCaller();
        if ((caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) && volume.getState() != Volume.State.UploadOp) {            
            volResponse.setHypervisor(ApiDBUtils.getVolumeHyperType(volume.getId()).toString());            
        }

        volResponse.setAttached(volume.getAttached());
        volResponse.setDestroyed(volume.getState() == Volume.State.Destroy);        
        boolean isExtractable = true;
        if (volume.getVolumeType() != Volume.Type.DATADISK) { // Datadisk dont have any template dependence.
            VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
            if (template != null) { // For ISO based volumes template = null and we allow extraction of all ISO based volumes
                isExtractable = template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;                
            }
        }
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Volume, volume.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        volResponse.setTags(tagResponses);
        
        volResponse.setExtractable(isExtractable);
    }

    @Override
    public InstanceGroupResponse createInstanceGroupResponse(InstanceGroup group) {
        InstanceGroupResponse groupResponse = new InstanceGroupResponse();
        groupResponse.setId(group.getId());
        groupResponse.setName(group.getName());
        groupResponse.setCreated(group.getCreated());

        populateOwner(groupResponse, group);

        groupResponse.setObjectName("instancegroup");
        return groupResponse;
    }

    @Override
    public StoragePoolResponse createStoragePoolResponse(StoragePool pool) {
        StoragePoolResponse poolResponse = new StoragePoolResponse();
        poolResponse.setId(pool.getId());
        poolResponse.setName(pool.getName());
        poolResponse.setState(pool.getStatus());
        poolResponse.setPath(pool.getPath());
        poolResponse.setIpAddress(pool.getHostAddress());
        poolResponse.setZoneId(pool.getDataCenterId());
        poolResponse.setZoneName(ApiDBUtils.findZoneById(pool.getDataCenterId()).getName());
        if (pool.getPoolType() != null) {
            poolResponse.setType(pool.getPoolType().toString());
        }
        if (pool.getPodId() != null) {
            poolResponse.setPodId(pool.getPodId());
            HostPodVO pod = ApiDBUtils.findPodById(pool.getPodId());
            if (pod != null) {
                poolResponse.setPodName(pod.getName());
            }
        }
        if (pool.getCreated() != null) {
            poolResponse.setCreated(pool.getCreated());
        }

        StorageStats stats = ApiDBUtils.getStoragePoolStatistics(pool.getId());
        long allocatedSize = ApiDBUtils.getStorageCapacitybyPool(pool.getId(), Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED);
        poolResponse.setDiskSizeTotal(pool.getCapacityBytes());
        poolResponse.setDiskSizeAllocated(allocatedSize);

        if (stats != null) {
            Long used = stats.getByteUsed();
            poolResponse.setDiskSizeUsed(used);
        }

        if (pool.getClusterId() != null) {
            ClusterVO cluster = ApiDBUtils.findClusterById(pool.getClusterId());
            poolResponse.setClusterId(cluster.getId());
            poolResponse.setClusterName(cluster.getName());
        }
        poolResponse.setTags(ApiDBUtils.getStoragePoolTags(pool.getId()));
        poolResponse.setObjectName("storagepool");
        return poolResponse;
    }

    @Override
    public ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities) {
        ClusterResponse clusterResponse = new ClusterResponse();
        clusterResponse.setId(cluster.getId());
        clusterResponse.setName(cluster.getName());
        clusterResponse.setPodId(cluster.getPodId());
        clusterResponse.setZoneId(cluster.getDataCenterId());
        clusterResponse.setHypervisorType(cluster.getHypervisorType().toString());
        clusterResponse.setClusterType(cluster.getClusterType().toString());
        clusterResponse.setAllocationState(cluster.getAllocationState().toString());
        clusterResponse.setManagedState(cluster.getManagedState().toString());
        HostPodVO pod = ApiDBUtils.findPodById(cluster.getPodId());
        if (pod != null) {
            clusterResponse.setPodName(pod.getName());
        }
        DataCenterVO zone = ApiDBUtils.findZoneById(cluster.getDataCenterId());
        clusterResponse.setZoneName(zone.getName());
        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, null, cluster.getId());
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());

                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, null, cluster.getId());
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, cluster.getId(), pod.getId(), pod.getDataCenterId()));
            clusterResponse.setCapacitites(new ArrayList(capacityResponses));
        }
        clusterResponse.setObjectName("cluster");
        return clusterResponse;
    }

    @Override
    public FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRule fwRule) {
        FirewallRuleResponse response = new FirewallRuleResponse();
        response.setId(fwRule.getId());
        response.setPrivateStartPort(Integer.toString(fwRule.getDestinationPortStart()));
        response.setPrivateEndPort(Integer.toString(fwRule.getDestinationPortEnd()));
        response.setProtocol(fwRule.getProtocol());
        response.setPublicStartPort(Integer.toString(fwRule.getSourcePortStart()));
        response.setPublicEndPort(Integer.toString(fwRule.getSourcePortEnd()));
        List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        if (ip != null && fwRule.getDestinationIpAddress() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(fwRule.getVirtualMachineId());
            if (vm != null) {
                response.setVirtualMachineId(vm.getId());
                response.setVirtualMachineName(vm.getHostName());
                
                if (vm.getDisplayName() != null) {
                    response.setVirtualMachineDisplayName(vm.getDisplayName());
                } else {
                    response.setVirtualMachineDisplayName(vm.getHostName());
                }
            }
        }
        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PortForwardingRule, fwRule.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        
        response.setState(stateToSet);
        response.setObjectName("portforwardingrule");
        return response;
    }

    @Override
    public IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule) {
        IpForwardingRuleResponse response = new IpForwardingRuleResponse();
        response.setId(fwRule.getId());
        response.setProtocol(fwRule.getProtocol());

    @Override
        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        if (ip != null && fwRule.getDestIpAddress() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(ip.getAssociatedWithVmId());
            if (vm != null) {// vm might be destroyed
                response.setVirtualMachineId(vm.getId());
                response.setVirtualMachineName(vm.getHostName());
                if (vm.getDisplayName() != null) {
                    response.setVirtualMachineDisplayName(vm.getDisplayName());
                } else {
                    response.setVirtualMachineDisplayName(vm.getHostName());
                }
            }
        }
        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setStartPort(fwRule.getSourcePortStart());
        response.setEndPort(fwRule.getSourcePortEnd());
        response.setProtocol(fwRule.getProtocol());
        response.setState(stateToSet);
        response.setObjectName("ipforwardingrule");
        return response;
    }

    @Override
    public List createUserVmResponse(String objectName, EnumSet details, UserVm... userVms) {
        Account caller = UserContext.current().getCaller();
        Map dataCenters = new HashMap();
        Map hosts = new HashMap();
        Map templates = new HashMap();
        Map serviceOfferings = new HashMap();
        Map networks = new HashMap();

        List vmResponses = new ArrayList();

        for (UserVm userVm : userVms) {
            UserVmResponse userVmResponse = new UserVmResponse();
            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.setId(userVm.getId());
            userVmResponse.setName(userVm.getHostName());
            userVmResponse.setCreated(userVm.getCreated());

            userVmResponse.setHaEnable(userVm.isHaEnabled());

            if (userVm.getDisplayName() != null) {
                userVmResponse.setDisplayName(userVm.getDisplayName());
            } else {
                userVmResponse.setDisplayName(userVm.getHostName());
            }
            
            if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {
                userVmResponse.setInstanceName(userVm.getInstanceName());
            }
            
 
            if (userVm.getPassword() != null) {
                userVmResponse.setPassword(userVm.getPassword());
            }

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

            }

            // Data Center Info
            DataCenter zone = dataCenters.get(userVm.getDataCenterIdToDeployIn());
            if (zone == null) {
                zone = ApiDBUtils.findZoneById(userVm.getDataCenterIdToDeployIn());
                dataCenters.put(zone.getId(), zone);
            }

        }
            userVmResponse.setZoneId(zone.getId());
            userVmResponse.setZoneName(zone.getName());

            // if user is an admin, display host id
            if (((caller == null) || (caller.getType() == Account.ACCOUNT_TYPE_ADMIN)) && (userVm.getHostId() != null)) {
                Host host = hosts.get(userVm.getHostId());

                if (host == null) {
                    host = ApiDBUtils.findHostById(userVm.getHostId());
                    hosts.put(host.getId(), host);
                }

                userVmResponse.setHostId(host.getId());
                userVmResponse.setHostName(host.getName());
            }

            if (userVm.getState() != null) {
                if (userVm.getHostId() != null) {
                    Host host = hosts.get(userVm.getHostId());

                    if (host == null) {
                        host = ApiDBUtils.findHostById(userVm.getHostId());
                        hosts.put(host.getId(), host);
                    }
                    if (host.getStatus() != com.cloud.host.Status.Up) {
                        userVmResponse.setState(VirtualMachine.State.Unknown.toString());
                    } else {
                        userVmResponse.setState(userVm.getState().toString());
                    }
                } else {
                    userVmResponse.setState(userVm.getState().toString());
                }
            }

            if (userVm.getHypervisorType() != null) {
                userVmResponse.setHypervisor(userVm.getHypervisorType().toString());
            }
            
            if (details.contains(VMDetails.all) || details.contains(VMDetails.tmpl)) {
                // Template Info
                VMTemplateVO template = templates.get(userVm.getTemplateId());
                if (template == null) {
                    template = ApiDBUtils.findTemplateById(userVm.getTemplateId());
                    if (template != null) {
                        templates.put(template.getId(), template);
                    }
                }

                if (template != null) {
                    userVmResponse.setTemplateId(userVm.getTemplateId());
                    userVmResponse.setTemplateName(template.getName());
                    userVmResponse.setTemplateDisplayText(template.getDisplayText());
                    userVmResponse.setPasswordEnabled(template.getEnablePassword());
                } else {
                    userVmResponse.setTemplateId(-1L);
                    userVmResponse.setTemplateName("ISO Boot");
                    userVmResponse.setTemplateDisplayText("ISO Boot");
                    userVmResponse.setPasswordEnabled(false);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.iso)) {
                // ISO Info
                VMTemplateVO iso = templates.get(userVm.getIsoId());
                if (iso == null) {
                    iso = ApiDBUtils.findTemplateById(userVm.getIsoId());
                    if (iso != null) {
                        templates.put(iso.getId(), iso);
                    }
                }

                if (iso != null) {
                    userVmResponse.setIsoId(iso.getId());
                    userVmResponse.setIsoName(iso.getName());
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.servoff)) {
                // Service Offering Info
                ServiceOffering offering = serviceOfferings.get(userVm.getServiceOfferingId());

                if (offering == null) {
                    offering = ApiDBUtils.findServiceOfferingById(userVm.getServiceOfferingId());
                    serviceOfferings.put(offering.getId(), offering);
                }

                userVmResponse.setServiceOfferingId(offering.getId());
                userVmResponse.setServiceOfferingName(offering.getName());
                userVmResponse.setCpuNumber(offering.getCpu());
                userVmResponse.setCpuSpeed(offering.getSpeed());
                userVmResponse.setMemory(offering.getRamSize());
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.volume)) {
                VolumeVO rootVolume = ApiDBUtils.findRootVolume(userVm.getId());
                if (rootVolume != null) {
                    userVmResponse.setRootDeviceId(rootVolume.getDeviceId());
                    String rootDeviceType = "Not created";
                    if (rootVolume.getPoolId() != null) {
                        StoragePoolVO storagePool = ApiDBUtils.findStoragePoolById(rootVolume.getPoolId());
                        rootDeviceType = storagePool.getPoolType().toString();
                    }
                    userVmResponse.setRootDeviceType(rootDeviceType);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.stats)) {
                // stats calculation
                DecimalFormat decimalFormat = new DecimalFormat("#.##");
                String cpuUsed = null;
                VmStats vmStats = ApiDBUtils.getVmStatistics(userVm.getId());
                if (vmStats != null) {
                    float cpuUtil = (float) vmStats.getCPUUtilization();
                    cpuUsed = decimalFormat.format(cpuUtil) + "%";
                    userVmResponse.setCpuUsed(cpuUsed);

                    Double networkKbRead = Double.valueOf(vmStats.getNetworkReadKBs());
                    userVmResponse.setNetworkKbsRead(networkKbRead.longValue());

                    Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
                    userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
                }
            }

            userVmResponse.setGuestOsId(userVm.getGuestOSId());

            if (details.contains(VMDetails.all) || details.contains(VMDetails.secgrp)) {
                // security groups - list only when zone is security group enabled
                if (zone.isSecurityGroupEnabled()) {
                    List securityGroups = ApiDBUtils.getSecurityGroupsForVm(userVm.getId());
                    List securityGroupResponse = new ArrayList();
                    for (SecurityGroupVO grp : securityGroups) {
                        SecurityGroupResponse resp = new SecurityGroupResponse();
                        resp.setId(grp.getId());
                        resp.setName(grp.getName());
                        resp.setDescription(grp.getDescription());
                        resp.setObjectName("securitygroup");
                        securityGroupResponse.add(resp);
                    }
                    userVmResponse.setSecurityGroupList(securityGroupResponse);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.nics)) {
                List nicProfiles = ApiDBUtils.getNics(userVm);
                List nicResponses = new ArrayList();
                for (NicProfile singleNicProfile : nicProfiles) {
                    NicResponse nicResponse = new NicResponse();
                    nicResponse.setId(singleNicProfile.getId());
                    nicResponse.setIpaddress(singleNicProfile.getIp4Address());
                    nicResponse.setGateway(singleNicProfile.getGateway());
                    nicResponse.setNetmask(singleNicProfile.getNetmask());
                    nicResponse.setNetworkid(singleNicProfile.getNetworkId());
                    if (acct.getType() == Account.ACCOUNT_TYPE_ADMIN) {
                        if (singleNicProfile.getBroadCastUri() != null) {
                            nicResponse.setBroadcastUri(singleNicProfile.getBroadCastUri().toString());
                        }
                        if (singleNicProfile.getIsolationUri() != null) {
                            nicResponse.setIsolationUri(singleNicProfile.getIsolationUri().toString());
                        }
                    }

                    // Long networkId = singleNicProfile.getNetworkId();
                    Network network = networks.get(singleNicProfile.getNetworkId());
                    if (network == null) {
                        network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                        networks.put(singleNicProfile.getNetworkId(), network);
                    }

                    nicResponse.setTrafficType(network.getTrafficType().toString());
                    nicResponse.setType(network.getGuestType().toString());
                    nicResponse.setIsDefault(singleNicProfile.isDefaultNic());
                    nicResponse.setObjectName("nic");
                    nicResponses.add(nicResponse);
                }
                userVmResponse.setNics(nicResponses);
            }
            
            //set tag information
            List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, userVm.getId());
            List tagResponses = new ArrayList();
            for (ResourceTag tag : tags) {
                ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                tagResponses.add(tagResponse);
            }
            userVmResponse.setTags(tagResponses);
            
            IpAddress ip = ApiDBUtils.findIpByAssociatedVmId(userVm.getId());
            if (ip != null) {
                userVmResponse.setPublicIpId(ip.getId());
                userVmResponse.setPublicIp(ip.getAddress().addr());
            }

            userVmResponse.setObjectName(objectName);
            vmResponses.add(userVmResponse);
        }

        return vmResponses;
    }

    @Override
    public List createUserVmResponse(String objectName, UserVm... userVms) {
        Account caller = UserContext.current().getCaller();
        boolean caller_is_admin = ((caller == null) || (caller.getType() == Account.ACCOUNT_TYPE_ADMIN));

        populateDomain(response, owner.getDomainId());
        Hashtable vmDataList = new Hashtable();
        // Initialise the vmdatalist with the input data
        for (UserVm userVm : userVms) {
            UserVmData userVmData = newUserVmData(userVm);
            vmDataList.put(userVm.getId(), userVmData);
        }

        vmDataList = ApiDBUtils.listVmDetails(vmDataList);

        // initialize vmresponse from vmdatalist
        List vmResponses = new ArrayList();
        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        for (UserVmData uvd : vmDataList.values()) {
            UserVmResponse userVmResponse = newUserVmResponse(uvd, caller_is_admin);

            // stats calculation
            String cpuUsed = null;
            // VmStats vmStats = ApiDBUtils.getVmStatistics(userVmResponse.getId());
            VmStats vmStats = ApiDBUtils.getVmStatistics(uvd.getId());
            if (vmStats != null) {
                float cpuUtil = (float) vmStats.getCPUUtilization();
                cpuUsed = decimalFormat.format(cpuUtil) + "%";
                userVmResponse.setCpuUsed(cpuUsed);

                Double networkKbRead = Double.valueOf(vmStats.getNetworkReadKBs());
                userVmResponse.setNetworkKbsRead(networkKbRead.longValue());

                Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
                userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
            }
            userVmResponse.setObjectName(objectName);

            vmResponses.add(userVmResponse);
        }
        return vmResponses;
    }

    @Override
    public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) {
        Account caller = UserContext.current().getCaller();
        Map serviceOfferings = new HashMap();

        DomainRouterResponse routerResponse = new DomainRouterResponse();
        routerResponse.setId(router.getId());
        routerResponse.setZoneId(router.getDataCenterIdToDeployIn());
        routerResponse.setName(router.getHostName());
        routerResponse.setTemplateId(router.getTemplateId());
        routerResponse.setCreated(router.getCreated());
        routerResponse.setState(router.getState());
        routerResponse.setIsRedundantRouter(router.getIsRedundantRouter());
        routerResponse.setRedundantState(router.getRedundantState().toString());

        if (caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            if (router.getHostId() != null) {
                routerResponse.setHostId(router.getHostId());
                routerResponse.setHostName(ApiDBUtils.findHostById(router.getHostId()).getName());
            }
            routerResponse.setPodId(router.getPodIdToDeployIn());
            List nicProfiles = ApiDBUtils.getNics(router);
            for (NicProfile singleNicProfile : nicProfiles) {
                Network network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                if (network != null) {
                    if (network.getTrafficType() == TrafficType.Public) {
                        routerResponse.setPublicIp(singleNicProfile.getIp4Address());
                        routerResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setPublicNetmask(singleNicProfile.getNetmask());
                        routerResponse.setGateway(singleNicProfile.getGateway());
                        routerResponse.setPublicNetworkId(singleNicProfile.getNetworkId());
                    } else if (network.getTrafficType() == TrafficType.Control) {
                        routerResponse.setLinkLocalIp(singleNicProfile.getIp4Address());
                        routerResponse.setLinkLocalMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setLinkLocalNetmask(singleNicProfile.getNetmask());
                        routerResponse.setLinkLocalNetworkId(singleNicProfile.getNetworkId());
                    } else if (network.getTrafficType() == TrafficType.Guest) {
                        routerResponse.setGuestIpAddress(singleNicProfile.getIp4Address());
                        routerResponse.setGuestMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setGuestNetmask(singleNicProfile.getNetmask());
                        routerResponse.setGuestNetworkId(singleNicProfile.getNetworkId());
                        routerResponse.setNetworkDomain(network.getNetworkDomain());
                    }
                }
            }
        }

        // Service Offering Info
        ServiceOffering offering = serviceOfferings.get(router.getServiceOfferingId());

        if (offering == null) {
            offering = ApiDBUtils.findServiceOfferingById(router.getServiceOfferingId());
            serviceOfferings.put(offering.getId(), offering);
        }
        routerResponse.setServiceOfferingId(offering.getId());
        routerResponse.setServiceOfferingName(offering.getName());

        populateOwner(routerResponse, router);

        DataCenter zone = ApiDBUtils.findZoneById(router.getDataCenterIdToDeployIn());
        if (zone != null) {
            routerResponse.setZoneName(zone.getName());
            routerResponse.setDns1(zone.getDns1());
            routerResponse.setDns2(zone.getDns2());
        }

        routerResponse.setVpcId(router.getVpcId());

        routerResponse.setObjectName("domainrouter");
        return routerResponse;
    }

    @Override
    public SystemVmResponse createSystemVmResponse(VirtualMachine vm) {
        SystemVmResponse vmResponse = new SystemVmResponse();
        if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy) {
            // SystemVm vm = (SystemVm) systemVM;
            vmResponse.setId(vm.getId());
            vmResponse.setObjectId(vm.getId());
            vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
            vmResponse.setZoneId(vm.getDataCenterIdToDeployIn());

            vmResponse.setName(vm.getHostName());
            vmResponse.setPodId(vm.getPodIdToDeployIn());
            vmResponse.setTemplateId(vm.getTemplateId());
            vmResponse.setCreated(vm.getCreated());

            if (vm.getHostId() != null) {
                vmResponse.setHostId(vm.getHostId());
                vmResponse.setHostName(ApiDBUtils.findHostById(vm.getHostId()).getName());
            }

            if (vm.getState() != null) {
                vmResponse.setState(vm.getState().toString());
            }

            // for console proxies, add the active sessions
            if (vm.getType() == Type.ConsoleProxy) {
                ConsoleProxyVO proxy = ApiDBUtils.findConsoleProxy(vm.getId());
                // proxy can be already destroyed
                if (proxy != null) {
                    vmResponse.setActiveViewerSessions(proxy.getActiveSession());
                }
            }

            DataCenter zone = ApiDBUtils.findZoneById(vm.getDataCenterIdToDeployIn());
            if (zone != null) {
                vmResponse.setZoneName(zone.getName());
                vmResponse.setDns1(zone.getDns1());
                vmResponse.setDns2(zone.getDns2());
            }

            List nicProfiles = ApiDBUtils.getNics(vm);
            for (NicProfile singleNicProfile : nicProfiles) {
                Network network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                if (network != null) {
                    if (network.getTrafficType() == TrafficType.Management) {
                        vmResponse.setPrivateIp(singleNicProfile.getIp4Address());
                        vmResponse.setPrivateMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setPrivateNetmask(singleNicProfile.getNetmask());
                    } else if (network.getTrafficType() == TrafficType.Control) {
                        vmResponse.setLinkLocalIp(singleNicProfile.getIp4Address());
                        vmResponse.setLinkLocalMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setLinkLocalNetmask(singleNicProfile.getNetmask());
                    } else if (network.getTrafficType() == TrafficType.Public || network.getTrafficType() == TrafficType.Guest) {
        
                        /*In basic zone, public ip has TrafficType.Guest*/
                        vmResponse.setPublicIp(singleNicProfile.getIp4Address());
                        vmResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setPublicNetmask(singleNicProfile.getNetmask());
                        vmResponse.setGateway(singleNicProfile.getGateway());
                    }
                }
            }
        }
        vmResponse.setObjectName("systemvm");
        return vmResponse;
    }

    @Override
    public Host findHostById(Long hostId) {
        return ApiDBUtils.findHostById(hostId);
    }

    @Override
    public User findUserById(Long userId) {
        return ApiDBUtils.findUserById(userId);
    }

    @Override
    public UserVm findUserVmById(Long vmId) {
        return ApiDBUtils.findUserVmById(vmId);

    }

    @Override
    public VolumeVO findVolumeById(Long volumeId) {
        return ApiDBUtils.findVolumeById(volumeId);
    }

    @Override
    public Account findAccountByNameDomain(String accountName, Long domainId) {
        return ApiDBUtils.findAccountByNameDomain(accountName, domainId);
    }

    @Override
    public VirtualMachineTemplate findTemplateById(Long templateId) {
        return ApiDBUtils.findTemplateById(templateId);
    }

    @Override
    public VpnUsersResponse createVpnUserResponse(VpnUser vpnUser) {
        VpnUsersResponse vpnResponse = new VpnUsersResponse();
        vpnResponse.setId(vpnUser.getId());
        vpnResponse.setUserName(vpnUser.getUsername());

        populateOwner(vpnResponse, vpnUser);

        vpnResponse.setObjectName("vpnuser");
        return vpnResponse;
    }

    public RemoteAccessVpnResponse createRemoteAccessVpnResponse(RemoteAccessVpn vpn) {
        RemoteAccessVpnResponse vpnResponse = new RemoteAccessVpnResponse();
        vpnResponse.setPublicIpId(vpn.getServerAddressId());
        vpnResponse.setPublicIp(ApiDBUtils.findIpAddressById(vpn.getServerAddressId()).getAddress().addr());
        vpnResponse.setIpRange(vpn.getIpRange());
        vpnResponse.setPresharedKey(vpn.getIpsecPresharedKey());
        vpnResponse.setDomainId(vpn.getDomainId());

        populateOwner(vpnResponse, vpn);

        vpnResponse.setState(vpn.getState().toString());
        vpnResponse.setObjectName("remoteaccessvpn");

        return vpnResponse;
    }

    @Override
    public TemplateResponse createIsoResponse(VirtualMachineTemplate result) {
        TemplateResponse response = new TemplateResponse();
        response.setId(result.getId());
        response.setName(result.getName());
        response.setDisplayText(result.getDisplayText());
        response.setPublic(result.isPublicTemplate());
        response.setCreated(result.getCreated());
        response.setFormat(result.getFormat());
        response.setOsTypeId(result.getGuestOSId());
        response.setOsTypeName(ApiDBUtils.findGuestOSById(result.getGuestOSId()).getDisplayName());
        response.setDetails(result.getDetails());
        Account caller = UserContext.current().getCaller();

        if (result.getFormat() == ImageFormat.ISO) { // Templates are always bootable
            response.setBootable(result.isBootable());
        } else {
            response.setHypervisor(result.getHypervisorType().toString());// hypervisors are associated with templates
        }

        // add account ID and name
        Account owner = ApiDBUtils.findAccountById(result.getAccountId());
        populateAccount(response, owner.getId());
        //set tag information
        List tags = null;
        if (result.getFormat() == ImageFormat.ISO) {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, result.getId());
        } else {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, result.getId());
        }
        
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("iso");
        return response;
    }

    @Override
    public List createTemplateResponses(long templateId, Long zoneId, boolean readyOnly) {
        if (zoneId == null || zoneId == -1) {
            List responses = new ArrayList();
            List dcs = new ArrayList();
            responses = createSwiftTemplateResponses(templateId);
            if (!responses.isEmpty()) {
                return responses;
            }
            dcs.addAll(ApiDBUtils.listZones());
            for (DataCenterVO dc : dcs) {
                responses.addAll(createTemplateResponses(templateId, dc.getId(), readyOnly));
            }
            return responses;
        } else {
            return createTemplateResponses(templateId, zoneId.longValue(), readyOnly);
        }
    }

    private List createSwiftTemplateResponses(long templateId) {
        VirtualMachineTemplate template = findTemplateById(templateId);
        List responses = new ArrayList();
        VMTemplateSwiftVO templateSwiftRef = ApiDBUtils.findTemplateSwiftRef(templateId);
        if (templateSwiftRef == null) {
            return responses;
        }

        TemplateResponse templateResponse = new TemplateResponse();
        templateResponse.setId(template.getId());
        templateResponse.setName(template.getName());
        templateResponse.setDisplayText(template.getDisplayText());
        templateResponse.setPublic(template.isPublicTemplate());
        templateResponse.setCreated(templateSwiftRef.getCreated());

        templateResponse.setReady(true);
        templateResponse.setFeatured(template.isFeatured());
        templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM));
        templateResponse.setPasswordEnabled(template.getEnablePassword());
        templateResponse.setCrossZones(template.isCrossZones());
        templateResponse.setFormat(template.getFormat());
        templateResponse.setDetails(template.getDetails());
        if (template.getTemplateType() != null) {
            templateResponse.setTemplateType(template.getTemplateType().toString());
        }

        templateResponse.setHypervisor(template.getHypervisorType().toString());

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

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId());
        populateAccount(templateResponse, account.getId());
        populateDomain(templateResponse, account.getDomainId());

        Account caller = UserContext.current().getCaller();
        boolean isAdmin = false;
        if (BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }

        // If the user is an Admin, add the template download status
        if (isAdmin || caller.getId() == template.getAccountId()) {
        templateResponse.setPasswordEnabled(template.getEnablePassword());
        response.setUploadId(uploadId);
            // add download status
            templateResponse.setStatus("Successfully Installed");
        }

        Long templateSize = templateSwiftRef.getSize();
        if (templateSize > 0) {
            templateResponse.setSize(templateSize);
        }

        templateResponse.setChecksum(template.getChecksum());
        templateResponse.setSourceTemplateId(template.getSourceTemplateId());

        templateResponse.setChecksum(template.getChecksum());

        templateResponse.setTemplateTag(template.getTemplateTag());

        templateResponse.setObjectName("template");
        responses.add(templateResponse);
        return responses;
    }

    @Override
    public List createTemplateResponses(long templateId, long zoneId, boolean readyOnly) {
        VirtualMachineTemplate template = findTemplateById(templateId);
        List responses = new ArrayList();
        VMTemplateHostVO templateHostRef = ApiDBUtils.findTemplateHostRef(templateId, zoneId, readyOnly);
        if (templateHostRef == null) {
            return responses;
        }

        HostVO host = ApiDBUtils.findHostById(templateHostRef.getHostId());
        if (host.getType() == Host.Type.LocalSecondaryStorage && host.getStatus() != com.cloud.host.Status.Up) {
            return responses;
        }

        TemplateResponse templateResponse = new TemplateResponse();
        templateResponse.setId(template.getId());
        templateResponse.setName(template.getName());
        templateResponse.setDisplayText(template.getDisplayText());
        templateResponse.setPublic(template.isPublicTemplate());
        templateResponse.setCreated(templateHostRef.getCreated());

        templateResponse.setReady(templateHostRef.getDownloadState() == Status.DOWNLOADED);
        templateResponse.setFeatured(template.isFeatured());
        templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM));
            isoResponse.setOsTypeId(-1L);
        templateResponse.setCrossZones(template.isCrossZones());
        templateResponse.setFormat(template.getFormat());
        if (template.getTemplateType() != null) {
            templateResponse.setTemplateType(template.getTemplateType().toString());
        }

        templateResponse.setHypervisor(template.getHypervisorType().toString());
        templateResponse.setDetails(template.getDetails());

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

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId());
        populateAccount(templateResponse, account.getId());
        populateDomain(templateResponse, account.getDomainId());

        DataCenterVO datacenter = ApiDBUtils.findZoneById(zoneId);

        // Add the zone ID
        templateResponse.setZoneId(zoneId);
        templateResponse.setZoneName(datacenter.getName());

        boolean isAdmin = false;
        Account caller = UserContext.current().getCaller();
        if ((caller == null) || BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }

        // If the user is an Admin, add the template download status
        if (isAdmin || caller.getId() == template.getAccountId()) {
            // add download status
            if (templateHostRef.getDownloadState() != Status.DOWNLOADED) {
                String templateStatus = "Processing";
                if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                    if (templateHostRef.getDownloadPercent() == 100) {
                        templateStatus = "Installing Template";
                    } else {
                        templateStatus = templateHostRef.getDownloadPercent() + "% Downloaded";
                    }
                } else {
                    templateStatus = templateHostRef.getErrorString();
                }
                templateResponse.setStatus(templateStatus);
            } else if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                templateResponse.setStatus("Download Complete");
            } else {
                templateResponse.setStatus("Successfully Installed");
            }
        }

        Long templateSize = templateHostRef.getSize();
        if (templateSize > 0) {
            templateResponse.setSize(templateSize);
        }

        templateResponse.setChecksum(template.getChecksum());
        templateResponse.setSourceTemplateId(template.getSourceTemplateId());

        templateResponse.setChecksum(template.getChecksum());

        templateResponse.setTemplateTag(template.getTemplateTag());
        
        //set tag information
        List tags = null;
        if (template.getFormat() == ImageFormat.ISO) {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, template.getId());
        } else {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, template.getId());
        }
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        templateResponse.setTags(tagResponses);

        templateResponse.setObjectName("template");
        responses.add(templateResponse);
        return responses;
    }

    @Override
            isoResponse.setOsTypeName("");
    public List createIsoResponses(long isoId, Long zoneId, boolean readyOnly) {

        List isoResponses = new ArrayList();
        VirtualMachineTemplate iso = findTemplateById(isoId);
        if (iso.getTemplateType() == TemplateType.PERHOST) {
            TemplateResponse isoResponse = new TemplateResponse();
            isoResponse.setId(iso.getId());
            isoResponse.setName(iso.getName());
            isoResponse.setDisplayText(iso.getDisplayText());
            isoResponse.setPublic(iso.isPublicTemplate());
            isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
            isoResponse.setReady(true);
            isoResponse.setBootable(iso.isBootable());
            isoResponse.setFeatured(iso.isFeatured());
            isoResponse.setCrossZones(iso.isCrossZones());
            isoResponse.setPublic(iso.isPublicTemplate());
            isoResponse.setCreated(iso.getCreated());
            isoResponse.setChecksum(iso.getChecksum());
            isoResponse.setPasswordEnabled(false);
            isoResponse.setDetails(iso.getDetails());

            // add account ID and name
            Account owner = ApiDBUtils.findAccountById(iso.getAccountId());
            populateAccount(isoResponse, owner.getId());
            populateDomain(isoResponse, owner.getDomainId());
            
            //set tag information
            List tags =  ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId());
            List tagResponses = new ArrayList();
            for (ResourceTag tag : tags) {
                ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                tagResponses.add(tagResponse);
            }
            isoResponse.setTags(tagResponses);

            isoResponse.setObjectName("iso");
            isoResponses.add(isoResponse);
            return isoResponses;
        } else {
            if (zoneId == null || zoneId == -1) {
                isoResponses = createSwiftIsoResponses(iso);
                if (!isoResponses.isEmpty()) {
                    return isoResponses;
                }
                List dcs = new ArrayList();
                dcs.addAll(ApiDBUtils.listZones());
                for (DataCenterVO dc : dcs) {
                    isoResponses.addAll(createIsoResponses(iso, dc.getId(), readyOnly));
                }
                return isoResponses;
            } else {
                return createIsoResponses(iso, zoneId, readyOnly);
            }
        }
    }

    private List createSwiftIsoResponses(VirtualMachineTemplate iso) {
        long isoId = iso.getId();
        List isoResponses = new ArrayList();
        VMTemplateSwiftVO isoSwift = ApiDBUtils.findTemplateSwiftRef(isoId);
        if (isoSwift == null) {
            return isoResponses;
        }
        TemplateResponse isoResponse = new TemplateResponse();
        isoResponse.setId(iso.getId());
        isoResponse.setName(iso.getName());
        isoResponse.setDisplayText(iso.getDisplayText());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
        isoResponse.setCreated(isoSwift.getCreated());
        isoResponse.setReady(true);
        isoResponse.setBootable(iso.isBootable());
        isoResponse.setFeatured(iso.isFeatured());
        isoResponse.setCrossZones(iso.isCrossZones());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setChecksum(iso.getChecksum());
        isoResponse.setDetails(iso.getDetails());

        // TODO: implement
        GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId());
        if (os != null) {
            isoResponse.setOsTypeId(os.getId());
            isoResponse.setOsTypeName(os.getDisplayName());
        } else {
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(iso.getAccountId());
        populateAccount(isoResponse, account.getId());
        populateDomain(isoResponse, account.getDomainId());
        boolean isAdmin = false;
        if ((account == null) || BaseCmd.isAdmin(account.getType())) {
            isAdmin = true;
        }

        // If the user is an admin, add the template download status
        if (isAdmin || account.getId() == iso.getAccountId()) {
            // add download status
            isoResponse.setStatus("Successfully Installed");
        }
        Long isoSize = isoSwift.getSize();
        if (isoSize > 0) {
            isoResponse.setSize(isoSize);
        }
        isoResponse.setObjectName("iso");
        isoResponses.add(isoResponse);
        return isoResponses;
    }

    @Override
    public List createIsoResponses(VirtualMachineTemplate iso, long zoneId, boolean readyOnly) {
        long isoId = iso.getId();
        List isoResponses = new ArrayList();
        VMTemplateHostVO isoHost = ApiDBUtils.findTemplateHostRef(isoId, zoneId, readyOnly);
        if (isoHost == null) {
            return isoResponses;
        }
        TemplateResponse isoResponse = new TemplateResponse();
        isoResponse.setId(iso.getId());
        isoResponse.setName(iso.getName());
        isoResponse.setDisplayText(iso.getDisplayText());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
        isoResponse.setCreated(isoHost.getCreated());
        isoResponse.setReady(isoHost.getDownloadState() == Status.DOWNLOADED);
        isoResponse.setBootable(iso.isBootable());
        isoResponse.setFeatured(iso.isFeatured());
        isoResponse.setCrossZones(iso.isCrossZones());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setChecksum(iso.getChecksum());
        isoResponse.setDetails(iso.getDetails());

        // TODO: implement
        GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId());
        if (os != null) {
            isoResponse.setOsTypeId(os.getId());
            isoResponse.setOsTypeName(os.getDisplayName());
        } else {
            isoResponse.setOsTypeId(-1L);
            isoResponse.setOsTypeName("");
        }

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(iso.getAccountId());
        populateAccount(isoResponse, account.getId());
        populateDomain(isoResponse, account.getDomainId());

        Account caller = UserContext.current().getCaller();
        boolean isAdmin = false;
        if ((caller == null) || BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }
        // Add the zone ID
        DataCenterVO datacenter = ApiDBUtils.findZoneById(zoneId);
        isoResponse.setZoneId(zoneId);
        isoResponse.setZoneName(datacenter.getName());

        // If the user is an admin, add the template download status
        if (isAdmin || caller.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();
        if (isoSize > 0) {
            isoResponse.setSize(isoSize);
        }
        
        //set tag information
        List tags =  ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId());
        
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        isoResponse.setTags(tagResponses);

        isoResponse.setObjectName("iso");
        isoResponses.add(isoResponse);
        return isoResponses;
    }

    @Override
    public ListResponse createSecurityGroupResponses(
            List networkGroups) {
        List groupResultObjs = SecurityGroupResultObject
                .transposeNetworkGroups(networkGroups);

        ListResponse response = new ListResponse();
        List netGrpResponses = new ArrayList();
        for (SecurityGroupResultObject networkGroup : groupResultObjs) {
            SecurityGroupResponse netGrpResponse = new SecurityGroupResponse();
            netGrpResponse.setId(networkGroup.getId());
            netGrpResponse.setName(networkGroup.getName());
            netGrpResponse.setDescription(networkGroup.getDescription());

            populateOwner(netGrpResponse, networkGroup);

            List securityGroupRules = networkGroup
                    .getSecurityGroupRules();
            if ((securityGroupRules != null) && !securityGroupRules.isEmpty()) {
                List ingressRulesResponse = new ArrayList();
                List egressRulesResponse = new ArrayList();
                for (SecurityGroupRuleResultObject securityGroupRule : securityGroupRules) {
                    SecurityGroupRuleResponse ruleData = new SecurityGroupRuleResponse();
                    ruleData.setRuleId(securityGroupRule.getId());
                    ruleData.setProtocol(securityGroupRule.getProtocol());

                    if ("icmp".equalsIgnoreCase(securityGroupRule.getProtocol())) {
                        ruleData.setIcmpType(securityGroupRule.getStartPort());
                        ruleData.setIcmpCode(securityGroupRule.getEndPort());
                    } else {
                        ruleData.setStartPort(securityGroupRule.getStartPort());
                        ruleData.setEndPort(securityGroupRule.getEndPort());
                    }

                    if (securityGroupRule.getAllowedSecurityGroup() != null) {
                        ruleData.setSecurityGroupName(securityGroupRule
                                .getAllowedSecurityGroup());
                        ruleData.setAccountName(securityGroupRule
                                .getAllowedSecGroupAcct());
                    } else {
                        ruleData.setCidr(securityGroupRule
                                .getAllowedSourceIpCidr());
                    }

                    if (securityGroupRule.getRuleType() == SecurityRuleType.IngressRule) {
                        ruleData.setObjectName("ingressrule");
                        ingressRulesResponse.add(ruleData);
                    } else {
                        ruleData.setObjectName("egressrule");
                        egressRulesResponse.add(ruleData);
                    }
                }
                //set tag information
                List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, networkGroup.getId());
                List tagResponses = new ArrayList();
                for (ResourceTag tag : tags) {
                    ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                    tagResponses.add(tagResponse);
                }
                netGrpResponse.setTags(tagResponses);
                
                netGrpResponse
                        .setSecurityGroupIngressRules(ingressRulesResponse);
                netGrpResponse.setSecurityGroupEgressRules(egressRulesResponse);
            }
            netGrpResponse.setObjectName("securitygroup");
            netGrpResponses.add(netGrpResponse);
        }
        
        response.setResponses(netGrpResponses);
        return response;
    }

    @Override
    public SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group) {
        SecurityGroupResponse response = new SecurityGroupResponse();

        populateOwner(response, group);

        response.setDescription(group.getDescription());
        response.setId(group.getId());
        response.setName(group.getName());

        response.setObjectName("securitygroup");
        return response;

    }

    @Override
    public ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode) {
        UploadVO uploadInfo = ApiDBUtils.findUploadById(uploadId);
        ExtractResponse response = new ExtractResponse();
        response.setObjectName("template");
        response.setId(id);
        response.setName(ApiDBUtils.findTemplateById(id).getName());
        if (zoneId != null) {
            response.setZoneId(zoneId);
            response.setZoneName(ApiDBUtils.findZoneById(zoneId).getName());
        }
        response.setMode(mode);
        response.setState(uploadInfo.getUploadState().toString());
        response.setAccountId(accountId);
        response.setUrl(uploadInfo.getUploadUrl());
        return response;

    }

    @Override
    public String toSerializedString(CreateCmdResponse response, String responseType) {
        return ApiResponseSerializer.toSerializedString(response, responseType);
    }

    @Override
    public AsyncJobResponse createAsyncJobResponse(AsyncJob job) {
        AsyncJobResponse jobResponse = new AsyncJobResponse();
        jobResponse.setAccountId(job.getAccountId());
        jobResponse.setUserId(job.getUserId());
        jobResponse.setCmd(job.getCmd());
        jobResponse.setCreated(job.getCreated());
        jobResponse.setJobId(job.getId());
        jobResponse.setJobStatus(job.getStatus());
        jobResponse.setJobProcStatus(job.getProcessStatus());

        if (job.getInstanceType() != null && job.getInstanceId() != null) {
            jobResponse.setJobInstanceType(job.getInstanceType().toString());
            jobResponse.setJobInstanceId(job.getInstanceId());
        }
        jobResponse.setJobResultCode(job.getResultCode());

        boolean savedValue = SerializationContext.current().getUuidTranslation();
        SerializationContext.current().setUuidTranslation(false);
        
        Object resultObject = ApiSerializerHelper.fromSerializedString(job.getResult());
        jobResponse.setJobResult((ResponseObject) resultObject);
        SerializationContext.current().setUuidTranslation(savedValue);
        
        if (resultObject != null) {
            Class clz = resultObject.getClass();
            if (clz.isPrimitive() || clz.getSuperclass() == Number.class || clz == String.class || clz == Date.class) {
                jobResponse.setJobResultType("text");
            } else {
                jobResponse.setJobResultType("object");
            }
        }

        jobResponse.setObjectName("asyncjobs");
        return jobResponse;
    }

    @Override
    public List createTemplateResponses(long templateId, Long snapshotId, Long volumeId, boolean readyOnly) {
        VolumeVO volume = null;
        if (snapshotId != null) {
            Snapshot snapshot = ApiDBUtils.findSnapshotById(snapshotId);
            volume = findVolumeById(snapshot.getVolumeId());
        } else {
            volume = findVolumeById(volumeId);
        }
        return createTemplateResponses(templateId, volume.getDataCenterId(), readyOnly);
    }

    @Override
    public List createTemplateResponses(long templateId, Long vmId) {
        UserVm vm = findUserVmById(vmId);
        Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
        Host host = findHostById(hostId);
        return createTemplateResponses(templateId, host.getDataCenterId(), true);
    }

    @Override
    public EventResponse createEventResponse(Event event) {
        EventResponse responseEvent = new EventResponse();
        responseEvent.setCreated(event.getCreateDate());
        responseEvent.setDescription(event.getDescription());
        responseEvent.setEventType(event.getType());
        responseEvent.setId(event.getId());
        responseEvent.setLevel(event.getLevel());
        responseEvent.setParentId(event.getStartId());
        responseEvent.setState(event.getState());

        populateOwner(responseEvent, event);

        User user = ApiDBUtils.findUserById(event.getUserId());
        if (user != null) {
            responseEvent.setUsername(user.getUsername());
        }

        responseEvent.setObjectName("event");
        return responseEvent;
    }

            float overprovisioningFactor = 1;
    private List sumCapacities(List hostCapacities) {
        Map totalCapacityMap = new HashMap();
        Map usedCapacityMap = new HashMap();

        Set poolIdsToIgnore = new HashSet();
        Criteria c = new Criteria();
        // TODO: implement
        List allStoragePools = ApiDBUtils.searchForStoragePools(c);
        for (StoragePoolVO pool : allStoragePools) {
            StoragePoolType poolType = pool.getPoolType();
            if (!(poolType.isShared())) {// All the non shared storages shouldn't show up in the capacity calculation
                poolIdsToIgnore.add(pool.getId());
            }
        }

        float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

        // collect all the capacity types, sum allocated/used and sum total...get one capacity number for each
        for (Capacity capacity : hostCapacities) {

            // check if zone exist
            DataCenter zone = ApiDBUtils.findZoneById(capacity.getDataCenterId());
            if (zone == null) {
                continue;
            }

            short capacityType = capacity.getCapacityType();

            // If local storage then ignore
            if ((capacityType == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED || capacityType == Capacity.CAPACITY_TYPE_STORAGE)
                    && poolIdsToIgnore.contains(capacity.getHostOrPoolId())) {
                continue;
            }

            String key = capacity.getCapacityType() + "_" + capacity.getDataCenterId();
            String keyForPodTotal = key + "_-1";

            boolean sumPodCapacity = false;
            if (capacity.getPodId() != null) {
                key += "_" + capacity.getPodId();
                sumPodCapacity = true;
            }

            Long totalCapacity = totalCapacityMap.get(key);
            Long usedCapacity = usedCapacityMap.get(key);

            // reset overprovisioning factor to 1
            if (capacityType == Capacity.CAPACITY_TYPE_CPU) {
                overprovisioningFactor = cpuOverprovisioningFactor;
            }

            if (totalCapacity == null) {
                totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor));
            } else {
                totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity;
            }

            if (usedCapacity == null) {
                usedCapacity = new Long(capacity.getUsedCapacity());
            } else {
                usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity);
            }

            if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved
                                                                                                               // Capacity
                                                                                                               // accounts
// for
                // stopped
// vms
                // that
// have been
                // stopped
// within
                // an
// interval
                usedCapacity += capacity.getReservedCapacity();
            }

            totalCapacityMap.put(key, totalCapacity);
            usedCapacityMap.put(key, usedCapacity);

            if (sumPodCapacity) {
                totalCapacity = totalCapacityMap.get(keyForPodTotal);
                usedCapacity = usedCapacityMap.get(keyForPodTotal);

                overprovisioningFactor = 1;
                if (capacityType == Capacity.CAPACITY_TYPE_CPU) {
                    overprovisioningFactor = cpuOverprovisioningFactor;
                if (totalCapacity == null) {
                    totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor));
                } else {
                    totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity;
                }

                if (usedCapacity == null) {
                    usedCapacity = new Long(capacity.getUsedCapacity());
                } else {
                    usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity);
                }

                if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved
                                                                                                                   // Capacity
                                                                                                                   // accounts
                                                                                                                   // for
                                                                                                                   // stopped
                                                                                                                   // vms
// that
                    // have
// been
                    // stopped
                    // within
// an
                    // interval
                    usedCapacity += capacity.getReservedCapacity();
                }

                totalCapacityMap.put(keyForPodTotal, totalCapacity);
                usedCapacityMap.put(keyForPodTotal, usedCapacity);
            }
        }

        List summedCapacities = new ArrayList();
        for (String key : totalCapacityMap.keySet()) {
            CapacityVO summedCapacity = new CapacityVO();

            StringTokenizer st = new StringTokenizer(key, "_");
            summedCapacity.setCapacityType(Short.parseShort(st.nextToken()));
            summedCapacity.setDataCenterId(Long.parseLong(st.nextToken()));
            if (st.hasMoreTokens()) {
                summedCapacity.setPodId(Long.parseLong(st.nextToken()));
            }

            summedCapacity.setTotalCapacity(totalCapacityMap.get(key));
            summedCapacity.setUsedCapacity(usedCapacityMap.get(key));

            summedCapacities.add(summedCapacity);
        }
        return summedCapacities;
    }

    @Override
    public List createCapacityResponse(List result, DecimalFormat format) {
        List capacityResponses = new ArrayList();
        
        for (Capacity summedCapacity : result) {
            CapacityResponse capacityResponse = new CapacityResponse();
            capacityResponse.setCapacityTotal(summedCapacity.getTotalCapacity());
            capacityResponse.setCapacityType(summedCapacity.getCapacityType());
            capacityResponse.setCapacityUsed(summedCapacity.getUsedCapacity());
            if (summedCapacity.getPodId() != null) {
                capacityResponse.setPodId(summedCapacity.getPodId());
                HostPodVO pod = ApiDBUtils.findPodById(summedCapacity.getPodId());
                if (pod != null) {
                    capacityResponse.setPodName(pod.getName());
                }
            }
            if (summedCapacity.getClusterId() != null) {
                capacityResponse.setClusterId(summedCapacity.getClusterId());
                ClusterVO cluster = ApiDBUtils.findClusterById(summedCapacity.getClusterId());
                if (cluster != null) {
                    capacityResponse.setClusterName(cluster.getName());
                    if (summedCapacity.getPodId() == null) {
                        long podId = cluster.getPodId();
                        capacityResponse.setPodId(podId);
                        capacityResponse.setPodName(ApiDBUtils.findPodById(podId).getName());
                    }
                }
            }
            capacityResponse.setZoneId(summedCapacity.getDataCenterId());
            capacityResponse.setZoneName(ApiDBUtils.findZoneById(summedCapacity.getDataCenterId()).getName());
            if (summedCapacity.getUsedPercentage() != null){
                capacityResponse.setPercentUsed(format.format(summedCapacity.getUsedPercentage() * 100f));
            } else if (summedCapacity.getTotalCapacity() != 0) {
                capacityResponse.setPercentUsed(format.format((float) summedCapacity.getUsedCapacity() / (float) summedCapacity.getTotalCapacity() * 100f));
            } else {
                capacityResponse.setPercentUsed(format.format(0L));
            }

            capacityResponse.setObjectName("capacity");
            capacityResponses.add(capacityResponse);
        }

        return capacityResponses;
    }

    @Override
    public TemplatePermissionsResponse createTemplatePermissionsResponse(List accountNames, Long id, boolean isAdmin) {
        Long templateOwnerDomain = null;
        VirtualMachineTemplate template = ApiDBUtils.findTemplateById(id);
        Account templateOwner = ApiDBUtils.findAccountById(template.getAccountId());
        if (isAdmin) {
            // FIXME: we have just template id and need to get template owner from that
            if (templateOwner != null) {
                templateOwnerDomain = templateOwner.getDomainId();
            }
        }

        TemplatePermissionsResponse response = new TemplatePermissionsResponse();
        response.setId(template.getId());
        response.setPublicTemplate(template.isPublicTemplate());
        if (isAdmin && (templateOwnerDomain != null)) {
            response.setDomainId(templateOwnerDomain);
        }

        // Set accounts
        List projectIds = new ArrayList();
        List regularAccounts = new ArrayList();
        for (String accountName : accountNames) {
            Account account = ApiDBUtils.findAccountByNameDomain(accountName, templateOwner.getDomainId());
            if (account.getType() != Account.ACCOUNT_TYPE_PROJECT) {
                regularAccounts.add(accountName);
            } else {
                // convert account to projectIds
                Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());

                if (project.getUuid() != null && !project.getUuid().isEmpty())
                    projectIds.add(project.getUuid());
                else
                    projectIds.add(String.valueOf(project.getId()));
            }
        }

        if (!projectIds.isEmpty()) {
            response.setProjectIds(projectIds);
        }

        if (!regularAccounts.isEmpty()) {
            response.setAccountNames(regularAccounts);
        }

        response.setObjectName("templatepermission");
        return response;
    }

    @Override
    public AsyncJobResponse queryJobResult(QueryAsyncJobResultCmd cmd) {
        AsyncJob result = ApiDBUtils._asyncMgr.queryAsyncJobResult(cmd);
        return createAsyncJobResponse(result);
    }

    @Override
    public SecurityGroupResponse createSecurityGroupResponseFromSecurityGroupRule(List securityRules) {
        SecurityGroupResponse response = new SecurityGroupResponse();
        Map securiytGroupAccounts = new HashMap();
        Map allowedSecurityGroups = new HashMap();
        Map allowedSecuriytGroupAccounts = new HashMap();

        if ((securityRules != null) && !securityRules.isEmpty()) {
            SecurityGroup securityGroup = ApiDBUtils.findSecurityGroupById(securityRules.get(0).getSecurityGroupId());
            response.setId(securityGroup.getId());
            response.setName(securityGroup.getName());
            response.setDescription(securityGroup.getDescription());

            Account account = securiytGroupAccounts.get(securityGroup.getAccountId());

            if (account == null) {
                account = ApiDBUtils.findAccountById(securityGroup.getAccountId());
                securiytGroupAccounts.put(securityGroup.getAccountId(), account);
            }

            populateAccount(response, account.getId());
            populateDomain(response, account.getDomainId());

            List egressResponses = new ArrayList();
            List ingressResponses = new ArrayList();
            for (SecurityRule securityRule : securityRules) {
                SecurityGroupRuleResponse securityGroupData = new SecurityGroupRuleResponse();

                securityGroupData.setRuleId(securityRule.getId());
                securityGroupData.setProtocol(securityRule.getProtocol());
                if ("icmp".equalsIgnoreCase(securityRule.getProtocol())) {
                    securityGroupData.setIcmpType(securityRule.getStartPort());
                    securityGroupData.setIcmpCode(securityRule.getEndPort());
                } else {
                    securityGroupData.setStartPort(securityRule.getStartPort());
                    securityGroupData.setEndPort(securityRule.getEndPort());
                }

                Long allowedSecurityGroupId = securityRule.getAllowedNetworkId();
                if (allowedSecurityGroupId != null) {
                    SecurityGroup allowedSecurityGroup = allowedSecurityGroups.get(allowedSecurityGroupId);
                    if (allowedSecurityGroup == null) {
                        allowedSecurityGroup = ApiDBUtils.findSecurityGroupById(allowedSecurityGroupId);
                        allowedSecurityGroups.put(allowedSecurityGroupId, allowedSecurityGroup);
                    }

                    securityGroupData.setSecurityGroupName(allowedSecurityGroup.getName());

                    Account allowedAccount = allowedSecuriytGroupAccounts.get(allowedSecurityGroup.getAccountId());
                    if (allowedAccount == null) {
                        allowedAccount = ApiDBUtils.findAccountById(allowedSecurityGroup.getAccountId());
                        allowedSecuriytGroupAccounts.put(allowedAccount.getId(), allowedAccount);
                    }

                    securityGroupData.setAccountName(allowedAccount.getAccountName());
                } else {
                    securityGroupData.setCidr(securityRule.getAllowedSourceIpCidr());
                }

                if (securityRule.getRuleType() == SecurityRuleType.IngressRule) {
                    securityGroupData.setObjectName("ingressrule");
                    ingressResponses.add(securityGroupData);
                } else {
                    securityGroupData.setObjectName("egressrule");
                    egressResponses.add(securityGroupData);
                }

            }
            response.setSecurityGroupIngressRules(ingressResponses);
            response.setSecurityGroupEgressRules(egressResponses);
            response.setObjectName("securitygroup");

        }
        return response;
    }

    @Override
    public NetworkOfferingResponse createNetworkOfferingResponse(NetworkOffering offering) {
        NetworkOfferingResponse response = new NetworkOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setTags(offering.getTags());
        response.setTrafficType(offering.getTrafficType().toString());
        response.setIsDefault(offering.isDefault());
        response.setSpecifyVlan(offering.getSpecifyVlan());
        response.setConserveMode(offering.isConserveMode());
        response.setSpecifyIpRanges(offering.getSpecifyIpRanges());
        response.setAvailability(offering.getAvailability().toString());
        response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId()));
        if (offering.getServiceOfferingId() != null) {
            response.setServiceOfferingId(offering.getServiceOfferingId());
        } else {
            response.setServiceOfferingId(ApiDBUtils.findDefaultRouterServiceOffering());
        }
        if (offering.getGuestType() != null) {
            response.setGuestIpType(offering.getGuestType().toString());
        }

        response.setState(offering.getState().name());

        Map> serviceProviderMap = ApiDBUtils.listNetworkOfferingServices(offering.getId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            if (Service.Lb == service) {
                List lbCapResponse = new ArrayList();

                CapabilityResponse lbIsoaltion = new CapabilityResponse();
                lbIsoaltion.setName(Capability.SupportedLBIsolation.getName());
                lbIsoaltion.setValue(offering.getDedicatedLB() ? "dedicated" : "shared");
                lbCapResponse.add(lbIsoaltion);

                CapabilityResponse eLb = new CapabilityResponse();
                eLb.setName(Capability.ElasticLb.getName());
                eLb.setValue(offering.getElasticLb() ? "true" : "false");
                lbCapResponse.add(eLb);

                svcRsp.setCapabilities(lbCapResponse);
            } else if (Service.SourceNat == service) {
                List capabilities = new ArrayList();
                CapabilityResponse sharedSourceNat = new CapabilityResponse();
                sharedSourceNat.setName(Capability.SupportedSourceNatTypes.getName());
                sharedSourceNat.setValue(offering.getSharedSourceNat() ? "perzone" : "peraccount");
                capabilities.add(sharedSourceNat);

        response.setDns1(profile.getDns1());
                CapabilityResponse redundantRouter = new CapabilityResponse();
                redundantRouter.setName(Capability.RedundantRouter.getName());
                redundantRouter.setValue(offering.getRedundantRouter() ? "true" : "false");
                capabilities.add(redundantRouter);

                svcRsp.setCapabilities(capabilities);
            } else if (service == Service.StaticNat) {
                List staticNatCapResponse = new ArrayList();

                CapabilityResponse eIp = new CapabilityResponse();
                eIp.setName(Capability.ElasticIp.getName());
                eIp.setValue(offering.getElasticLb() ? "true" : "false");
                staticNatCapResponse.add(eIp);

                svcRsp.setCapabilities(staticNatCapResponse);
            }

            serviceResponses.add(svcRsp);
        }
        response.setForVpc(ApiDBUtils.isOfferingForVpc(offering));
        
        response.setServices(serviceResponses);
        response.setObjectName("networkoffering");
        return response;
    }

    @Override
    public NetworkResponse createNetworkResponse(Network network) {
        // need to get network profile in order to retrieve dns information from there
        NetworkProfile profile = ApiDBUtils.getNetworkProfile(network.getId());
        NetworkResponse response = new NetworkResponse();
        response.setId(network.getId());
        response.setName(network.getName());
        response.setDisplaytext(network.getDisplayText());
        if (network.getBroadcastDomainType() != null) {
            response.setBroadcastDomainType(network.getBroadcastDomainType().toString());
        }

        if (network.getTrafficType() != null) {
            response.setTrafficType(network.getTrafficType().name());
        }

        if (network.getGuestType() != null) {
            response.setType(network.getGuestType().toString());
        }

        response.setGateway(network.getGateway());

        // FIXME - either set netmask or cidr
        response.setCidr(network.getCidr());
        if (network.getCidr() != null) {
            response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
        }

        if (network.getBroadcastUri() != null) {
            String broadcastUri = network.getBroadcastUri().toString();
            response.setBroadcastUri(broadcastUri);
            String vlan="N/A";
            if (broadcastUri.startsWith("vlan")) {
                vlan = broadcastUri.substring("vlan://".length(), broadcastUri.length());
            }
            response.setVlan(vlan);
        }

        DataCenter zone = ApiDBUtils.findZoneById(network.getDataCenterId());
        response.setZoneId(network.getDataCenterId());
        response.setZoneName(zone.getName());
        response.setPhysicalNetworkId(network.getPhysicalNetworkId());

        // populate network offering information
        NetworkOffering networkOffering = ApiDBUtils.findNetworkOfferingById(network.getNetworkOfferingId());
        if (networkOffering != null) {
            response.setNetworkOfferingId(networkOffering.getId());
            response.setNetworkOfferingName(networkOffering.getName());
            response.setNetworkOfferingDisplayText(networkOffering.getDisplayText());
            response.setIsSystem(networkOffering.isSystemOnly());
            response.setNetworkOfferingAvailability(networkOffering.getAvailability().toString());
        }

        if (network.getAclType() != null) {
            response.setAclType(network.getAclType().toString());
        }
        response.setState(network.getState().toString());
        response.setRestartRequired(network.isRestartRequired());
        response.setRelated(network.getRelated());
        response.setNetworkDomain(network.getNetworkDomain());
        response.setDns2(profile.getDns2());
        // populate capability
        Map> serviceCapabilitiesMap = ApiDBUtils.getNetworkCapabilities(network.getId(), network.getDataCenterId());
        List serviceResponses = new ArrayList();
        if (serviceCapabilitiesMap != null) {
            for (Service service : serviceCapabilitiesMap.keySet()) {
                ServiceResponse serviceResponse = new ServiceResponse();
                // skip gateway service
                if (service == Service.Gateway) {
                    continue;
                }
                serviceResponse.setName(service.getName());

                // set list of capabilities for the service
                List capabilityResponses = new ArrayList();
                Map serviceCapabilities = serviceCapabilitiesMap.get(service);
                if (serviceCapabilities != null) {
                    for (Capability capability : serviceCapabilities.keySet()) {
                        CapabilityResponse capabilityResponse = new CapabilityResponse();
                        String capabilityValue = serviceCapabilities.get(capability);
                        capabilityResponse.setName(capability.getName());
                        capabilityResponse.setValue(capabilityValue);
                        capabilityResponse.setObjectName("capability");
                        capabilityResponses.add(capabilityResponse);
                    }
                    serviceResponse.setCapabilities(capabilityResponses);
                }

                serviceResponse.setObjectName("service");
                serviceResponses.add(serviceResponse);
            }
        }
        response.setServices(serviceResponses);

        if (network.getAclType() == null || network.getAclType() == ACLType.Account) {
            populateOwner(response, network);
        } else {
            // get domain from network_domain table
            Pair domainNetworkDetails = ApiDBUtils.getDomainNetworkDetails(network.getId());
            response.setDomainId(domainNetworkDetails.first());
            response.setSubdomainAccess(domainNetworkDetails.second());
        }

        Long dedicatedDomainId = ApiDBUtils.getDedicatedNetworkDomain(network.getId());
        if (dedicatedDomainId != null) {
            Domain domain = ApiDBUtils.findDomainById(dedicatedDomainId);
            response.setDomainId(dedicatedDomainId);
            response.setDomainName(domain.getName());
        }

        response.setSpecifyIpRanges(network.getSpecifyIpRanges());
        response.setCanUseForDeploy(ApiDBUtils.canUseForDeploy(network));
        response.setVpcId(network.getVpcId());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Network, network.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("network");
        return response;
    }

    @Override
    public Long getSecurityGroupId(String groupName, long accountId) {
        SecurityGroup sg = ApiDBUtils.getSecurityGroup(groupName, accountId);
        if (sg == null) {
            return null;
        } else {
            return sg.getId();
        }
    }

    @Override
    public ProjectResponse createProjectResponse(Project project) {
        ProjectResponse response = new ProjectResponse();
        response.setId(project.getId());
        response.setName(project.getName());
        response.setDisplaytext(project.getDisplayText());
        response.setState(project.getState().toString());

        Domain domain = ApiDBUtils.findDomainById(project.getDomainId());
        response.setDomainId(domain.getId());
        response.setDomain(domain.getName());

        response.setOwner(ApiDBUtils.getProjectOwner(project.getId()).getAccountName());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Project, project.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("project");
        return response;
    }

    @Override
    public FirewallResponse createFirewallResponse(FirewallRule fwRule) {
        FirewallResponse response = new FirewallResponse();

        response.setId(fwRule.getId());
        response.setProtocol(fwRule.getProtocol());
        if (fwRule.getSourcePortStart() != null) {
            response.setStartPort(Integer.toString(fwRule.getSourcePortStart()));
        }

        if (fwRule.getSourcePortEnd() != null) {
            response.setEndPort(Integer.toString(fwRule.getSourcePortEnd()));
        }

        List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setIcmpCode(fwRule.getIcmpCode());
        response.setIcmpType(fwRule.getIcmpType());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.FirewallRule, fwRule.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setState(stateToSet);
        response.setObjectName("firewallrule");
        return response;
    }
    
    @Override
    public NetworkACLResponse createNetworkACLResponse(FirewallRule networkACL) {
        NetworkACLResponse response = new NetworkACLResponse();

        response.setId(networkACL.getId());
        response.setProtocol(networkACL.getProtocol());
        if (networkACL.getSourcePortStart() != null) {
            response.setStartPort(Integer.toString(networkACL.getSourcePortStart()));
        }

        if (networkACL.getSourcePortEnd() != null) {
            response.setEndPort(Integer.toString(networkACL.getSourcePortEnd()));
        }

        List cidrs = ApiDBUtils.findFirewallSourceCidrs(networkACL.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        response.setTrafficType(networkACL.getTrafficType().toString());

        FirewallRule.State state = networkACL.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setIcmpCode(networkACL.getIcmpCode());
        response.setIcmpType(networkACL.getIcmpType());

        response.setState(stateToSet);
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.NetworkACL, networkACL.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        
        response.setObjectName("networkacl");
        return response;
    }

    public UserVmData newUserVmData(UserVm userVm) {
        UserVmData userVmData = new UserVmData();
        userVmData.setId(userVm.getId());
        userVmData.setName(userVm.getHostName());
        userVmData.setCreated(userVm.getCreated());
        userVmData.setGuestOsId(userVm.getGuestOSId());
        userVmData.setHaEnable(userVm.isHaEnabled());
        if (userVm.getState() != null) {
            userVmData.setState(userVm.getState().toString());
        }
        if (userVm.getDisplayName() != null) {
            userVmData.setDisplayName(userVm.getDisplayName());
        } else {
            userVmData.setDisplayName(userVm.getHostName());
        }
        userVmData.setInstanceName(userVm.getInstanceName());
        
        userVmData.setDomainId(userVm.getDomainId());

        if (userVm.getHypervisorType() != null) {
            userVmData.setHypervisor(userVm.getHypervisorType().toString());
        }

        if (userVm.getPassword() != null) {
            userVmData.setPassword(userVm.getPassword());
        }
        return userVmData;
    }

    public UserVmResponse newUserVmResponse(UserVmData userVmData, boolean caller_is_admin) {
        UserVmResponse userVmResponse = new UserVmResponse();

        userVmResponse.setHypervisor(userVmData.getHypervisor());
        userVmResponse.setId(userVmData.getId());
        userVmResponse.setName(userVmData.getName());

        userVmResponse.setDisplayName(userVmData.getDisplayName());

        populateAccount(userVmResponse, userVmData.getAccountId());
        populateDomain(userVmResponse, userVmData.getDomainId());

        userVmResponse.setCreated(userVmData.getCreated());
        userVmResponse.setState(userVmData.getState());
        userVmResponse.setHaEnable(userVmData.getHaEnable());
        userVmResponse.setGroupId(userVmData.getGroupId());
        userVmResponse.setGroup(userVmData.getGroup());
        userVmResponse.setZoneId(userVmData.getZoneId());
        userVmResponse.setZoneName(userVmData.getZoneName());
        if (caller_is_admin) {
            userVmResponse.setInstanceName(userVmData.getInstanceName());
            userVmResponse.setHostId(userVmData.getHostId());
            userVmResponse.setHostName(userVmData.getHostName());
        }
        userVmResponse.setTemplateId(userVmData.getTemplateId());
        userVmResponse.setTemplateName(userVmData.getTemplateName());
        userVmResponse.setTemplateDisplayText(userVmData.getTemplateDisplayText());
        userVmResponse.setPasswordEnabled(userVmData.getPasswordEnabled());
        userVmResponse.setIsoId(userVmData.getIsoId());
        userVmResponse.setIsoName(userVmData.getIsoName());
        userVmResponse.setIsoDisplayText(userVmData.getIsoDisplayText());
        userVmResponse.setServiceOfferingId(userVmData.getServiceOfferingId());
        userVmResponse.setServiceOfferingName(userVmData.getServiceOfferingName());
        userVmResponse.setCpuNumber(userVmData.getCpuNumber());
        userVmResponse.setCpuSpeed(userVmData.getCpuSpeed());
        userVmResponse.setMemory(userVmData.getMemory());
        userVmResponse.setCpuUsed(userVmData.getCpuUsed());
        userVmResponse.setNetworkKbsRead(userVmData.getNetworkKbsRead());
        userVmResponse.setNetworkKbsWrite(userVmData.getNetworkKbsWrite());
        userVmResponse.setGuestOsId(userVmData.getGuestOsId());
        userVmResponse.setRootDeviceId(userVmData.getRootDeviceId());
        userVmResponse.setRootDeviceType(userVmData.getRootDeviceType());
        userVmResponse.setPassword(userVmData.getPassword());
        userVmResponse.setJobId(userVmData.getJobId());
        userVmResponse.setJobStatus(userVmData.getJobStatus());
        userVmResponse.setForVirtualNetwork(userVmData.getForVirtualNetwork());

        Set securityGroupResponse = new HashSet();
        for (SecurityGroupData sgd : userVmData.getSecurityGroupList()) {
            if (sgd.getId() != null) {
                SecurityGroupResponse sgr = new SecurityGroupResponse();
                sgr.setId(sgd.getId());
                sgr.setName(sgd.getName());
                sgr.setDescription(sgd.getDescription());

                Account account = ApiDBUtils.findAccountByNameDomain(sgd.getAccountName(), sgd.getDomainId());
                if (account != null) {
                    populateAccount(sgr, account.getId());
                    populateDomain(sgr, account.getDomainId());
                }

                sgr.setObjectName(sgd.getObjectName());
                securityGroupResponse.add(sgr);
            }
        }
        userVmResponse.setSecurityGroupList(new ArrayList(securityGroupResponse));

        Set nicResponses = new HashSet();
        for (NicData nd : userVmData.getNics()) {
            NicResponse nr = new NicResponse();
            nr.setId(nd.getId());
            nr.setNetworkid(nd.getNetworkid());
            nr.setNetmask(nd.getNetmask());
            nr.setGateway(nd.getGateway());
            nr.setIpaddress(nd.getIpaddress());
            nr.setIsolationUri(nd.getIsolationUri());
            nr.setBroadcastUri(nd.getBroadcastUri());
            nr.setTrafficType(nd.getTrafficType());
            nr.setType(nd.getType());
            nr.setIsDefault(nd.getIsDefault());

    @Override
            nr.setMacAddress(nd.getMacAddress());
            nr.setObjectName(nd.getObjectName());
            nicResponses.add(nr);
        }
        userVmResponse.setNics(new ArrayList(nicResponses));
        userVmResponse.setPublicIpId(userVmData.getPublicIpId());
        userVmResponse.setPublicIp(userVmData.getPublicIp());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, userVmData.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        userVmResponse.setTags(tagResponses);

        return userVmResponse;
    }

    @Override
    public HypervisorCapabilitiesResponse createHypervisorCapabilitiesResponse(HypervisorCapabilities hpvCapabilities) {
        HypervisorCapabilitiesResponse hpvCapabilitiesResponse = new HypervisorCapabilitiesResponse();
        hpvCapabilitiesResponse.setId(hpvCapabilities.getId());
        hpvCapabilitiesResponse.setHypervisor(hpvCapabilities.getHypervisorType());
        hpvCapabilitiesResponse.setHypervisorVersion(hpvCapabilities.getHypervisorVersion());
        hpvCapabilitiesResponse.setIsSecurityGroupEnabled(hpvCapabilities.isSecurityGroupEnabled());
        hpvCapabilitiesResponse.setMaxGuestsLimit(hpvCapabilities.getMaxGuestsLimit());
        return hpvCapabilitiesResponse;
    }

    private void populateOwner(ControlledEntityResponse response, ControlledEntity object) {
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(object.getAccountId());

        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
            // find the project
            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
            response.setProjectId(project.getId());
            response.setProjectName(project.getName());
        } else {
            response.setAccountName(account.getAccountName());
        }

        Domain domain = ApiDBUtils.findDomainById(object.getDomainId());
        response.setDomainId(domain.getId());
        response.setDomainName(domain.getName());
    }

    private void populateAccount(ControlledEntityResponse response, long accountId) {
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(accountId);
        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
            // find the project
            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
            response.setProjectId(project.getId());
            response.setProjectName(project.getName());
        } else {
            response.setAccountName(account.getAccountName());
        }
    }

    private void populateDomain(ControlledEntityResponse response, long domainId) {
        Domain domain = ApiDBUtils.findDomainById(domainId);

        response.setDomainId(domain.getId());
        response.setDomainName(domain.getName());
    }

    @Override
    public ProjectAccountResponse createProjectAccountResponse(ProjectAccount projectAccount) {
        Account account = ApiDBUtils.findAccountById(projectAccount.getAccountId());
        ProjectAccountResponse projectAccountResponse = new ProjectAccountResponse();

        long projectId = projectAccount.getProjectId();
        projectAccountResponse.setProjectId(projectId);
        projectAccountResponse.setProjectName(ApiDBUtils.findProjectById(projectId).getName());

        projectAccountResponse.setId(account.getId());
        projectAccountResponse.setAccountName(account.getAccountName());
        projectAccountResponse.setAccountType(account.getType());
        projectAccountResponse.setRole(projectAccount.getAccountRole().toString());
        populateDomain(projectAccountResponse, account.getDomainId());

        // add all the users for an account as part of the response obj
        List usersForAccount = ApiDBUtils.listUsersByAccount(account.getAccountId());
        spResponse.setlbRuleId(lb.getId());
        List userResponseList = new ArrayList();
        for (UserVO user : usersForAccount) {
            UserResponse userResponse = createUserResponse(user);
            userResponseList.add(userResponse);
        }

        projectAccountResponse.setUsers(userResponseList);
        projectAccountResponse.setObjectName("projectaccount");

        return projectAccountResponse;
    }

    @Override
    public ProjectInvitationResponse createProjectInvitationResponse(ProjectInvitation invite) {
        ProjectInvitationResponse response = new ProjectInvitationResponse();
        response.setId(invite.getId());
        response.setProjectId(invite.getProjectId());
        response.setProjectName(ApiDBUtils.findProjectById(invite.getProjectId()).getName());
        response.setInvitationState(invite.getState().toString());

        if (invite.getForAccountId() != null) {
            Account account = ApiDBUtils.findAccountById(invite.getForAccountId());
            response.setAccountName(account.getAccountName());

        } else {
            response.setEmail(invite.getEmail());
        }

        populateDomain(response, invite.getInDomainId());

        response.setObjectName("projectinvitation");
        return response;
    }

    @Override
    public SystemVmInstanceResponse createSystemVmInstanceResponse(VirtualMachine vm) {
        SystemVmInstanceResponse vmResponse = new SystemVmInstanceResponse();
        vmResponse.setId(vm.getId());
        vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
        vmResponse.setName(vm.getHostName());
        if (vm.getHostId() != null) {
            vmResponse.setHostId(vm.getHostId());
        }
        if (vm.getState() != null) {
            vmResponse.setState(vm.getState().toString());
        }
        if (vm.getType() == Type.DomainRouter) {
            VirtualRouter router = (VirtualRouter) vm;
            if (router.getRole() != null) {
                vmResponse.setRole(router.getRole().toString());
            }
        }
        vmResponse.setObjectName("systemvminstance");
        return vmResponse;
    }

    @Override
    public PhysicalNetworkResponse createPhysicalNetworkResponse(PhysicalNetwork result) {
        PhysicalNetworkResponse response = new PhysicalNetworkResponse();

        response.setZoneId(result.getDataCenterId());
        response.setNetworkSpeed(result.getSpeed());
        response.setVlan(result.getVnet());
        response.setDomainId(result.getDomainId());
        response.setId(result.getUuid());
        if (result.getBroadcastDomainRange() != null) {
            response.setBroadcastDomainRange(result.getBroadcastDomainRange().toString());
        }
        response.setIsolationMethods(result.getIsolationMethods());
        response.setTags(result.getTags());
        if (result.getState() != null) {
            response.setState(result.getState().toString());
        }

        response.setName(result.getName());

        response.setObjectName("physicalnetwork");
        return response;
    }

    @Override
    public ServiceResponse createNetworkServiceResponse(Service service) {
        ServiceResponse response = new ServiceResponse();
        response.setName(service.getName());

        // set list of capabilities required for the service
        List capabilityResponses = new ArrayList();
        Capability[] capabilities = service.getCapabilities();
        for (Capability cap : capabilities) {
            CapabilityResponse capabilityResponse = new CapabilityResponse();
            capabilityResponse.setName(cap.getName());
            capabilityResponse.setObjectName("capability");
            if (cap.getName().equals(Capability.SupportedLBIsolation.getName()) ||
                    cap.getName().equals(Capability.SupportedSourceNatTypes.getName()) ||
                    cap.getName().equals(Capability.RedundantRouter.getName())) {
                capabilityResponse.setCanChoose(true);
            } else {
                capabilityResponse.setCanChoose(false);
            }
            capabilityResponses.add(capabilityResponse);
        }
        response.setCapabilities(capabilityResponses);

        // set list of providers providing this service
        List serviceProviders = ApiDBUtils.getProvidersForService(service);
        List serviceProvidersResponses = new ArrayList();
        for (Network.Provider serviceProvider : serviceProviders) {
            // return only Virtual Router/JuniperSRX as a provider for the firewall
            if (service == Service.Firewall && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX)) {
                continue;
            }

            ProviderResponse serviceProviderResponse = createServiceProviderResponse(serviceProvider);
            serviceProvidersResponses.add(serviceProviderResponse);
        }
        response.setProviders(serviceProvidersResponses);

        response.setObjectName("networkservice");
        return response;

    }

    private ProviderResponse createServiceProviderResponse(Provider serviceProvider) {
        ProviderResponse response = new ProviderResponse();
        response.setName(serviceProvider.getName());
        boolean canEnableIndividualServices = ApiDBUtils.canElementEnableIndividualServices(serviceProvider);
        response.setCanEnableIndividualServices(canEnableIndividualServices);
        return response;
    }

    @Override
    public ProviderResponse createNetworkServiceProviderResponse(PhysicalNetworkServiceProvider result) {
        ProviderResponse response = new ProviderResponse();
        response.setId(result.getUuid());
        response.setName(result.getProviderName());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        response.setDestinationPhysicalNetworkId(result.getDestinationPhysicalNetworkId());
        response.setState(result.getState().toString());

        // set enabled services
        List services = new ArrayList();
        for (Service service : result.getEnabledServices()) {
            services.add(service.getName());
        }
        response.setServices(services);

        response.setObjectName("networkserviceprovider");
        return response;
    }

    @Override
    public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType result) {
        TrafficTypeResponse response = new TrafficTypeResponse();
        response.setId(result.getUuid());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        response.setTrafficType(result.getTrafficType().toString());
        response.setXenLabel(result.getXenNetworkLabel());
        response.setKvmLabel(result.getKvmNetworkLabel());
        response.setVmwareLabel(result.getVmwareNetworkLabel());

        response.setObjectName("traffictype");
        return response;
    }

    @Override
    public VirtualRouterProviderResponse createVirtualRouterProviderResponse(VirtualRouterProvider result) {
        VirtualRouterProviderResponse response = new VirtualRouterProviderResponse();
        response.setId(result.getId());
        response.setNspId(result.getNspId());
        response.setEnabled(result.isEnabled());

        response.setObjectName("virtualrouterelement");
        return response;
    }

    @Override
    public LBStickinessResponse createLBStickinessPolicyResponse(
            StickinessPolicy stickinessPolicy, LoadBalancer lb) {
        LBStickinessResponse spResponse = new LBStickinessResponse();
        Account accountTemp = ApiDBUtils.findAccountById(lb.getAccountId());
        if (accountTemp != null) {
            spResponse.setAccountName(accountTemp.getAccountName());
            spResponse.setDomainId(accountTemp.getDomainId());
            spResponse.setDomainName(ApiDBUtils.findDomainById(
                    accountTemp.getDomainId()).getName());
        }

        List responses = new ArrayList();
        LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(
                stickinessPolicy);
        responses.add(ruleResponse);

        spResponse.setRules(responses);

        spResponse.setObjectName("stickinesspolicies");
        return spResponse;
    }

    @Override
    public LBStickinessResponse createLBStickinessPolicyResponse(
            List stickinessPolicies, LoadBalancer lb) {
        LBStickinessResponse spResponse = new LBStickinessResponse();

        if (lb == null)
            return spResponse;
        spResponse.setlbRuleId(lb.getId());
        Account account = ApiDBUtils.findAccountById(lb.getAccountId());
        if (account != null) {
            spResponse.setAccountName(account.getAccountName());
            spResponse.setDomainId(account.getDomainId());
            spResponse.setDomainName(ApiDBUtils.findDomainById(
                    account.getDomainId()).getName());
        }

        List responses = new ArrayList();
        for (StickinessPolicy stickinessPolicy : stickinessPolicies) {
            LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(stickinessPolicy);
            responses.add(ruleResponse);
        }
        spResponse.setRules(responses);

        spResponse.setObjectName("stickinesspolicies");
        return spResponse;
    }

    public LDAPConfigResponse createLDAPConfigResponse(String hostname,
            Integer port, Boolean useSSL, String queryFilter,
            String searchBase, String bindDN) {
        LDAPConfigResponse lr = new LDAPConfigResponse();
        lr.setHostname(hostname);
        lr.setPort(port.toString());
        lr.setUseSSL(useSSL.toString());
        lr.setQueryFilter(queryFilter);
        lr.setBindDN(bindDN);
        lr.setSearchBase(searchBase);
        lr.setObjectName("ldapconfig");
        return lr;
    }

    @Override
    public StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result) {
        StorageNetworkIpRangeResponse response = new StorageNetworkIpRangeResponse();
        response.setUuid(result.getUuid());
        response.setVlan(result.getVlan());
        response.setEndIp(result.getEndIp());
        response.setStartIp(result.getStartIp());
        response.setPodUuid(result.getPodUuid());
        response.setZoneUuid(result.getZoneUuid());
        response.setNetworkUuid(result.getNetworkUuid());
        response.setNetmask(result.getNetmask());
        response.setGateway(result.getGateway());
        response.setObjectName("storagenetworkiprange");
        return response;
    }
    
    @Override
    public Long getIdentiyId(String tableName, String token) {
        return ApiDispatcher.getIdentiyId(tableName, token);
    }
    
    @Override
    public ResourceTagResponse createResourceTagResponse(ResourceTag resourceTag, boolean keyValueOnly) {
        ResourceTagResponse response = new ResourceTagResponse();
        response.setKey(resourceTag.getKey());
        response.setValue(resourceTag.getValue());
        
        if (!keyValueOnly) {
            response.setResourceType(resourceTag.getResourceType().toString());        
            response.setId(ApiDBUtils.getUuid(String.valueOf(resourceTag.getResourceId()),resourceTag.getResourceType()));
            Long accountId = resourceTag.getAccountId();
            Long domainId = resourceTag.getDomainId();
            if (accountId != null) {
                Account account = ApiDBUtils.findAccountByIdIncludingRemoved(resourceTag.getAccountId());

                if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
                    // find the project
                    Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
                    response.setProjectId(project.getId());
                    response.setProjectName(project.getName());
                } else {
                    response.setAccountName(account.getAccountName());
                }
            }
            
            if (domainId != null) {
                response.setDomainId(domainId);
                response.setDomainName(ApiDBUtils.findDomainById(domainId).getName());
            }
            
            response.setCustomer(resourceTag.getCustomer());
        }
        
        response.setObjectName("tag");
  
        return response;
    }
    
    @Override
    public VpcOfferingResponse createVpcOfferingResponse(VpcOffering offering) {
        VpcOfferingResponse response = new VpcOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setIsDefault(offering.isDefault());
        response.setState(offering.getState().name());

        Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            serviceResponses.add(svcRsp);
        }
        response.setServices(serviceResponses);
        response.setObjectName("vpcoffering");
        return response;
    }
    
    
    @Override
    public VpcResponse createVpcResponse(Vpc vpc) {
        VpcResponse response = new VpcResponse();
        response.setId(vpc.getId());
        response.setName(vpc.getName());
        response.setDisplayText(vpc.getDisplayText());
        response.setState(vpc.getState().name());
        response.setVpcOfferingId(vpc.getVpcOfferingId());
        response.setCidr(vpc.getCidr());
        response.setRestartRequired(vpc.isRestartRequired());
        response.setNetworkDomain(vpc.getNetworkDomain());

        Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            serviceResponses.add(svcRsp);
        }
        
        List networkResponses = new ArrayList();
        List networks = ApiDBUtils.listVpcNetworks(vpc.getId());
        for (Network network : networks) {
            NetworkResponse ntwkRsp = createNetworkResponse(network);
            networkResponses.add(ntwkRsp);
        }
        
        DataCenter zone = ApiDBUtils.findZoneById(vpc.getZoneId());
        response.setZoneId(vpc.getZoneId());
        response.setZoneName(zone.getName());
        
        response.setNetworks(networkResponses);
        response.setServices(serviceResponses);
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Vpc, vpc.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        
        response.setObjectName("vpc");
        return response;
    }

    @Override
    public PrivateGatewayResponse createPrivateGatewayResponse(PrivateGateway result) {
        PrivateGatewayResponse response = new PrivateGatewayResponse();
        response.setId(result.getId());
        response.setVlan(result.getVlanTag());
        response.setGateway(result.getGateway());
        response.setNetmask(result.getNetmask());
        response.setVpcId(result.getVpcId());
        response.setZoneId(result.getZoneId());
        DataCenter zone = ApiDBUtils.findZoneById(result.getZoneId());
        response.setZoneName(zone.getName());
        response.setAddress(result.getIp4Address());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        response.setState(result.getState().toString());
        
        response.setObjectName("privategateway");
        
        return response;
    }
    
    @Override
    public StaticRouteResponse createStaticRouteResponse(StaticRoute result) {
        StaticRouteResponse response = new StaticRouteResponse();
        response.setId(result.getId());
        response.setVpcId(result.getVpcId());
        response.setCidr(result.getCidr());
        
        StaticRoute.State state = result.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        response.setState(stateToSet);
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.StaticRoute, result.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        response.setObjectName("staticroute");
        
        return response;
    }
  
    @Override
    public Site2SiteVpnGatewayResponse createSite2SiteVpnGatewayResponse(Site2SiteVpnGateway result) {
        Site2SiteVpnGatewayResponse response = new Site2SiteVpnGatewayResponse();
        response.setId(result.getId());
        response.setIp(ApiDBUtils.findIpAddressById(result.getAddrId()).getAddress().toString());
        response.setVpcId(result.getVpcId());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpngateway");
        
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        return response;
    }

    @Override
    public Site2SiteCustomerGatewayResponse createSite2SiteCustomerGatewayResponse(Site2SiteCustomerGateway result) {
        Site2SiteCustomerGatewayResponse response = new Site2SiteCustomerGatewayResponse();
        response.setId(result.getId());
        response.setGatewayIp(result.getGatewayIp());
        response.setGuestCidrList(result.getGuestCidrList());
        response.setIpsecPsk(result.getIpsecPsk());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpncustomergateway");
        
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        return response;
    }

    @Override
    public Site2SiteVpnConnectionResponse createSite2SiteVpnConnectionResponse(Site2SiteVpnConnection result) {
        Site2SiteVpnConnectionResponse response = new Site2SiteVpnConnectionResponse();
        response.setId(result.getId());
        
        response.setVpnGatewayId(result.getVpnGatewayId()); 
        Long vpnGatewayId = result.getVpnGatewayId();
        if(vpnGatewayId != null) {
        	Site2SiteVpnGatewayVO vpnGateway = ApiDBUtils.findVpnGatewayById(vpnGatewayId);
        	
        	long ipId = vpnGateway.getAddrId();
        	IPAddressVO ipObj = ApiDBUtils.findIpAddressById(ipId);
        	response.setIp(ipObj.getAddress().addr());  
        }
        
        response.setCustomerGatewayId(result.getCustomerGatewayId()); 
        Long customerGatewayId = result.getCustomerGatewayId();
        if(customerGatewayId != null) {
        	Site2SiteCustomerGatewayVO customerGateway = ApiDBUtils.findCustomerGatewayById(customerGatewayId);
        	response.setGatewayIp(customerGateway.getGatewayIp());
        	response.setGuestCidrList(customerGateway.getGuestCidrList());
        	response.setIpsecPsk(customerGateway.getIpsecPsk());
        	response.setIkePolicy(customerGateway.getIkePolicy());
        	response.setEspPolicy(customerGateway.getEspPolicy());
        	response.setLifetime(customerGateway.getLifetime());
        }      
                
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        response.setState(result.getState().toString());
        response.setCreated(result.getCreated());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpnconnection");
        return response;
    }
}
>>>>>>> 165b85fab5ea301289fceca30b53618d0453d36b
Solution content
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.api;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

import com.cloud.acl.ControlledEntity;
import com.cloud.acl.ControlledEntity.ACLType;
import com.cloud.api.ApiConstants.HostDetails;
import com.cloud.api.ApiConstants.VMDetails;
import com.cloud.api.commands.QueryAsyncJobResultCmd;
import com.cloud.api.response.AccountResponse;
import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.api.response.AsyncJobResponse;
import com.cloud.api.response.AutoScalePolicyResponse;
import com.cloud.api.response.AutoScaleVmGroupResponse;
import com.cloud.api.response.AutoScaleVmProfileResponse;
import com.cloud.api.response.CapabilityResponse;
import com.cloud.api.response.CapacityResponse;
import com.cloud.api.response.ClusterResponse;
import com.cloud.api.response.ConditionResponse;
import com.cloud.api.response.ConfigurationResponse;
import com.cloud.api.response.ControlledEntityResponse;
import com.cloud.api.response.CounterResponse;
import com.cloud.api.response.CreateCmdResponse;
import com.cloud.api.response.DiskOfferingResponse;
import com.cloud.api.response.DomainResponse;
import com.cloud.api.response.DomainRouterResponse;
import com.cloud.api.response.EventResponse;
import com.cloud.api.response.ExtractResponse;


import com.cloud.api.response.FirewallResponse;
import com.cloud.api.response.FirewallRuleResponse;
import com.cloud.api.response.HostResponse;
import com.cloud.api.response.HypervisorCapabilitiesResponse;
import com.cloud.api.response.IPAddressResponse;
import com.cloud.api.response.InstanceGroupResponse;
import com.cloud.api.response.IpForwardingRuleResponse;
import com.cloud.api.response.LBStickinessPolicyResponse;
import com.cloud.api.response.LBStickinessResponse;
import com.cloud.api.response.LDAPConfigResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.LoadBalancerResponse;
import com.cloud.api.response.NetworkACLResponse;
import com.cloud.api.response.NetworkOfferingResponse;
import com.cloud.api.response.NetworkResponse;
import com.cloud.api.response.NicResponse;
import com.cloud.api.response.PhysicalNetworkResponse;
import com.cloud.api.response.PodResponse;
import com.cloud.api.response.PrivateGatewayResponse;
import com.cloud.api.response.ProjectAccountResponse;
import com.cloud.api.response.ProjectInvitationResponse;
import com.cloud.api.response.ProjectResponse;
import com.cloud.api.response.ProviderResponse;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.api.response.ResourceCountResponse;
import com.cloud.api.response.ResourceLimitResponse;
import com.cloud.api.response.ResourceTagResponse;
import com.cloud.api.response.SecurityGroupResponse;
import com.cloud.api.response.SecurityGroupResultObject;
import com.cloud.api.response.SecurityGroupRuleResponse;
import com.cloud.api.response.SecurityGroupRuleResultObject;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.api.response.ServiceResponse;
import com.cloud.api.response.Site2SiteCustomerGatewayResponse;
import com.cloud.api.response.Site2SiteVpnConnectionResponse;
import com.cloud.api.response.Site2SiteVpnGatewayResponse;
import com.cloud.api.response.SnapshotPolicyResponse;
import com.cloud.api.response.SnapshotResponse;
import com.cloud.api.response.StaticRouteResponse;
import com.cloud.api.response.StorageNetworkIpRangeResponse;
import com.cloud.api.response.StoragePoolResponse;
import com.cloud.api.response.SwiftResponse;
import com.cloud.api.response.SystemVmInstanceResponse;
import com.cloud.api.response.SystemVmResponse;
import com.cloud.api.response.TemplatePermissionsResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.api.response.TrafficTypeResponse;
import com.cloud.api.response.UserResponse;
import com.cloud.api.response.UserVmResponse;
import com.cloud.api.response.VirtualRouterProviderResponse;
import com.cloud.api.response.VlanIpRangeResponse;
import com.cloud.api.response.VolumeResponse;
import com.cloud.api.response.VpcOfferingResponse;
import com.cloud.api.response.VpcResponse;
import com.cloud.api.response.VpnUsersResponse;
import com.cloud.api.response.ZoneResponse;
import com.cloud.async.AsyncJob;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
import com.cloud.configuration.Configuration;
import com.cloud.configuration.Resource.ResourceOwnerType;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimit;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.Pod;
import com.cloud.dc.StorageNetworkIpRange;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.domain.Domain;
import com.cloud.event.Event;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.HostStats;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.HypervisorCapabilities;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkProfile;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.Site2SiteCustomerGateway;
import com.cloud.network.Site2SiteCustomerGatewayVO;
import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.Site2SiteVpnGateway;
import com.cloud.network.Site2SiteVpnGatewayVO;
import com.cloud.network.VirtualRouterProvider;
import com.cloud.network.VpnUser;
import com.cloud.network.as.AutoScalePolicy;
import com.cloud.network.as.AutoScaleVmGroup;
import com.cloud.network.as.AutoScaleVmProfile;
import com.cloud.network.as.Condition;
import com.cloud.network.as.ConditionVO;
import com.cloud.network.as.Counter;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNatRule;
import com.cloud.network.rules.StickinessPolicy;
import com.cloud.network.security.SecurityGroup;
import com.cloud.network.security.SecurityGroupRules;
import com.cloud.network.security.SecurityGroupVO;
import com.cloud.network.security.SecurityRule;
import com.cloud.network.security.SecurityRule.SecurityRuleType;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.StaticRoute;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectAccount;
import com.cloud.projects.ProjectInvitation;
import com.cloud.server.Criteria;
import com.cloud.server.ResourceTag;
import com.cloud.server.ResourceTag.TaggedResourceType;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSCategoryVO;
import com.cloud.storage.Snapshot;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Swift;
import com.cloud.storage.UploadVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateSwiftVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.test.PodZoneConfig;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserContext;
import com.cloud.user.UserStatisticsVO;
import com.cloud.user.UserVO;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.InstanceGroup;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VmStats;
import com.cloud.vm.dao.UserVmData;
import com.cloud.vm.dao.UserVmData.NicData;
import com.cloud.vm.dao.UserVmData.SecurityGroupData;

public class ApiResponseHelper implements ResponseGenerator {
    public final Logger s_logger = Logger.getLogger(ApiResponseHelper.class);
    private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##");

    @Override
    public UserResponse createUserResponse(User user) {
        UserResponse userResponse = new UserResponse();
        Account account = ApiDBUtils.findAccountById(user.getAccountId());
        userResponse.setAccountName(account.getAccountName());
        userResponse.setAccountType(account.getType());
        userResponse.setCreated(user.getCreated());
        userResponse.setDomainId(account.getDomainId());
        userResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());
        userResponse.setEmail(user.getEmail());
        userResponse.setFirstname(user.getFirstname());
        userResponse.setId(user.getId());
        userResponse.setLastname(user.getLastname());
        userResponse.setState(user.getState().toString());
        userResponse.setTimezone(user.getTimezone());
        userResponse.setUsername(user.getUsername());
        userResponse.setApiKey(user.getApiKey());
        userResponse.setSecretKey(user.getSecretKey());
        userResponse.setObjectName("user");

        return userResponse;
    }

    // this method is used for response generation via createAccount (which creates an account + user)
    @Override
    public AccountResponse createUserAccountResponse(UserAccount user) {
        return createAccountResponse(ApiDBUtils.findAccountById(user.getAccountId()));
    }

    @Override
    public AccountResponse createAccountResponse(Account account) {
        boolean accountIsAdmin = (account.getType() == Account.ACCOUNT_TYPE_ADMIN);
        AccountResponse accountResponse = new AccountResponse();
        accountResponse.setId(account.getId());
        accountResponse.setName(account.getAccountName());
        accountResponse.setAccountType(account.getType());
        accountResponse.setDomainId(account.getDomainId());
        accountResponse.setDomainName(ApiDBUtils.findDomainById(account.getDomainId()).getName());
        accountResponse.setState(account.getState().toString());
        accountResponse.setNetworkDomain(account.getNetworkDomain());
        accountResponse.setDefaultZone(account.getDefaultZoneId());

        // get network stat
        List stats = ApiDBUtils.listUserStatsBy(account.getId());
        if (stats == null) {
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error searching for user stats");
        }

        Long bytesSent = 0L;
        Long bytesReceived = 0L;
        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);
        }
        accountResponse.setBytesReceived(bytesReceived);
        accountResponse.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);
        accountResponse.setVmLimit(vmLimitDisplay);
        accountResponse.setVmTotal(vmTotal);
        accountResponse.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());

        Long ips = ipLimit - ipTotal;
        // check how many free ips are left, and if it's less than max allowed number of ips from account - use this
        // value
        Long ipsLeft = ApiDBUtils.countFreePublicIps();
        boolean unlimited = true;
        } else {
        if (ips.longValue() > ipsLeft.longValue()) {
            ips = ipsLeft;
            unlimited = false;
        }

        String ipAvail = ((accountIsAdmin || ipLimit == -1) && unlimited) ? "Unlimited" : String.valueOf(ips);

        accountResponse.setIpLimit(ipLimitDisplay);
        accountResponse.setIpTotal(ipTotal);
        accountResponse.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);
        accountResponse.setVolumeLimit(volumeLimitDisplay);
        accountResponse.setVolumeTotal(volumeTotal);
        accountResponse.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);
        accountResponse.setSnapshotLimit(snapshotLimitDisplay);
        accountResponse.setSnapshotTotal(snapshotTotal);
        accountResponse.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);
        accountResponse.setTemplateLimit(templateLimitDisplay);
        accountResponse.setTemplateTotal(templateTotal);
        accountResponse.setTemplateAvailable(templateAvail);

        // Get stopped and running VMs
        int vmStopped = 0;
        int vmRunning = 0;

        List permittedAccounts = new ArrayList();
        permittedAccounts.add(account.getId());

        List virtualMachines = ApiDBUtils.searchForUserVMs(new Criteria(), permittedAccounts);

        // 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++;
            }
        }

        accountResponse.setVmStopped(vmStopped);
        accountResponse.setVmRunning(vmRunning);
        accountResponse.setObjectName("account");
        
        //get resource limits for projects
        Long projectLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.project, account.getId());
        if (offering.getDomainId() != null) {
        String projectLimitDisplay = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit);
        Long projectTotal = ApiDBUtils.getResourceCount(ResourceType.project, account.getId());
        String projectAvail = (accountIsAdmin || projectLimit == -1) ? "Unlimited" : String.valueOf(projectLimit - projectTotal);
        accountResponse.setProjectLimit(projectLimitDisplay);
        accountResponse.setProjectTotal(projectTotal);
        accountResponse.setProjectAvailable(projectAvail);
        
        //get resource limits for networks
        Long networkLimit = ApiDBUtils.findCorrectResourceLimit(ResourceType.network, account.getId());
        String networkLimitDisplay = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit);
        Long networkTotal = ApiDBUtils.getResourceCount(ResourceType.network, account.getId());
        String networkAvail = (accountIsAdmin || networkLimit == -1) ? "Unlimited" : String.valueOf(networkLimit - networkTotal);
        accountResponse.setNetworkLimit(networkLimitDisplay);
        accountResponse.setNetworkTotal(networkTotal);
        accountResponse.setNetworkAvailable(networkAvail);
      
        // adding all the users for an account as part of the response obj
        List usersForAccount = ApiDBUtils.listUsersByAccount(account.getAccountId());
        List userResponseList = new ArrayList();
        for (UserVO user : usersForAccount) {
            UserResponse userResponse = createUserResponse(user);
            userResponseList.add(userResponse);
        }

        accountResponse.setUsers(userResponseList);
        accountResponse.setDetails(ApiDBUtils.getAccountDetails(account.getId()));
        return accountResponse;
    }

    @Override
    public UserResponse createUserResponse(UserAccount user) {
        UserResponse userResponse = new UserResponse();
        userResponse.setAccountName(user.getAccountName());
        userResponse.setAccountType(user.getType());
        userResponse.setCreated(user.getCreated());
        userResponse.setDomainId(user.getDomainId());
        userResponse.setDomainName(ApiDBUtils.findDomainById(user.getDomainId()).getName());
        userResponse.setEmail(user.getEmail());
        userResponse.setFirstname(user.getFirstname());
        userResponse.setId(user.getId());
        userResponse.setLastname(user.getLastname());
        userResponse.setState(user.getState());
        userResponse.setTimezone(user.getTimezone());
        userResponse.setUsername(user.getUsername());
        userResponse.setApiKey(user.getApiKey());
        userResponse.setSecretKey(user.getSecretKey());
        userResponse.setAccountId((user.getAccountId()));
        userResponse.setObjectName("user");

        return userResponse;
    }

    @Override
    public DomainResponse createDomainResponse(Domain domain) {
        DomainResponse domainResponse = new DomainResponse();
        domainResponse.setDomainName(domain.getName());
        domainResponse.setId(domain.getId());
        domainResponse.setLevel(domain.getLevel());
        domainResponse.setNetworkDomain(domain.getNetworkDomain());
        domainResponse.setParentDomainId(domain.getParent());
        StringBuilder domainPath = new StringBuilder("ROOT");  
        (domainPath.append(domain.getPath())).deleteCharAt(domainPath.length() - 1);
        domainResponse.setPath(domainPath.toString());
        if (domain.getParent() != null) {
            domainResponse.setParentDomainName(ApiDBUtils.findDomainById(domain.getParent()).getName());
        }
        if (domain.getChildCount() > 0) {
            domainResponse.setHasChild(true);
        }
        domainResponse.setObjectName("domain");
        return domainResponse;
    }

    @Override
    public DiskOfferingResponse createDiskOfferingResponse(DiskOffering offering) {
        DiskOfferingResponse diskOfferingResponse = new DiskOfferingResponse();
        diskOfferingResponse.setId(offering.getId());
        diskOfferingResponse.setName(offering.getName());
        diskOfferingResponse.setDisplayText(offering.getDisplayText());
        diskOfferingResponse.setCreated(offering.getCreated());
        diskOfferingResponse.setDiskSize(offering.getDiskSize() / (1024 * 1024 * 1024));
            diskOfferingResponse.setDomain(ApiDBUtils.findDomainById(offering.getDomainId()).getName());
            diskOfferingResponse.setDomainId(offering.getDomainId());
        }
        diskOfferingResponse.setTags(offering.getTags());
        diskOfferingResponse.setCustomized(offering.isCustomized());
        diskOfferingResponse.setObjectName("diskoffering");
        return diskOfferingResponse;
    }

    @Override
    public ResourceLimitResponse createResourceLimitResponse(ResourceLimit limit) {
        ResourceLimitResponse resourceLimitResponse = new ResourceLimitResponse();
        if (limit.getResourceOwnerType() == ResourceOwnerType.Domain) {
            populateDomain(resourceLimitResponse, limit.getOwnerId());
        } else if (limit.getResourceOwnerType() == ResourceOwnerType.Account) {
            Account accountTemp = ApiDBUtils.findAccountById(limit.getOwnerId());
            populateAccount(resourceLimitResponse, limit.getOwnerId());
            populateDomain(resourceLimitResponse, accountTemp.getDomainId());
        }
        resourceLimitResponse.setResourceType(Integer.valueOf(limit.getType().getOrdinal()).toString());
        resourceLimitResponse.setMax(limit.getMax());
        resourceLimitResponse.setObjectName("resourcelimit");

        return resourceLimitResponse;
    }

    @Override
    public ResourceCountResponse createResourceCountResponse(ResourceCount resourceCount) {
        ResourceCountResponse resourceCountResponse = new ResourceCountResponse();

        if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Account) {
            Account accountTemp = ApiDBUtils.findAccountById(resourceCount.getOwnerId());
            if (accountTemp != null) {
                populateAccount(resourceCountResponse, accountTemp.getId());
                populateDomain(resourceCountResponse, accountTemp.getDomainId());
            }
        } else if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Domain) {
            populateDomain(resourceCountResponse, resourceCount.getOwnerId());
        }

        resourceCountResponse.setResourceType(Integer.valueOf(resourceCount.getType().getOrdinal()).toString());
        resourceCountResponse.setResourceCount(resourceCount.getCount());
        resourceCountResponse.setObjectName("resourcecount");
        return resourceCountResponse;
    }

    @Override
    public ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering) {
        ServiceOfferingResponse offeringResponse = new ServiceOfferingResponse();
        offeringResponse.setId(offering.getId());
        offeringResponse.setName(offering.getName());
        offeringResponse.setIsSystemOffering(offering.getSystemUse());
        offeringResponse.setDefaultUse(offering.getDefaultUse());
        offeringResponse.setSystemVmType(offering.getSystemVmType());
        offeringResponse.setDisplayText(offering.getDisplayText());
        offeringResponse.setCpuNumber(offering.getCpu());
        offeringResponse.setCpuSpeed(offering.getSpeed());
        offeringResponse.setMemory(offering.getRamSize());
        offeringResponse.setCreated(offering.getCreated());
        offeringResponse.setStorageType(offering.getUseLocalStorage() ? ServiceOffering.StorageType.local.toString() : ServiceOffering.StorageType.shared.toString());
        offeringResponse.setOfferHa(offering.getOfferHA());
        offeringResponse.setLimitCpuUse(offering.getLimitCpuUse());
        offeringResponse.setTags(offering.getTags());
        if (offering.getDomainId() != null) {
            offeringResponse.setDomain(ApiDBUtils.findDomainById(offering.getDomainId()).getName());
            offeringResponse.setDomainId(offering.getDomainId());
        }
        offeringResponse.setNetworkRate(offering.getRateMbps());
        offeringResponse.setHostTag(offering.getHostTag());
        offeringResponse.setObjectName("serviceoffering");

        return offeringResponse;
    }

    @Override
    public ConfigurationResponse createConfigurationResponse(Configuration cfg) {
        ConfigurationResponse cfgResponse = new ConfigurationResponse();
        cfgResponse.setCategory(cfg.getCategory());
        cfgResponse.setDescription(cfg.getDescription());
        cfgResponse.setName(cfg.getName());
        cfgResponse.setValue(cfg.getValue());
        cfgResponse.setObjectName("configuration");

        return cfgResponse;
    }

    @Override
    public SnapshotResponse createSnapshotResponse(Snapshot snapshot) {
        SnapshotResponse snapshotResponse = new SnapshotResponse();
        snapshotResponse.setId(snapshot.getId());

        populateOwner(snapshotResponse, snapshot);

        VolumeVO volume = findVolumeById(snapshot.getVolumeId());
        String snapshotTypeStr = snapshot.getType().name();
        snapshotResponse.setSnapshotType(snapshotTypeStr);
        snapshotResponse.setVolumeId(snapshot.getVolumeId());
        if (volume != null) {
            snapshotResponse.setVolumeName(volume.getName());
            snapshotResponse.setVolumeType(volume.getVolumeType().name());
        }
        snapshotResponse.setCreated(snapshot.getCreated());
        snapshotResponse.setName(snapshot.getName());
        snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId()));
        snapshotResponse.setState(snapshot.getStatus());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Snapshot, snapshot.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        snapshotResponse.setTags(tagResponses);
        
        snapshotResponse.setObjectName("snapshot");
        return snapshotResponse;
    }

    @Override
    public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) {
        SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse();
        policyResponse.setId(policy.getId());
        policyResponse.setVolumeId(policy.getVolumeId());
        policyResponse.setSchedule(policy.getSchedule());
        policyResponse.setIntervalType(policy.getInterval());
        policyResponse.setMaxSnaps(policy.getMaxSnaps());
        policyResponse.setTimezone(policy.getTimezone());
        policyResponse.setObjectName("snapshotpolicy");

        return policyResponse;
    }

    @Override
    public HostResponse createHostResponse(Host host) {
        return createHostResponse(host, EnumSet.of(HostDetails.all));
    }

    @Override
    public HostResponse createHostResponse(Host host, EnumSet details) {
        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.setRemoved(host.getRemoved());
        hostResponse.setCpuSpeed(host.getSpeed());
        hostResponse.setState(host.getStatus());
        hostResponse.setIpAddress(host.getPrivateIpAddress());
        hostResponse.setVersion(host.getVersion());
        hostResponse.setCreated(host.getCreated());

        if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)
                || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) {

            GuestOSCategoryVO guestOSCategory = ApiDBUtils.getHostGuestOSCategory(host.getId());
            if (guestOSCategory != null) {
                while (iter.hasNext()) {
                hostResponse.setOsCategoryId(guestOSCategory.getId());
                hostResponse.setOsCategoryName(guestOSCategory.getName());
            }
            hostResponse.setZoneName(ApiDBUtils.findZoneById(host.getDataCenterId()).getName());

            if (host.getPodId() != null) {
                HostPodVO pod = ApiDBUtils.findPodById(host.getPodId());
                if (pod != null) {
                    hostResponse.setPodName(pod.getName());
                }
            }

            if (host.getClusterId() != null) {
                ClusterVO cluster = ApiDBUtils.findClusterById(host.getClusterId());
                hostResponse.setClusterName(cluster.getName());
                hostResponse.setClusterType(cluster.getClusterType().toString());
            }
        }

        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        if (host.getType() == Host.Type.Routing) {
            if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) {
                // set allocated capacities
                Long mem = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_MEMORY);
                Long cpu = ApiDBUtils.getMemoryOrCpuCapacitybyHost(host.getId(), Capacity.CAPACITY_TYPE_CPU);

                hostResponse.setMemoryAllocated(mem);
                hostResponse.setMemoryTotal(host.getTotalMemory());
                String hostTags = ApiDBUtils.getHostTags(host.getId());
                hostResponse.setHostTags(hostTags);
                
                String haTag = ApiDBUtils.getHaTag();
                if (haTag != null && !haTag.isEmpty() && hostTags != null && !hostTags.isEmpty()) {
                    if (haTag.equalsIgnoreCase(hostTags)) {
                        hostResponse.setHaHost(true);
                    } else {
                        hostResponse.setHaHost(false);
                    }
                } else {
                    hostResponse.setHaHost(false);
                }
                
                hostResponse.setHypervisorVersion(host.getHypervisorVersion());

                String cpuAlloc = decimalFormat.format(((float) cpu / (float) (host.getCpus() * host.getSpeed())) * 100f) + "%";
                hostResponse.setCpuAllocated(cpuAlloc);
                String cpuWithOverprovisioning = new Float(host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor()).toString();
                hostResponse.setCpuWithOverprovisioning(cpuWithOverprovisioning);
            }

            if (details.contains(HostDetails.all) || details.contains(HostDetails.stats)) {
                // set CPU/RAM/Network stats
                String cpuUsed = null;
                HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId());
                if (hostStats != null) {
                    float cpuUtil = (float) hostStats.getCpuUtilization();
                    cpuUsed = decimalFormat.format(cpuUtil) + "%";
                    hostResponse.setCpuUsed(cpuUsed);
                    hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue());
                    hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue());
                    hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue());

                }
            }

        } else if (host.getType() == Host.Type.SecondaryStorage) {
            StorageStats secStorageStats = ApiDBUtils.getSecondaryStorageStatistics(host.getId());
            if (secStorageStats != null) {
                hostResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes());
                hostResponse.setDiskSizeAllocated(secStorageStats.getByteUsed());
            }
        }

        hostResponse.setLocalStorageActive(ApiDBUtils.isLocalStorageActiveOnHost(host));

        if (details.contains(HostDetails.all) || details.contains(HostDetails.events)) {
            Set possibleEvents = host.getStatus().getPossibleEvents();
            if ((possibleEvents != null) && !possibleEvents.isEmpty()) {
                String events = "";
                Iterator iter = possibleEvents.iterator();
                    com.cloud.host.Status.Event event = iter.next();
                    events += event.toString();
                    if (iter.hasNext()) {
                        events += "; ";
                    }
                }
                hostResponse.setEvents(events);
            }
        }

        hostResponse.setResourceState(host.getResourceState().toString());
        hostResponse.setObjectName("host");

        return hostResponse;
    }

    @Override
    public SwiftResponse createSwiftResponse(Swift swift) {
        SwiftResponse swiftResponse = new SwiftResponse();
        swiftResponse.setId(swift.getId());
        swiftResponse.setUrl(swift.getUrl());
        swiftResponse.setAccount(swift.getAccount());
        swiftResponse.setUsername(swift.getUserName());
        swiftResponse.setObjectName("swift");
        return swiftResponse;
    }

    @Override
    public VlanIpRangeResponse createVlanIpRangeResponse(Vlan vlan) {
        Long podId = ApiDBUtils.getPodIdForVlan(vlan.getId());

        VlanIpRangeResponse vlanResponse = new VlanIpRangeResponse();
        vlanResponse.setId(vlan.getId());
        vlanResponse.setForVirtualNetwork(vlan.getVlanType().equals(VlanType.VirtualNetwork));
        vlanResponse.setVlan(vlan.getVlanTag());
        vlanResponse.setZoneId(vlan.getDataCenterId());

        if (podId != null) {
            HostPodVO pod = ApiDBUtils.findPodById(podId);
            vlanResponse.setPodId(podId);
            if (pod != null) {
                vlanResponse.setPodName(pod.getName());
            }
        }

        vlanResponse.setGateway(vlan.getVlanGateway());
        vlanResponse.setNetmask(vlan.getVlanNetmask());

        // get start ip and end ip of corresponding vlan
        String ipRange = vlan.getIpRange();
        String[] range = ipRange.split("-");
        vlanResponse.setStartIp(range[0]);
        vlanResponse.setEndIp(range[1]);

        vlanResponse.setNetworkId(vlan.getNetworkId());
        Account owner = ApiDBUtils.getVlanAccount(vlan.getId());
        if (owner != null) {
            populateAccount(vlanResponse, owner.getId());
            populateDomain(vlanResponse, owner.getDomainId());
        }

        vlanResponse.setPhysicalNetworkId(vlan.getPhysicalNetworkId());

        vlanResponse.setObjectName("vlan");
        return vlanResponse;
    }

    @Override
    public IPAddressResponse createIPAddressResponse(IpAddress ipAddr) {
        VlanVO vlan = ApiDBUtils.findVlanById(ipAddr.getVlanId());
        boolean forVirtualNetworks = vlan.getVlanType().equals(VlanType.VirtualNetwork);
        long zoneId = ipAddr.getDataCenterId();

        IPAddressResponse ipResponse = new IPAddressResponse();
        ipResponse.setId(ipAddr.getId());
        ipResponse.setIpAddress(ipAddr.getAddress().toString());
        if (ipAddr.getAllocatedTime() != null) {
            ipResponse.setAllocated(ipAddr.getAllocatedTime());
        }
        ipResponse.setZoneId(zoneId);
        ipResponse.setZoneName(ApiDBUtils.findZoneById(ipAddr.getDataCenterId()).getName());
        ipResponse.setSourceNat(ipAddr.isSourceNat());
        ipResponse.setIsSystem(ipAddr.getSystem());

        // get account information
        if (ipAddr.getAllocatedToAccountId() != null) {
        populateOwner(ipResponse, ipAddr);
        }

        ipResponse.setForVirtualNetwork(forVirtualNetworks);
        ipResponse.setStaticNat(ipAddr.isOneToOneNat());

        if (ipAddr.getAssociatedWithVmId() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(ipAddr.getAssociatedWithVmId());
            ipResponse.setVirtualMachineId(vm.getId());
            ipResponse.setVirtualMachineName(vm.getHostName());
            if (vm.getDisplayName() != null) {
                ipResponse.setVirtualMachineDisplayName(vm.getDisplayName());
            } else {
                ipResponse.setVirtualMachineDisplayName(vm.getHostName());
            }
        }

        ipResponse.setAssociatedNetworkId(ipAddr.getAssociatedWithNetworkId());
        ipResponse.setVpcId(ipAddr.getVpcId());

        // Network id the ip is associated with (if associated networkId is null, try to get this information from vlan)
        Long vlanNetworkId = ApiDBUtils.getVlanNetworkId(ipAddr.getVlanId());

        // Network id the ip belongs to
        Long networkId;
        if (vlanNetworkId != null) {
            networkId = vlanNetworkId;
            networkId = ApiDBUtils.getPublicNetworkIdByZone(zoneId);
        }

        ipResponse.setNetworkId(networkId);
        ipResponse.setState(ipAddr.getState().toString());
        ipResponse.setPhysicalNetworkId(ipAddr.getPhysicalNetworkId());

        // show this info to admin only
        Account account = UserContext.current().getCaller();
        if ((account == null) || account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            ipResponse.setVlanId(ipAddr.getVlanId());
            ipResponse.setVlanName(ApiDBUtils.findVlanById(ipAddr.getVlanId()).getVlanTag());
        }
        
        if (ipAddr.getSystem()) {
            if (ipAddr.isOneToOneNat()) {
                ipResponse.setPurpose(IpAddress.Purpose.StaticNat.toString());
            } else {
                ipResponse.setPurpose(IpAddress.Purpose.Lb.toString());
            }
        }
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PublicIpAddress, ipAddr.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        ipResponse.setTags(tagResponses);
        
        ipResponse.setObjectName("ipaddress");
        return ipResponse;
    }

    @Override
    public LoadBalancerResponse createLoadBalancerResponse(LoadBalancer loadBalancer) {
        LoadBalancerResponse lbResponse = new LoadBalancerResponse();
        lbResponse.setId(loadBalancer.getId());
        lbResponse.setName(loadBalancer.getName());
        lbResponse.setDescription(loadBalancer.getDescription());
        List cidrs = ApiDBUtils.findFirewallSourceCidrs(loadBalancer.getId());
        lbResponse.setCidrList(StringUtils.join(cidrs, ","));

        IPAddressVO publicIp = ApiDBUtils.findIpAddressById(loadBalancer.getSourceIpAddressId());
        lbResponse.setPublicIpId(publicIp.getId());
        lbResponse.setPublicIp(publicIp.getAddress().addr());
        lbResponse.setPublicPort(Integer.toString(loadBalancer.getSourcePortStart()));
        lbResponse.setPrivatePort(Integer.toString(loadBalancer.getDefaultPortStart()));
        lbResponse.setAlgorithm(loadBalancer.getAlgorithm());
        FirewallRule.State state = loadBalancer.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        lbResponse.setState(stateToSet);
        populateOwner(lbResponse, loadBalancer);
        lbResponse.setZoneId(publicIp.getDataCenterId());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, loadBalancer.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        lbResponse.setTags(tagResponses);
        lbResponse.setObjectName("loadbalancer");
        return lbResponse;
    }

    @Override
    public PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
        String[] ipRange = new String[2];
        if (pod.getDescription() != null && pod.getDescription().length() > 0) {
            ipRange = pod.getDescription().split("-");
        } else {
            ipRange[0] = pod.getDescription();
        }

        PodResponse podResponse = new PodResponse();
        podResponse.setId(pod.getId());
        podResponse.setName(pod.getName());
        podResponse.setZoneId(pod.getDataCenterId());
        podResponse.setZoneName(PodZoneConfig.getZoneName(pod.getDataCenterId()));
        podResponse.setNetmask(NetUtils.getCidrNetmask(pod.getCidrSize()));
        podResponse.setStartIp(ipRange[0]);
        podResponse.setEndIp(((ipRange.length > 1) && (ipRange[1] != null)) ? ipRange[1] : "");
        podResponse.setGateway(pod.getGateway());
        podResponse.setAllocationState(pod.getAllocationState().toString());
        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, pod.getId(), null);
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, pod.getId(), null);
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, null, pod.getId(), pod.getDataCenterId()));
            podResponse.setCapacitites(new ArrayList(capacityResponses));
        }
        podResponse.setObjectName("pod");
        return podResponse;
    }

    @Override
    public ZoneResponse createZoneResponse(DataCenter dataCenter, Boolean showCapacities) {
        Account account = UserContext.current().getCaller();
        ZoneResponse zoneResponse = new ZoneResponse();
        zoneResponse.setId(dataCenter.getId());
        zoneResponse.setName(dataCenter.getName());
        zoneResponse.setSecurityGroupsEnabled(ApiDBUtils.isSecurityGroupEnabledInZone(dataCenter.getId()));

        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());
            // FIXME zoneResponse.setVlan(dataCenter.get.getVnet());
            zoneResponse.setGuestCidrAddress(dataCenter.getGuestNetworkCidr());
        }

        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(dataCenter.getId(), null, null);
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(dataCenter.getId(), null, null);
                UserVm userVm = ApiDBUtils.findUserVmById(vm.getId());
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, null, null, dataCenter.getId()));

            zoneResponse.setCapacitites(new ArrayList(capacityResponses));
        }

        // set network domain info
        zoneResponse.setDomain(dataCenter.getDomain());

        // set domain info
        Long domainId = dataCenter.getDomainId();
        if (domainId != null) {
            Domain domain = ApiDBUtils.findDomainById(domainId);
            zoneResponse.setDomainId(domain.getId());
            zoneResponse.setDomainName(domain.getName());
        }

        zoneResponse.setType(dataCenter.getNetworkType().toString());
        zoneResponse.setAllocationState(dataCenter.getAllocationState().toString());
        zoneResponse.setZoneToken(dataCenter.getZoneToken());
        zoneResponse.setDhcpProvider(dataCenter.getDhcpProvider());
        zoneResponse.setObjectName("zone");
        return zoneResponse;
    }

    private List getStatsCapacityresponse(Long poolId, Long clusterId, Long podId, Long zoneId) {
        List capacities = new ArrayList();
        capacities.add(ApiDBUtils.getStoragePoolUsedStats(poolId, clusterId, podId, zoneId));
        if (clusterId == null && podId == null) {
            capacities.add(ApiDBUtils.getSecondaryStorageUsedStats(poolId, zoneId));
        }

        List capacityResponses = new ArrayList();
        for (CapacityVO capacity : capacities) {
            CapacityResponse capacityResponse = new CapacityResponse();
            capacityResponse.setCapacityType(capacity.getCapacityType());
            capacityResponse.setCapacityUsed(capacity.getUsedCapacity());
            capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
            if (capacityResponse.getCapacityTotal() != 0) {
                capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
            } else {
                capacityResponse.setPercentUsed(s_percentFormat.format(0L));
            }
            capacityResponses.add(capacityResponse);
        }

        return capacityResponses;
    }

    @Override
    public VolumeResponse createVolumeResponse(Volume volume) {
        VolumeResponse volResponse = new VolumeResponse();
        volResponse.setId(volume.getId());

        if (volume.getName() != null) {
            volResponse.setName(volume.getName());
        } else {
            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 && volume.getState() != Volume.State.Destroy) {
            VMInstanceVO vm = ApiDBUtils.findVMInstanceById(instanceId);
            if (vm != null) {
                volResponse.setVirtualMachineId(vm.getId());
                volResponse.setVirtualMachineName(vm.getHostName());
                if (userVm != null) {
                    if (userVm.getDisplayName() != null) {
                        volResponse.setVirtualMachineDisplayName(userVm.getDisplayName());
                    } else {
                        volResponse.setVirtualMachineDisplayName(userVm.getHostName());
                    }
                    volResponse.setVirtualMachineState(vm.getState().toString());
                } else {
                    s_logger.error("User Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
                }
            } else {
                s_logger.error("Vm with Id: " + instanceId + " does not exist for volume " + volume.getId());
            }
        }

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

        volResponse.setCreated(volume.getCreated());
        volResponse.setState(volume.getState().toString());
        if(volume.getState() == Volume.State.UploadOp){
            com.cloud.storage.VolumeHostVO volumeHostRef = ApiDBUtils.findVolumeHostRef(volume.getId(), volume.getDataCenterId());
            volResponse.setSize(volumeHostRef.getSize());
            volResponse.setCreated(volumeHostRef.getCreated());
            Account caller = UserContext.current().getCaller();
            if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN)
            volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volumeHostRef.getFormat()).toString());
            if (volumeHostRef.getDownloadState() != Status.DOWNLOADED) {
                String volumeStatus = "Processing";
                if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                    if (volumeHostRef.getDownloadPercent() == 100) {
                        volumeStatus = "Checking Volume";
                    } else {
                        volumeStatus = volumeHostRef.getDownloadPercent() + "% Uploaded";
                    }
                    volResponse.setState("Uploading");
                } else {
                    volumeStatus = volumeHostRef.getErrorString();
                    if(volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.NOT_DOWNLOADED){
                        volResponse.setState("UploadNotStarted");
                    }else {
                        volResponse.setState("UploadError");
                    }
                }
                volResponse.setStatus(volumeStatus);
            } else if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                volResponse.setStatus("Upload Complete");
                volResponse.setState("Uploaded");
            } else {
                volResponse.setStatus("Successfully Installed");
            }            
        }
        
        populateOwner(volResponse, volume);

        String storageType;
        try {
            if (volume.getPoolId() == null) {
                if (volume.getState() == Volume.State.Allocated || volume.getState() == Volume.State.UploadOp) {
                    /* set it as shared, so the UI can attach it to VM */
                    storageType = "shared";
                } else {
                    storageType = "unknown";
                }
            } else {
                storageType = ApiDBUtils.volumeIsOnSharedStorage(volume.getId()) ? ServiceOffering.StorageType.shared.toString() : ServiceOffering.StorageType.local.toString();
            }
        } catch (InvalidParameterValueException e) {
            s_logger.error(e.getMessage(), e);
            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Volume " + volume.getName() + " does not have a valid ID");
        }

        volResponse.setStorageType(storageType);
        if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
            volResponse.setServiceOfferingId(volume.getDiskOfferingId());
        } else {
            volResponse.setDiskOfferingId(volume.getDiskOfferingId());
        }

        DiskOfferingVO diskOffering = ApiDBUtils.findDiskOfferingById(volume.getDiskOfferingId());
        if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
                    }
            volResponse.setServiceOfferingName(diskOffering.getName());
            volResponse.setServiceOfferingDisplayText(diskOffering.getDisplayText());
        } else {
            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.setSourceId(volume.getSourceId());
        // if (volume.getSourceType() != null) {
        // volResponse.setSourceType(volume.getSourceType().toString());
        // }

        // return hypervisor for ROOT and Resource domain only
        Account caller = UserContext.current().getCaller();
        if ((caller.getType() == Account.ACCOUNT_TYPE_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) && volume.getState() != Volume.State.UploadOp) {            
            volResponse.setHypervisor(ApiDBUtils.getVolumeHyperType(volume.getId()).toString());            
        }

        volResponse.setAttached(volume.getAttached());
        volResponse.setDestroyed(volume.getState() == Volume.State.Destroy);        
        boolean isExtractable = true;
        if (volume.getVolumeType() != Volume.Type.DATADISK) { // Datadisk dont have any template dependence.
            VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
            if (template != null) { // For ISO based volumes template = null and we allow extraction of all ISO based
                // volumes
                isExtractable = template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;                
            }
        }
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Volume, volume.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        volResponse.setTags(tagResponses);
        
        volResponse.setExtractable(isExtractable);
        volResponse.setObjectName("volume");
        return volResponse;
    }

    @Override
    public InstanceGroupResponse createInstanceGroupResponse(InstanceGroup group) {
        InstanceGroupResponse groupResponse = new InstanceGroupResponse();
        groupResponse.setId(group.getId());
        groupResponse.setName(group.getName());
        groupResponse.setCreated(group.getCreated());

        populateOwner(groupResponse, group);

        groupResponse.setObjectName("instancegroup");
        return groupResponse;
    }

    @Override
    public StoragePoolResponse createStoragePoolResponse(StoragePool pool) {
        StoragePoolResponse poolResponse = new StoragePoolResponse();
        poolResponse.setId(pool.getId());
        poolResponse.setName(pool.getName());
        poolResponse.setState(pool.getStatus());
        poolResponse.setPath(pool.getPath());
        poolResponse.setIpAddress(pool.getHostAddress());
        poolResponse.setZoneId(pool.getDataCenterId());
        poolResponse.setZoneName(ApiDBUtils.findZoneById(pool.getDataCenterId()).getName());
        if (pool.getPoolType() != null) {
            poolResponse.setType(pool.getPoolType().toString());
        }
        if (pool.getPodId() != null) {
            poolResponse.setPodId(pool.getPodId());
            HostPodVO pod = ApiDBUtils.findPodById(pool.getPodId());
            if (pod != null) {
                poolResponse.setPodName(pod.getName());
            }
        }
        if (pool.getCreated() != null) {
            poolResponse.setCreated(pool.getCreated());
        }

        StorageStats stats = ApiDBUtils.getStoragePoolStatistics(pool.getId());

        if (state.equals(FirewallRule.State.Revoke)) {
        long allocatedSize = ApiDBUtils.getStorageCapacitybyPool(pool.getId(), Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED);
        poolResponse.setDiskSizeTotal(pool.getCapacityBytes());
        poolResponse.setDiskSizeAllocated(allocatedSize);

        if (stats != null) {
            Long used = stats.getByteUsed();
            poolResponse.setDiskSizeUsed(used);
        }

        if (pool.getClusterId() != null) {
            ClusterVO cluster = ApiDBUtils.findClusterById(pool.getClusterId());
            poolResponse.setClusterId(cluster.getId());
            poolResponse.setClusterName(cluster.getName());
        }
        poolResponse.setTags(ApiDBUtils.getStoragePoolTags(pool.getId()));
        poolResponse.setObjectName("storagepool");
        return poolResponse;
    }

    @Override
    public ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities) {
        ClusterResponse clusterResponse = new ClusterResponse();
        clusterResponse.setId(cluster.getId());
        clusterResponse.setName(cluster.getName());
        clusterResponse.setPodId(cluster.getPodId());
        clusterResponse.setZoneId(cluster.getDataCenterId());
        clusterResponse.setHypervisorType(cluster.getHypervisorType().toString());
        clusterResponse.setClusterType(cluster.getClusterType().toString());
        clusterResponse.setAllocationState(cluster.getAllocationState().toString());
        clusterResponse.setManagedState(cluster.getManagedState().toString());
        HostPodVO pod = ApiDBUtils.findPodById(cluster.getPodId());
        if (pod != null) {
            clusterResponse.setPodName(pod.getName());
        }
        DataCenterVO zone = ApiDBUtils.findZoneById(cluster.getDataCenterId());
        clusterResponse.setZoneName(zone.getName());
        if (showCapacities != null && showCapacities) {
            List capacities = ApiDBUtils.getCapacityByClusterPodZone(null, null, cluster.getId());
            Set capacityResponses = new HashSet();
            float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

            for (SummedCapacity capacity : capacities) {
                CapacityResponse capacityResponse = new CapacityResponse();
                capacityResponse.setCapacityType(capacity.getCapacityType());
                capacityResponse.setCapacityUsed(capacity.getUsedCapacity());

                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_CPU) {
                    capacityResponse.setCapacityTotal(new Long((long) (capacity.getTotalCapacity() * cpuOverprovisioningFactor)));
                } else if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
                    List c = ApiDBUtils.findNonSharedStorageForClusterPodZone(null, null, cluster.getId());
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity() - c.get(0).getTotalCapacity());
                    capacityResponse.setCapacityUsed(capacity.getUsedCapacity() - c.get(0).getUsedCapacity());
                } else {
                    capacityResponse.setCapacityTotal(capacity.getTotalCapacity());
                }
                if (capacityResponse.getCapacityTotal() != 0) {
                    capacityResponse.setPercentUsed(s_percentFormat.format((float) capacityResponse.getCapacityUsed() / (float) capacityResponse.getCapacityTotal() * 100f));
                } else {
                    capacityResponse.setPercentUsed(s_percentFormat.format(0L));
                }
                capacityResponses.add(capacityResponse);
            }
            // Do it for stats as well.
            capacityResponses.addAll(getStatsCapacityresponse(null, cluster.getId(), pod.getId(), pod.getDataCenterId()));
            clusterResponse.setCapacitites(new ArrayList(capacityResponses));
        }
        clusterResponse.setObjectName("cluster");
        return clusterResponse;
    }

    @Override
    public FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRule fwRule) {
        FirewallRuleResponse response = new FirewallRuleResponse();
        response.setId(fwRule.getId());
        response.setPrivateStartPort(Integer.toString(fwRule.getDestinationPortStart()));
        response.setPrivateEndPort(Integer.toString(fwRule.getDestinationPortEnd()));
        response.setProtocol(fwRule.getProtocol());
        response.setPublicStartPort(Integer.toString(fwRule.getSourcePortStart()));
        response.setPublicEndPort(Integer.toString(fwRule.getSourcePortEnd()));
        List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        if (ip != null && fwRule.getDestinationIpAddress() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(fwRule.getVirtualMachineId());
            if (vm != null) {
                response.setVirtualMachineId(vm.getId());
                response.setVirtualMachineName(vm.getHostName());
                
                if (vm.getDisplayName() != null) {
                    response.setVirtualMachineDisplayName(vm.getDisplayName());
                } else {
                    response.setVirtualMachineDisplayName(vm.getHostName());
                }
            }
        }
        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.PortForwardingRule, fwRule.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        
        response.setState(stateToSet);
        response.setObjectName("portforwardingrule");
        return response;
    }

    @Override
    public IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule) {
        IpForwardingRuleResponse response = new IpForwardingRuleResponse();
        response.setId(fwRule.getId());
        response.setProtocol(fwRule.getProtocol());

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        if (ip != null && fwRule.getDestIpAddress() != null) {
            UserVm vm = ApiDBUtils.findUserVmById(ip.getAssociatedWithVmId());
            if (vm != null) {// vm might be destroyed
                response.setVirtualMachineId(vm.getId());
                response.setVirtualMachineName(vm.getHostName());
                if (vm.getDisplayName() != null) {
                    response.setVirtualMachineDisplayName(vm.getDisplayName());
                } else {
                    response.setVirtualMachineDisplayName(vm.getHostName());
                }
            }
        }
        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
            stateToSet = "Deleting";
        }

        response.setStartPort(fwRule.getSourcePortStart());
        response.setEndPort(fwRule.getSourcePortEnd());
        response.setProtocol(fwRule.getProtocol());
        response.setState(stateToSet);
        response.setObjectName("ipforwardingrule");
        return response;
    }

    @Override
    public List createUserVmResponse(String objectName, EnumSet details, UserVm... userVms) {
        Account caller = UserContext.current().getCaller();
        Map dataCenters = new HashMap();
        Map hosts = new HashMap();
        Map templates = new HashMap();
        Map serviceOfferings = new HashMap();
        Map networks = new HashMap();
        List vmResponses = new ArrayList();

        for (UserVm userVm : userVms) {
            UserVmResponse userVmResponse = new UserVmResponse();
            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.setId(userVm.getId());
            userVmResponse.setName(userVm.getHostName());
            userVmResponse.setCreated(userVm.getCreated());

            userVmResponse.setHaEnable(userVm.isHaEnabled());

            if (userVm.getDisplayName() != null) {
                userVmResponse.setDisplayName(userVm.getDisplayName());
            } else {
                userVmResponse.setDisplayName(userVm.getHostName());
            }
            
            if (caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {
                userVmResponse.setInstanceName(userVm.getInstanceName());
            }
            
            if (userVm.getPassword() != null) {
                userVmResponse.setPassword(userVm.getPassword());
            }

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

            }

            // Data Center Info
            DataCenter zone = dataCenters.get(userVm.getDataCenterIdToDeployIn());
            if (zone == null) {
                zone = ApiDBUtils.findZoneById(userVm.getDataCenterIdToDeployIn());
                dataCenters.put(zone.getId(), zone);
            }

            userVmResponse.setZoneId(zone.getId());
            userVmResponse.setZoneName(zone.getName());

            // if user is an admin, display host id
            if (((caller == null) || (caller.getType() == Account.ACCOUNT_TYPE_ADMIN)) && (userVm.getHostId() != null)) {
                Host host = hosts.get(userVm.getHostId());

                if (host == null) {
                    host = ApiDBUtils.findHostById(userVm.getHostId());
                    hosts.put(host.getId(), host);
                }

                userVmResponse.setHostId(host.getId());
                userVmResponse.setHostName(host.getName());
            }

            if (userVm.getState() != null) {
                if (userVm.getHostId() != null) {
                    Host host = hosts.get(userVm.getHostId());

                    if (host == null) {
                        host = ApiDBUtils.findHostById(userVm.getHostId());
                        hosts.put(host.getId(), host);
                    if (host.getStatus() != com.cloud.host.Status.Up) {
                        userVmResponse.setState(VirtualMachine.State.Unknown.toString());
                    } else {
                        userVmResponse.setState(userVm.getState().toString());
                    }
                } else {
                    userVmResponse.setState(userVm.getState().toString());
                }
            }

            if (userVm.getHypervisorType() != null) {
                userVmResponse.setHypervisor(userVm.getHypervisorType().toString());
            }
            
            if (details.contains(VMDetails.all) || details.contains(VMDetails.tmpl)) {
                // Template Info
                VMTemplateVO template = templates.get(userVm.getTemplateId());
                if (template == null) {
                    template = ApiDBUtils.findTemplateById(userVm.getTemplateId());
                    if (template != null) {
                        templates.put(template.getId(), template);
                    }
                }

                if (template != null) {
                    userVmResponse.setTemplateId(userVm.getTemplateId());
                    userVmResponse.setTemplateName(template.getName());
                    userVmResponse.setTemplateDisplayText(template.getDisplayText());
                    userVmResponse.setPasswordEnabled(template.getEnablePassword());
                } else {
                    userVmResponse.setTemplateId(-1L);
                    userVmResponse.setTemplateName("ISO Boot");
                    userVmResponse.setTemplateDisplayText("ISO Boot");
                    userVmResponse.setPasswordEnabled(false);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.iso)) {
                // ISO Info
                VMTemplateVO iso = templates.get(userVm.getIsoId());
                if (iso == null) {
                    iso = ApiDBUtils.findTemplateById(userVm.getIsoId());
                    if (iso != null) {
                        templates.put(iso.getId(), iso);
                    }
                }

                if (iso != null) {
                    userVmResponse.setIsoId(iso.getId());
                    userVmResponse.setIsoName(iso.getName());
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.servoff)) {
                // Service Offering Info
                ServiceOffering offering = serviceOfferings.get(userVm.getServiceOfferingId());

                if (offering == null) {
                    offering = ApiDBUtils.findServiceOfferingById(userVm.getServiceOfferingId());
                    serviceOfferings.put(offering.getId(), offering);
                }

                userVmResponse.setServiceOfferingId(offering.getId());
                userVmResponse.setServiceOfferingName(offering.getName());
                userVmResponse.setCpuNumber(offering.getCpu());
                userVmResponse.setCpuSpeed(offering.getSpeed());
                userVmResponse.setMemory(offering.getRamSize());
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.volume)) {
                VolumeVO rootVolume = ApiDBUtils.findRootVolume(userVm.getId());
                if (rootVolume != null) {
                    userVmResponse.setRootDeviceId(rootVolume.getDeviceId());
                    String rootDeviceType = "Not created";
                    if (rootVolume.getPoolId() != null) {
                        StoragePoolVO storagePool = ApiDBUtils.findStoragePoolById(rootVolume.getPoolId());
                        rootDeviceType = storagePool.getPoolType().toString();
                    }
                    userVmResponse.setRootDeviceType(rootDeviceType);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.stats)) {
                // stats calculation
                DecimalFormat decimalFormat = new DecimalFormat("#.##");
                String cpuUsed = null;
                VmStats vmStats = ApiDBUtils.getVmStatistics(userVm.getId());
                if (vmStats != null) {
                    float cpuUtil = (float) vmStats.getCPUUtilization();
                    cpuUsed = decimalFormat.format(cpuUtil) + "%";
                    userVmResponse.setCpuUsed(cpuUsed);

                    Double networkKbRead = Double.valueOf(vmStats.getNetworkReadKBs());
                    userVmResponse.setNetworkKbsRead(networkKbRead.longValue());

                    Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
                    userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
                }
            }

            userVmResponse.setGuestOsId(userVm.getGuestOSId());

            if (details.contains(VMDetails.all) || details.contains(VMDetails.secgrp)) {
                // security groups - list only when zone is security group enabled
                if (zone.isSecurityGroupEnabled()) {
                    List securityGroups = ApiDBUtils.getSecurityGroupsForVm(userVm.getId());
                    List securityGroupResponse = new ArrayList();
                    for (SecurityGroupVO grp : securityGroups) {
                        SecurityGroupResponse resp = new SecurityGroupResponse();
                        resp.setId(grp.getId());
                        resp.setName(grp.getName());
                        resp.setDescription(grp.getDescription());
                        resp.setObjectName("securitygroup");
                        securityGroupResponse.add(resp);
                    }
                    userVmResponse.setSecurityGroupList(securityGroupResponse);
                }
            }

            if (details.contains(VMDetails.all) || details.contains(VMDetails.nics)) {
                List nicProfiles = ApiDBUtils.getNics(userVm);
                List nicResponses = new ArrayList();
                for (NicProfile singleNicProfile : nicProfiles) {
                    NicResponse nicResponse = new NicResponse();
                    nicResponse.setId(singleNicProfile.getId());
                    nicResponse.setIpaddress(singleNicProfile.getIp4Address());
                    nicResponse.setGateway(singleNicProfile.getGateway());
                    nicResponse.setNetmask(singleNicProfile.getNetmask());
                    nicResponse.setNetworkid(singleNicProfile.getNetworkId());
                    if (acct.getType() == Account.ACCOUNT_TYPE_ADMIN) {
                        if (singleNicProfile.getBroadCastUri() != null) {
                            nicResponse.setBroadcastUri(singleNicProfile.getBroadCastUri().toString());
                        }
                        if (singleNicProfile.getIsolationUri() != null) {
                            nicResponse.setIsolationUri(singleNicProfile.getIsolationUri().toString());
                        }
                    }

                    // Long networkId = singleNicProfile.getNetworkId();
                    Network network = networks.get(singleNicProfile.getNetworkId());
                    if (network == null) {
                        network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                        networks.put(singleNicProfile.getNetworkId(), network);
                    }

                    nicResponse.setTrafficType(network.getTrafficType().toString());
                    nicResponse.setType(network.getGuestType().toString());
                    nicResponse.setIsDefault(singleNicProfile.isDefaultNic());
                    nicResponse.setObjectName("nic");
                    nicResponses.add(nicResponse);
                }
                userVmResponse.setNics(nicResponses);
            }
            
            //set tag information
            List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, userVm.getId());
            List tagResponses = new ArrayList();
            for (ResourceTag tag : tags) {
                ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                tagResponses.add(tagResponse);
            }
            userVmResponse.setTags(tagResponses);
            
            IpAddress ip = ApiDBUtils.findIpByAssociatedVmId(userVm.getId());
            if (ip != null) {
                userVmResponse.setPublicIpId(ip.getId());
                userVmResponse.setPublicIp(ip.getAddress().addr());
            }

            userVmResponse.setObjectName(objectName);
            vmResponses.add(userVmResponse);
        }

        return vmResponses;
    }

    @Override
    public List createUserVmResponse(String objectName, UserVm... userVms) {
        Account caller = UserContext.current().getCaller();
        boolean caller_is_admin = ((caller == null) || (caller.getType() == Account.ACCOUNT_TYPE_ADMIN));

        populateDomain(response, owner.getDomainId());
        Hashtable vmDataList = new Hashtable();
        // Initialise the vmdatalist with the input data
        for (UserVm userVm : userVms) {
            UserVmData userVmData = newUserVmData(userVm);
            vmDataList.put(userVm.getId(), userVmData);
        }

        vmDataList = ApiDBUtils.listVmDetails(vmDataList);

        // initialize vmresponse from vmdatalist
        List vmResponses = new ArrayList();
        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        for (UserVmData uvd : vmDataList.values()) {
            UserVmResponse userVmResponse = newUserVmResponse(uvd, caller_is_admin);

            // stats calculation
            String cpuUsed = null;
            // VmStats vmStats = ApiDBUtils.getVmStatistics(userVmResponse.getId());
            VmStats vmStats = ApiDBUtils.getVmStatistics(uvd.getId());
            if (vmStats != null) {
                float cpuUtil = (float) vmStats.getCPUUtilization();
                cpuUsed = decimalFormat.format(cpuUtil) + "%";
                userVmResponse.setCpuUsed(cpuUsed);

                Double networkKbRead = Double.valueOf(vmStats.getNetworkReadKBs());
                userVmResponse.setNetworkKbsRead(networkKbRead.longValue());

                Double networkKbWrite = Double.valueOf(vmStats.getNetworkWriteKBs());
                userVmResponse.setNetworkKbsWrite(networkKbWrite.longValue());
            }
            userVmResponse.setObjectName(objectName);

            vmResponses.add(userVmResponse);
        }
        return vmResponses;
    }

    @Override
    public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) {
        Account caller = UserContext.current().getCaller();
        Map serviceOfferings = new HashMap();

        DomainRouterResponse routerResponse = new DomainRouterResponse();
        routerResponse.setId(router.getId());
        routerResponse.setZoneId(router.getDataCenterIdToDeployIn());
        routerResponse.setName(router.getHostName());
        routerResponse.setTemplateId(router.getTemplateId());
        routerResponse.setCreated(router.getCreated());
        routerResponse.setState(router.getState());
        routerResponse.setIsRedundantRouter(router.getIsRedundantRouter());
        routerResponse.setRedundantState(router.getRedundantState().toString());

        if (caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {
            if (router.getHostId() != null) {
                routerResponse.setHostId(router.getHostId());
                routerResponse.setHostName(ApiDBUtils.findHostById(router.getHostId()).getName());
            }
            routerResponse.setPodId(router.getPodIdToDeployIn());
            List nicProfiles = ApiDBUtils.getNics(router);
            for (NicProfile singleNicProfile : nicProfiles) {
                Network network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                if (network != null) {
                    if (network.getTrafficType() == TrafficType.Public) {
                        routerResponse.setPublicIp(singleNicProfile.getIp4Address());
                        routerResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setPublicNetmask(singleNicProfile.getNetmask());
                        routerResponse.setGateway(singleNicProfile.getGateway());
                        routerResponse.setPublicNetworkId(singleNicProfile.getNetworkId());
                    } else if (network.getTrafficType() == TrafficType.Control) {
                        routerResponse.setLinkLocalIp(singleNicProfile.getIp4Address());
                        routerResponse.setLinkLocalMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setLinkLocalNetmask(singleNicProfile.getNetmask());
                        routerResponse.setLinkLocalNetworkId(singleNicProfile.getNetworkId());
                    } else if (network.getTrafficType() == TrafficType.Guest) {
                        routerResponse.setGuestIpAddress(singleNicProfile.getIp4Address());
                        routerResponse.setGuestMacAddress(singleNicProfile.getMacAddress());
                        routerResponse.setGuestNetmask(singleNicProfile.getNetmask());
            }
                        routerResponse.setGuestNetworkId(singleNicProfile.getNetworkId());
                        routerResponse.setNetworkDomain(network.getNetworkDomain());
                    }
                }
            }
        }

        // Service Offering Info
        ServiceOffering offering = serviceOfferings.get(router.getServiceOfferingId());

        if (offering == null) {
            offering = ApiDBUtils.findServiceOfferingById(router.getServiceOfferingId());
            serviceOfferings.put(offering.getId(), offering);
        }
        routerResponse.setServiceOfferingId(offering.getId());
        routerResponse.setServiceOfferingName(offering.getName());

        populateOwner(routerResponse, router);

        DataCenter zone = ApiDBUtils.findZoneById(router.getDataCenterIdToDeployIn());
        if (zone != null) {
            routerResponse.setZoneName(zone.getName());
            routerResponse.setDns1(zone.getDns1());
            routerResponse.setDns2(zone.getDns2());
        }

        routerResponse.setVpcId(router.getVpcId());

        routerResponse.setObjectName("domainrouter");
        return routerResponse;
    }

    @Override
    public SystemVmResponse createSystemVmResponse(VirtualMachine vm) {
        SystemVmResponse vmResponse = new SystemVmResponse();
        if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy) {
            // SystemVm vm = (SystemVm) systemVM;
            vmResponse.setId(vm.getId());
            vmResponse.setObjectId(vm.getId());
            vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
            vmResponse.setZoneId(vm.getDataCenterIdToDeployIn());

            vmResponse.setName(vm.getHostName());
            vmResponse.setPodId(vm.getPodIdToDeployIn());
            vmResponse.setTemplateId(vm.getTemplateId());
            vmResponse.setCreated(vm.getCreated());

            if (vm.getHostId() != null) {
                vmResponse.setHostId(vm.getHostId());
                vmResponse.setHostName(ApiDBUtils.findHostById(vm.getHostId()).getName());
            }

            if (vm.getState() != null) {
                vmResponse.setState(vm.getState().toString());
            }

            // for console proxies, add the active sessions
            if (vm.getType() == Type.ConsoleProxy) {
                ConsoleProxyVO proxy = ApiDBUtils.findConsoleProxy(vm.getId());
                // proxy can be already destroyed
                if (proxy != null) {
                    vmResponse.setActiveViewerSessions(proxy.getActiveSession());
                }
            }

            DataCenter zone = ApiDBUtils.findZoneById(vm.getDataCenterIdToDeployIn());
            if (zone != null) {
                vmResponse.setZoneName(zone.getName());
                vmResponse.setDns1(zone.getDns1());
                vmResponse.setDns2(zone.getDns2());

            List nicProfiles = ApiDBUtils.getNics(vm);
            for (NicProfile singleNicProfile : nicProfiles) {
                Network network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
                if (network != null) {
                    if (network.getTrafficType() == TrafficType.Management) {
                        vmResponse.setPrivateIp(singleNicProfile.getIp4Address());
                        vmResponse.setPrivateMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setPrivateNetmask(singleNicProfile.getNetmask());
                    } else if (network.getTrafficType() == TrafficType.Control) {
                        vmResponse.setLinkLocalIp(singleNicProfile.getIp4Address());
                        vmResponse.setLinkLocalMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setLinkLocalNetmask(singleNicProfile.getNetmask());
                    } else if (network.getTrafficType() == TrafficType.Public || network.getTrafficType() == TrafficType.Guest) {
        
                        /*In basic zone, public ip has TrafficType.Guest*/
                        vmResponse.setPublicIp(singleNicProfile.getIp4Address());
                        vmResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
                        vmResponse.setPublicNetmask(singleNicProfile.getNetmask());
                        vmResponse.setGateway(singleNicProfile.getGateway());
                    }
                }
            }
        }
        vmResponse.setObjectName("systemvm");
        return vmResponse;
    }

    @Override
    public Host findHostById(Long hostId) {
        return ApiDBUtils.findHostById(hostId);
    }

    @Override
    public User findUserById(Long userId) {
        return ApiDBUtils.findUserById(userId);
    }

    @Override
    public UserVm findUserVmById(Long vmId) {
        return ApiDBUtils.findUserVmById(vmId);

    }

    @Override
    public VolumeVO findVolumeById(Long volumeId) {
        return ApiDBUtils.findVolumeById(volumeId);
    }

    @Override
    public Account findAccountByNameDomain(String accountName, Long domainId) {
        return ApiDBUtils.findAccountByNameDomain(accountName, domainId);
    }

    @Override
    public VirtualMachineTemplate findTemplateById(Long templateId) {
        return ApiDBUtils.findTemplateById(templateId);
    }

    @Override
    public VpnUsersResponse createVpnUserResponse(VpnUser vpnUser) {
        VpnUsersResponse vpnResponse = new VpnUsersResponse();
        vpnResponse.setId(vpnUser.getId());
        vpnResponse.setUserName(vpnUser.getUsername());

        populateOwner(vpnResponse, vpnUser);

        vpnResponse.setObjectName("vpnuser");
        return vpnResponse;
    }

    @Override
    public RemoteAccessVpnResponse createRemoteAccessVpnResponse(RemoteAccessVpn vpn) {
        RemoteAccessVpnResponse vpnResponse = new RemoteAccessVpnResponse();
        vpnResponse.setPublicIpId(vpn.getServerAddressId());
        vpnResponse.setPublicIp(ApiDBUtils.findIpAddressById(vpn.getServerAddressId()).getAddress().addr());
        vpnResponse.setIpRange(vpn.getIpRange());
        vpnResponse.setPresharedKey(vpn.getIpsecPresharedKey());
        vpnResponse.setDomainId(vpn.getDomainId());

        populateOwner(vpnResponse, vpn);

        vpnResponse.setState(vpn.getState().toString());
        vpnResponse.setObjectName("remoteaccessvpn");

        return vpnResponse;
    }

    @Override
    public TemplateResponse createIsoResponse(VirtualMachineTemplate result) {
        TemplateResponse response = new TemplateResponse();
        response.setId(result.getId());

        response.setName(result.getName());
        response.setDisplayText(result.getDisplayText());
        response.setPublic(result.isPublicTemplate());
        response.setCreated(result.getCreated());
        response.setFormat(result.getFormat());
        response.setOsTypeId(result.getGuestOSId());
        response.setOsTypeName(ApiDBUtils.findGuestOSById(result.getGuestOSId()).getDisplayName());
        response.setDetails(result.getDetails());
        Account caller = UserContext.current().getCaller();

        if (result.getFormat() == ImageFormat.ISO) { // Templates are always bootable
            response.setBootable(result.isBootable());
        } else {
            response.setHypervisor(result.getHypervisorType().toString());// hypervisors are associated with templates
        }

        // add account ID and name
        Account owner = ApiDBUtils.findAccountById(result.getAccountId());
        populateAccount(response, owner.getId());
        //set tag information
        List tags = null;
        if (result.getFormat() == ImageFormat.ISO) {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, result.getId());
        } else {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, result.getId());
        }
        
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("iso");
        return response;
    }

    @Override
    public List createTemplateResponses(long templateId, Long zoneId, boolean readyOnly) {
        if (zoneId == null || zoneId == -1) {
            List responses = new ArrayList();
            List dcs = new ArrayList();
            responses = createSwiftTemplateResponses(templateId);
            if (!responses.isEmpty()) {
                return responses;
            }
            dcs.addAll(ApiDBUtils.listZones());
            for (DataCenterVO dc : dcs) {
                responses.addAll(createTemplateResponses(templateId, dc.getId(), readyOnly));
            }
            return responses;
        } else {
            return createTemplateResponses(templateId, zoneId.longValue(), readyOnly);
        }
    }

    private List createSwiftTemplateResponses(long templateId) {
        VirtualMachineTemplate template = findTemplateById(templateId);
        List responses = new ArrayList();
        VMTemplateSwiftVO templateSwiftRef = ApiDBUtils.findTemplateSwiftRef(templateId);
        if (templateSwiftRef == null) {
            return responses;
        }

        TemplateResponse templateResponse = new TemplateResponse();
        templateResponse.setId(template.getId());
        templateResponse.setName(template.getName());
        templateResponse.setDisplayText(template.getDisplayText());
        templateResponse.setPublic(template.isPublicTemplate());
        templateResponse.setCreated(templateSwiftRef.getCreated());

        templateResponse.setReady(true);
        templateResponse.setFeatured(template.isFeatured());
        templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM));
        templateResponse.setPasswordEnabled(template.getEnablePassword());
        templateResponse.setCrossZones(template.isCrossZones());
        templateResponse.setFormat(template.getFormat());
        templateResponse.setDetails(template.getDetails());
        if (template.getTemplateType() != null) {
            templateResponse.setTemplateType(template.getTemplateType().toString());
        }

        templateResponse.setHypervisor(template.getHypervisorType().toString());

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

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId());
        populateAccount(templateResponse, account.getId());
        populateDomain(templateResponse, account.getDomainId());

        Account caller = UserContext.current().getCaller();
        boolean isAdmin = false;
        if (BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }

        // If the user is an Admin, add the template download status
        if (isAdmin || caller.getId() == template.getAccountId()) {
            // add download status
            templateResponse.setStatus("Successfully Installed");
        }

        Long templateSize = templateSwiftRef.getSize();
        if (templateSize > 0) {
            templateResponse.setSize(templateSize);
        }

        templateResponse.setChecksum(template.getChecksum());
        templateResponse.setSourceTemplateId(template.getSourceTemplateId());

        templateResponse.setChecksum(template.getChecksum());

        templateResponse.setTemplateTag(template.getTemplateTag());

        templateResponse.setObjectName("template");
        responses.add(templateResponse);
        return responses;
    }

    @Override
    public List createTemplateResponses(long templateId, long zoneId, boolean readyOnly) {
        VirtualMachineTemplate template = findTemplateById(templateId);
        List responses = new ArrayList();
        VMTemplateHostVO templateHostRef = ApiDBUtils.findTemplateHostRef(templateId, zoneId, readyOnly);
        if (templateHostRef == null) {
            return responses;
        }

        HostVO host = ApiDBUtils.findHostById(templateHostRef.getHostId());
        if (host.getType() == Host.Type.LocalSecondaryStorage && host.getStatus() != com.cloud.host.Status.Up) {
            return responses;
        }

        TemplateResponse templateResponse = new TemplateResponse();
        templateResponse.setId(template.getId());
        templateResponse.setName(template.getName());
        templateResponse.setDisplayText(template.getDisplayText());
        templateResponse.setPublic(template.isPublicTemplate());
        templateResponse.setCreated(templateHostRef.getCreated());

        templateResponse.setReady(templateHostRef.getDownloadState() == Status.DOWNLOADED);
        templateResponse.setFeatured(template.isFeatured());
        templateResponse.setExtractable(template.isExtractable() && !(template.getTemplateType() == TemplateType.SYSTEM));
        templateResponse.setPasswordEnabled(template.getEnablePassword());
        templateResponse.setCrossZones(template.isCrossZones());
        templateResponse.setFormat(template.getFormat());
        if (template.getTemplateType() != null) {
            templateResponse.setTemplateType(template.getTemplateType().toString());
        }

        templateResponse.setHypervisor(template.getHypervisorType().toString());
        templateResponse.setDetails(template.getDetails());

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

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(template.getAccountId());
        populateAccount(templateResponse, account.getId());

        populateDomain(templateResponse, account.getDomainId());

        DataCenterVO datacenter = ApiDBUtils.findZoneById(zoneId);

        // Add the zone ID
        templateResponse.setZoneId(zoneId);
        templateResponse.setZoneName(datacenter.getName());

        boolean isAdmin = false;
        Account caller = UserContext.current().getCaller();
        if ((caller == null) || BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }

        // If the user is an Admin, add the template download status
        if (isAdmin || caller.getId() == template.getAccountId()) {
            // add download status
            if (templateHostRef.getDownloadState() != Status.DOWNLOADED) {
                String templateStatus = "Processing";
                if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) {
                    if (templateHostRef.getDownloadPercent() == 100) {
            isoResponse.setChecksum(iso.getChecksum());
                        templateStatus = "Installing Template";
                    } else {
                        templateStatus = templateHostRef.getDownloadPercent() + "% Downloaded";
                    }
                } else {
                    templateStatus = templateHostRef.getErrorString();
                }
                templateResponse.setStatus(templateStatus);
            } else if (templateHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) {
                templateResponse.setStatus("Download Complete");
            } else {
                templateResponse.setStatus("Successfully Installed");
            }
        }

        Long templateSize = templateHostRef.getSize();
        if (templateSize > 0) {
            templateResponse.setSize(templateSize);
        }

        templateResponse.setChecksum(template.getChecksum());
        templateResponse.setSourceTemplateId(template.getSourceTemplateId());

        templateResponse.setChecksum(template.getChecksum());

        templateResponse.setTemplateTag(template.getTemplateTag());
        
        //set tag information
        List tags = null;
        if (template.getFormat() == ImageFormat.ISO) {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, template.getId());
        } else {
            tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Template, template.getId());
        }
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        templateResponse.setTags(tagResponses);

        templateResponse.setObjectName("template");
        responses.add(templateResponse);
        return responses;
    }

    @Override
    public List createIsoResponses(long isoId, Long zoneId, boolean readyOnly) {

        List isoResponses = new ArrayList();
        VirtualMachineTemplate iso = findTemplateById(isoId);
        if (iso.getTemplateType() == TemplateType.PERHOST) {
            TemplateResponse isoResponse = new TemplateResponse();
            isoResponse.setId(iso.getId());
            isoResponse.setName(iso.getName());
            isoResponse.setDisplayText(iso.getDisplayText());
            isoResponse.setPublic(iso.isPublicTemplate());
            isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
            isoResponse.setReady(true);
            isoResponse.setBootable(iso.isBootable());
            isoResponse.setFeatured(iso.isFeatured());
            isoResponse.setCrossZones(iso.isCrossZones());
            isoResponse.setPublic(iso.isPublicTemplate());
            isoResponse.setCreated(iso.getCreated());
            isoResponse.setPasswordEnabled(false);
            isoResponse.setDetails(iso.getDetails());

            // add account ID and name
            Account owner = ApiDBUtils.findAccountById(iso.getAccountId());
            populateAccount(isoResponse, owner.getId());
            populateDomain(isoResponse, owner.getDomainId());
            
            //set tag information
            List tags =  ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId());
            List tagResponses = new ArrayList();
            for (ResourceTag tag : tags) {
                ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                tagResponses.add(tagResponse);
            }
            isoResponse.setTags(tagResponses);

            isoResponse.setObjectName("iso");
            isoResponses.add(isoResponse);
            return isoResponses;
        } else {
                }
            if (zoneId == null || zoneId == -1) {
                isoResponses = createSwiftIsoResponses(iso);
                if (!isoResponses.isEmpty()) {
                    return isoResponses;
                }
                List dcs = new ArrayList();
                dcs.addAll(ApiDBUtils.listZones());
                for (DataCenterVO dc : dcs) {
                    isoResponses.addAll(createIsoResponses(iso, dc.getId(), readyOnly));
                }
                return isoResponses;
            } else {
                return createIsoResponses(iso, zoneId, readyOnly);
            }
        }
    }

    private List createSwiftIsoResponses(VirtualMachineTemplate iso) {
        long isoId = iso.getId();
        List isoResponses = new ArrayList();
        VMTemplateSwiftVO isoSwift = ApiDBUtils.findTemplateSwiftRef(isoId);
        if (isoSwift == null) {
            return isoResponses;
        }
        TemplateResponse isoResponse = new TemplateResponse();
        isoResponse.setId(iso.getId());
        isoResponse.setName(iso.getName());
        isoResponse.setDisplayText(iso.getDisplayText());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
        isoResponse.setCreated(isoSwift.getCreated());
        isoResponse.setReady(true);
        isoResponse.setBootable(iso.isBootable());
        isoResponse.setFeatured(iso.isFeatured());
        isoResponse.setCrossZones(iso.isCrossZones());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setChecksum(iso.getChecksum());
        isoResponse.setDetails(iso.getDetails());

        // TODO: implement
        GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId());
        if (os != null) {
            isoResponse.setOsTypeId(os.getId());
            isoResponse.setOsTypeName(os.getDisplayName());
        } else {
            isoResponse.setOsTypeId(-1L);
            isoResponse.setOsTypeName("");
        }
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(iso.getAccountId());
        populateAccount(isoResponse, account.getId());
        populateDomain(isoResponse, account.getDomainId());
        boolean isAdmin = false;
        if ((account == null) || BaseCmd.isAdmin(account.getType())) {
            isAdmin = true;
        }

        // If the user is an admin, add the template download status
        if (isAdmin || account.getId() == iso.getAccountId()) {
            // add download status
            isoResponse.setStatus("Successfully Installed");
        }
        Long isoSize = isoSwift.getSize();
        if (isoSize > 0) {
            isoResponse.setSize(isoSize);
        }
        isoResponse.setObjectName("iso");
        isoResponses.add(isoResponse);
        return isoResponses;
    }

    @Override
    public List createIsoResponses(VirtualMachineTemplate iso, long zoneId, boolean readyOnly) {
        long isoId = iso.getId();
        List isoResponses = new ArrayList();
        VMTemplateHostVO isoHost = ApiDBUtils.findTemplateHostRef(isoId, zoneId, readyOnly);
        if (isoHost == null) {
            return isoResponses;
        }
        TemplateResponse isoResponse = new TemplateResponse();
        isoResponse.setId(iso.getId());
        isoResponse.setName(iso.getName());
        isoResponse.setDisplayText(iso.getDisplayText());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
        isoResponse.setCreated(isoHost.getCreated());
        isoResponse.setReady(isoHost.getDownloadState() == Status.DOWNLOADED);
        isoResponse.setBootable(iso.isBootable());

        isoResponse.setFeatured(iso.isFeatured());
        isoResponse.setCrossZones(iso.isCrossZones());
        isoResponse.setPublic(iso.isPublicTemplate());
        isoResponse.setChecksum(iso.getChecksum());
        isoResponse.setDetails(iso.getDetails());

        // TODO: implement
        GuestOS os = ApiDBUtils.findGuestOSById(iso.getGuestOSId());
        if (os != null) {
            isoResponse.setOsTypeId(os.getId());
            isoResponse.setOsTypeName(os.getDisplayName());
        } else {
            isoResponse.setOsTypeId(-1L);
            isoResponse.setOsTypeName("");
        }

        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(iso.getAccountId());
        populateAccount(isoResponse, account.getId());
        populateDomain(isoResponse, account.getDomainId());

        Account caller = UserContext.current().getCaller();
        boolean isAdmin = false;
        if ((caller == null) || BaseCmd.isAdmin(caller.getType())) {
            isAdmin = true;
        }
        // Add the zone ID
        DataCenterVO datacenter = ApiDBUtils.findZoneById(zoneId);
        isoResponse.setZoneId(zoneId);
        isoResponse.setZoneName(datacenter.getName());

        // If the user is an admin, add the template download status
        if (isAdmin || caller.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();
        if (isoSize > 0) {
            isoResponse.setSize(isoSize);
        }
        
        //set tag information
        List tags =  ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.ISO, iso.getId());
        
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        isoResponse.setTags(tagResponses);
        isoResponse.setObjectName("iso");
        isoResponses.add(isoResponse);
        return isoResponses;
    }

    @Override
    public ListResponse createSecurityGroupResponses(
            List networkGroups) {
        List groupResultObjs = SecurityGroupResultObject
                .transposeNetworkGroups(networkGroups);

        ListResponse response = new ListResponse();
        List netGrpResponses = new ArrayList();
        for (SecurityGroupResultObject networkGroup : groupResultObjs) {
            SecurityGroupResponse netGrpResponse = new SecurityGroupResponse();
            netGrpResponse.setId(networkGroup.getId());
            netGrpResponse.setName(networkGroup.getName());
            netGrpResponse.setDescription(networkGroup.getDescription());

            populateOwner(netGrpResponse, networkGroup);

            List securityGroupRules = networkGroup
                    .getSecurityGroupRules();
            if ((securityGroupRules != null) && !securityGroupRules.isEmpty()) {
                List ingressRulesResponse = new ArrayList();
                List egressRulesResponse = new ArrayList();
                for (SecurityGroupRuleResultObject securityGroupRule : securityGroupRules) {
                    SecurityGroupRuleResponse ruleData = new SecurityGroupRuleResponse();
                    ruleData.setRuleId(securityGroupRule.getId());
                    ruleData.setProtocol(securityGroupRule.getProtocol());

                    if ("icmp".equalsIgnoreCase(securityGroupRule.getProtocol())) {
                        ruleData.setIcmpType(securityGroupRule.getStartPort());
                        ruleData.setIcmpCode(securityGroupRule.getEndPort());
                    } else {
                        ruleData.setStartPort(securityGroupRule.getStartPort());
                        ruleData.setEndPort(securityGroupRule.getEndPort());
                    }

                    if (securityGroupRule.getAllowedSecurityGroup() != null) {
                        ruleData.setSecurityGroupName(securityGroupRule
                                .getAllowedSecurityGroup());
                        ruleData.setAccountName(securityGroupRule
                                .getAllowedSecGroupAcct());
                    } else {
                        ruleData.setCidr(securityGroupRule
                                .getAllowedSourceIpCidr());
                    }

                    if (securityGroupRule.getRuleType() == SecurityRuleType.IngressRule) {
                        ruleData.setObjectName("ingressrule");
                        ingressRulesResponse.add(ruleData);
                    } else {
                        ruleData.setObjectName("egressrule");
                        egressRulesResponse.add(ruleData);
                    }
                }
                //set tag information
                List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, networkGroup.getId());
                List tagResponses = new ArrayList();
                for (ResourceTag tag : tags) {
                    ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
                    tagResponses.add(tagResponse);
                }
                netGrpResponse.setTags(tagResponses);
                
                netGrpResponse
                        .setSecurityGroupIngressRules(ingressRulesResponse);
                netGrpResponse.setSecurityGroupEgressRules(egressRulesResponse);
            }
            netGrpResponse.setObjectName("securitygroup");
            netGrpResponses.add(netGrpResponse);
        }
        
        response.setResponses(netGrpResponses);
        return response;
    }

    @Override
    public SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group) {
        SecurityGroupResponse response = new SecurityGroupResponse();
        populateOwner(response, group);

        response.setDescription(group.getDescription());
        response.setId(group.getId());
        response.setName(group.getName());

        response.setObjectName("securitygroup");
        return response;

    }

    @Override
    public ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode) {
        UploadVO uploadInfo = ApiDBUtils.findUploadById(uploadId);
        ExtractResponse response = new ExtractResponse();
        response.setObjectName("template");
        response.setId(id);
        response.setName(ApiDBUtils.findTemplateById(id).getName());
        if (zoneId != null) {
            response.setZoneId(zoneId);
            response.setZoneName(ApiDBUtils.findZoneById(zoneId).getName());
        }
        response.setMode(mode);
        response.setUploadId(uploadId);
        response.setState(uploadInfo.getUploadState().toString());
        response.setAccountId(accountId);
        response.setUrl(uploadInfo.getUploadUrl());
        return response;

    }

    @Override
    public String toSerializedString(CreateCmdResponse response, String responseType) {
        return ApiResponseSerializer.toSerializedString(response, responseType);
    }

    @Override
    public AsyncJobResponse createAsyncJobResponse(AsyncJob job) {
        AsyncJobResponse jobResponse = new AsyncJobResponse();
        jobResponse.setAccountId(job.getAccountId());
        jobResponse.setUserId(job.getUserId());
        jobResponse.setCmd(job.getCmd());
        jobResponse.setCreated(job.getCreated());
        jobResponse.setJobId(job.getId());
        jobResponse.setJobStatus(job.getStatus());
        jobResponse.setJobProcStatus(job.getProcessStatus());

        if (job.getInstanceType() != null && job.getInstanceId() != null) {
            jobResponse.setJobInstanceType(job.getInstanceType().toString());
            jobResponse.setJobInstanceId(job.getInstanceId());
        }
        jobResponse.setJobResultCode(job.getResultCode());

        boolean savedValue = SerializationContext.current().getUuidTranslation();
        SerializationContext.current().setUuidTranslation(false);
        
        Object resultObject = ApiSerializerHelper.fromSerializedString(job.getResult());
        jobResponse.setJobResult((ResponseObject) resultObject);
        SerializationContext.current().setUuidTranslation(savedValue);
        
        if (resultObject != null) {
            Class clz = resultObject.getClass();
            if (clz.isPrimitive() || clz.getSuperclass() == Number.class || clz == String.class || clz == Date.class) {
                jobResponse.setJobResultType("text");
            } else {
                jobResponse.setJobResultType("object");
            }
        }

        jobResponse.setObjectName("asyncjobs");
        return jobResponse;
    }

    @Override
    public List createTemplateResponses(long templateId, Long snapshotId, Long volumeId, boolean readyOnly) {
        VolumeVO volume = null;
        if (snapshotId != null) {
            Snapshot snapshot = ApiDBUtils.findSnapshotById(snapshotId);
            volume = findVolumeById(snapshot.getVolumeId());
        } else {
            volume = findVolumeById(volumeId);
        }
        return createTemplateResponses(templateId, volume.getDataCenterId(), readyOnly);
    }

    @Override
    public List createTemplateResponses(long templateId, Long vmId) {
        UserVm vm = findUserVmById(vmId);
        Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
        Host host = findHostById(hostId);
        return createTemplateResponses(templateId, host.getDataCenterId(), true);
    }

    @Override
    public EventResponse createEventResponse(Event event) {
        EventResponse responseEvent = new EventResponse();
        responseEvent.setCreated(event.getCreateDate());
        responseEvent.setDescription(event.getDescription());
        responseEvent.setEventType(event.getType());
        responseEvent.setId(event.getId());
        responseEvent.setLevel(event.getLevel());
        responseEvent.setParentId(event.getStartId());
        responseEvent.setState(event.getState());

        populateOwner(responseEvent, event);

        User user = ApiDBUtils.findUserById(event.getUserId());
        if (user != null) {
            responseEvent.setUsername(user.getUsername());
        }

        responseEvent.setObjectName("event");
        return responseEvent;
    }

    private List sumCapacities(List hostCapacities) {
        Map totalCapacityMap = new HashMap();
        Map usedCapacityMap = new HashMap();

        Set poolIdsToIgnore = new HashSet();
        Criteria c = new Criteria();
        // TODO: implement
        List allStoragePools = ApiDBUtils.searchForStoragePools(c);
        for (StoragePoolVO pool : allStoragePools) {
            StoragePoolType poolType = pool.getPoolType();
            if (!(poolType.isShared())) {// All the non shared storages shouldn't show up in the capacity calculation
                poolIdsToIgnore.add(pool.getId());
            }
        }

        float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor();

        // collect all the capacity types, sum allocated/used and sum total...get one capacity number for each
        for (Capacity capacity : hostCapacities) {

            // check if zone exist
            DataCenter zone = ApiDBUtils.findZoneById(capacity.getDataCenterId());
            if (zone == null) {
                continue;
            }

            short capacityType = capacity.getCapacityType();

            // If local storage then ignore
            if ((capacityType == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED || capacityType == Capacity.CAPACITY_TYPE_STORAGE)
                    && poolIdsToIgnore.contains(capacity.getHostOrPoolId())) {
                continue;
            }

            String key = capacity.getCapacityType() + "_" + capacity.getDataCenterId();
            String keyForPodTotal = key + "_-1";

            boolean sumPodCapacity = false;
            if (capacity.getPodId() != null) {
                key += "_" + capacity.getPodId();
                sumPodCapacity = true;
            }

            Long totalCapacity = totalCapacityMap.get(key);
            Long usedCapacity = usedCapacityMap.get(key);

            // reset overprovisioning factor to 1
            float overprovisioningFactor = 1;
            if (capacityType == Capacity.CAPACITY_TYPE_CPU) {
                overprovisioningFactor = cpuOverprovisioningFactor;
            }

            if (totalCapacity == null) {
                totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor));
            } else {
                totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity;
            }

            if (usedCapacity == null) {
                usedCapacity = new Long(capacity.getUsedCapacity());
            } else {
                usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity);
            }

            if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved
            if (summedCapacity.getPodId() != null) {
                                                                                                               // Capacity
                                                                                                               // accounts
// for
                // stopped
// vms
                // that
// have been
                // stopped
// within
                // an
// interval
                usedCapacity += capacity.getReservedCapacity();
            }

            totalCapacityMap.put(key, totalCapacity);
            usedCapacityMap.put(key, usedCapacity);

            if (sumPodCapacity) {
                totalCapacity = totalCapacityMap.get(keyForPodTotal);
                usedCapacity = usedCapacityMap.get(keyForPodTotal);

                overprovisioningFactor = 1;
                if (capacityType == Capacity.CAPACITY_TYPE_CPU) {
                    overprovisioningFactor = cpuOverprovisioningFactor;
                if (totalCapacity == null) {
                    totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor));
                } else {
                    totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity;
                }

                if (usedCapacity == null) {
                    usedCapacity = new Long(capacity.getUsedCapacity());
                } else {
                    usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity);
                }

                if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved
                                                                                                                   // Capacity
                                                                                                                   // accounts
                                                                                                                   // for
                                                                                                                   // stopped
                                                                                                                   // vms
// that
                    // have
// been
                    // stopped
                    // within
// an
                    // interval
                    usedCapacity += capacity.getReservedCapacity();
                }

                totalCapacityMap.put(keyForPodTotal, totalCapacity);
                usedCapacityMap.put(keyForPodTotal, usedCapacity);
            }
        }

        List summedCapacities = new ArrayList();
        for (String key : totalCapacityMap.keySet()) {
            CapacityVO summedCapacity = new CapacityVO();

            StringTokenizer st = new StringTokenizer(key, "_");
            summedCapacity.setCapacityType(Short.parseShort(st.nextToken()));
            summedCapacity.setDataCenterId(Long.parseLong(st.nextToken()));
            if (st.hasMoreTokens()) {
                summedCapacity.setPodId(Long.parseLong(st.nextToken()));
            }

            summedCapacity.setTotalCapacity(totalCapacityMap.get(key));
            summedCapacity.setUsedCapacity(usedCapacityMap.get(key));

            summedCapacities.add(summedCapacity);
        }
        return summedCapacities;
    }

    @Override
    public List createCapacityResponse(List result, DecimalFormat format) {
        List capacityResponses = new ArrayList();
        
        for (Capacity summedCapacity : result) {
            CapacityResponse capacityResponse = new CapacityResponse();
            capacityResponse.setCapacityTotal(summedCapacity.getTotalCapacity());
            capacityResponse.setCapacityType(summedCapacity.getCapacityType());
            capacityResponse.setCapacityUsed(summedCapacity.getUsedCapacity());
                capacityResponse.setPodId(summedCapacity.getPodId());
                HostPodVO pod = ApiDBUtils.findPodById(summedCapacity.getPodId());
                if (pod != null) {
                    capacityResponse.setPodName(pod.getName());
                }
            }
            if (summedCapacity.getClusterId() != null) {
                capacityResponse.setClusterId(summedCapacity.getClusterId());
                ClusterVO cluster = ApiDBUtils.findClusterById(summedCapacity.getClusterId());
                if (cluster != null) {
                    capacityResponse.setClusterName(cluster.getName());
                    if (summedCapacity.getPodId() == null) {
                        long podId = cluster.getPodId();
                        capacityResponse.setPodId(podId);
                        capacityResponse.setPodName(ApiDBUtils.findPodById(podId).getName());
                    }
                }
            }
            capacityResponse.setZoneId(summedCapacity.getDataCenterId());
            capacityResponse.setZoneName(ApiDBUtils.findZoneById(summedCapacity.getDataCenterId()).getName());
            if (summedCapacity.getUsedPercentage() != null){
                capacityResponse.setPercentUsed(format.format(summedCapacity.getUsedPercentage() * 100f));
            } else if (summedCapacity.getTotalCapacity() != 0) {
                capacityResponse.setPercentUsed(format.format((float) summedCapacity.getUsedCapacity() / (float) summedCapacity.getTotalCapacity() * 100f));
            } else {
                capacityResponse.setPercentUsed(format.format(0L));
            }

            capacityResponse.setObjectName("capacity");
            capacityResponses.add(capacityResponse);
        }

        return capacityResponses;
    }

    @Override
    public TemplatePermissionsResponse createTemplatePermissionsResponse(List accountNames, Long id, boolean isAdmin) {
        Long templateOwnerDomain = null;
        VirtualMachineTemplate template = ApiDBUtils.findTemplateById(id);
        Account templateOwner = ApiDBUtils.findAccountById(template.getAccountId());
        if (isAdmin) {
            // FIXME: we have just template id and need to get template owner from that
            if (templateOwner != null) {
                templateOwnerDomain = templateOwner.getDomainId();
            }
        }

        TemplatePermissionsResponse response = new TemplatePermissionsResponse();
        response.setId(template.getId());
        response.setPublicTemplate(template.isPublicTemplate());
        if (isAdmin && (templateOwnerDomain != null)) {
            response.setDomainId(templateOwnerDomain);
        }

        // Set accounts
        List projectIds = new ArrayList();
        List regularAccounts = new ArrayList();
        for (String accountName : accountNames) {
            Account account = ApiDBUtils.findAccountByNameDomain(accountName, templateOwner.getDomainId());
            if (account.getType() != Account.ACCOUNT_TYPE_PROJECT) {
                regularAccounts.add(accountName);
            } else {
                // convert account to projectIds
                Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());

                if (project.getUuid() != null && !project.getUuid().isEmpty())
                    projectIds.add(project.getUuid());
                else
                    projectIds.add(String.valueOf(project.getId()));
            }
        }

        if (!projectIds.isEmpty()) {
            response.setProjectIds(projectIds);
        }

        if (!regularAccounts.isEmpty()) {
            response.setAccountNames(regularAccounts);
        }

        response.setObjectName("templatepermission");
        return response;
    }

    @Override
    public AsyncJobResponse queryJobResult(QueryAsyncJobResultCmd cmd) {
        AsyncJob result = ApiDBUtils._asyncMgr.queryAsyncJobResult(cmd);
        return createAsyncJobResponse(result);
    }

    @Override
    public SecurityGroupResponse createSecurityGroupResponseFromSecurityGroupRule(List securityRules) {
        SecurityGroupResponse response = new SecurityGroupResponse();
        Map securiytGroupAccounts = new HashMap();
        Map allowedSecurityGroups = new HashMap();
        Map allowedSecuriytGroupAccounts = new HashMap();

        if ((securityRules != null) && !securityRules.isEmpty()) {
            SecurityGroup securityGroup = ApiDBUtils.findSecurityGroupById(securityRules.get(0).getSecurityGroupId());
            response.setId(securityGroup.getId());
            response.setName(securityGroup.getName());
            response.setDescription(securityGroup.getDescription());

            Account account = securiytGroupAccounts.get(securityGroup.getAccountId());

            if (account == null) {
                account = ApiDBUtils.findAccountById(securityGroup.getAccountId());
                securiytGroupAccounts.put(securityGroup.getAccountId(), account);
            }

            populateAccount(response, account.getId());
            populateDomain(response, account.getDomainId());

            List egressResponses = new ArrayList();
            List ingressResponses = new ArrayList();
            for (SecurityRule securityRule : securityRules) {
                SecurityGroupRuleResponse securityGroupData = new SecurityGroupRuleResponse();

                securityGroupData.setRuleId(securityRule.getId());
                securityGroupData.setProtocol(securityRule.getProtocol());
                if ("icmp".equalsIgnoreCase(securityRule.getProtocol())) {
                    securityGroupData.setIcmpType(securityRule.getStartPort());
                    securityGroupData.setIcmpCode(securityRule.getEndPort());
                } else {
                    securityGroupData.setStartPort(securityRule.getStartPort());
                    securityGroupData.setEndPort(securityRule.getEndPort());
                }

                Long allowedSecurityGroupId = securityRule.getAllowedNetworkId();
                if (allowedSecurityGroupId != null) {
                    SecurityGroup allowedSecurityGroup = allowedSecurityGroups.get(allowedSecurityGroupId);
                    if (allowedSecurityGroup == null) {
                        allowedSecurityGroup = ApiDBUtils.findSecurityGroupById(allowedSecurityGroupId);
                        allowedSecurityGroups.put(allowedSecurityGroupId, allowedSecurityGroup);
                    }

                    securityGroupData.setSecurityGroupName(allowedSecurityGroup.getName());

                    Account allowedAccount = allowedSecuriytGroupAccounts.get(allowedSecurityGroup.getAccountId());
                    if (allowedAccount == null) {
                        allowedAccount = ApiDBUtils.findAccountById(allowedSecurityGroup.getAccountId());
                        allowedSecuriytGroupAccounts.put(allowedAccount.getId(), allowedAccount);
                    }

                    securityGroupData.setAccountName(allowedAccount.getAccountName());
                } else {
                    securityGroupData.setCidr(securityRule.getAllowedSourceIpCidr());
                }
                if (securityRule.getRuleType() == SecurityRuleType.IngressRule) {
                    securityGroupData.setObjectName("ingressrule");
                    ingressResponses.add(securityGroupData);
                } else {
                    securityGroupData.setObjectName("egressrule");
                    egressResponses.add(securityGroupData);
                }

            }
            response.setSecurityGroupIngressRules(ingressResponses);
            response.setSecurityGroupEgressRules(egressResponses);
            response.setObjectName("securitygroup");

        }
        return response;
    }

    @Override

    public NetworkOfferingResponse createNetworkOfferingResponse(NetworkOffering offering) {
        NetworkOfferingResponse response = new NetworkOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setTags(offering.getTags());
        response.setTrafficType(offering.getTrafficType().toString());
        response.setIsDefault(offering.isDefault());
        response.setSpecifyVlan(offering.getSpecifyVlan());
        response.setConserveMode(offering.isConserveMode());
        response.setSpecifyIpRanges(offering.getSpecifyIpRanges());
        response.setAvailability(offering.getAvailability().toString());
        response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId()));
        if (offering.getServiceOfferingId() != null) {
            response.setServiceOfferingId(offering.getServiceOfferingId());
        } else {
            response.setServiceOfferingId(ApiDBUtils.findDefaultRouterServiceOffering());
        }
        if (offering.getGuestType() != null) {
            populateOwner(response, network);
            response.setGuestIpType(offering.getGuestType().toString());
        }

        response.setState(offering.getState().name());

        Map> serviceProviderMap = ApiDBUtils.listNetworkOfferingServices(offering.getId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            if (Service.Lb == service) {
                List lbCapResponse = new ArrayList();

                CapabilityResponse lbIsoaltion = new CapabilityResponse();
                lbIsoaltion.setName(Capability.SupportedLBIsolation.getName());
                lbIsoaltion.setValue(offering.getDedicatedLB() ? "dedicated" : "shared");
                lbCapResponse.add(lbIsoaltion);

                CapabilityResponse eLb = new CapabilityResponse();
                eLb.setName(Capability.ElasticLb.getName());
                eLb.setValue(offering.getElasticLb() ? "true" : "false");
                lbCapResponse.add(eLb);

                svcRsp.setCapabilities(lbCapResponse);
            } else if (Service.SourceNat == service) {
                List capabilities = new ArrayList();
                CapabilityResponse sharedSourceNat = new CapabilityResponse();
                sharedSourceNat.setName(Capability.SupportedSourceNatTypes.getName());
                sharedSourceNat.setValue(offering.getSharedSourceNat() ? "perzone" : "peraccount");
                capabilities.add(sharedSourceNat);

                CapabilityResponse redundantRouter = new CapabilityResponse();
                redundantRouter.setName(Capability.RedundantRouter.getName());
                redundantRouter.setValue(offering.getRedundantRouter() ? "true" : "false");
                capabilities.add(redundantRouter);

                svcRsp.setCapabilities(capabilities);
            } else if (service == Service.StaticNat) {
                List staticNatCapResponse = new ArrayList();

                CapabilityResponse eIp = new CapabilityResponse();
                eIp.setName(Capability.ElasticIp.getName());
                eIp.setValue(offering.getElasticLb() ? "true" : "false");
                staticNatCapResponse.add(eIp);

                svcRsp.setCapabilities(staticNatCapResponse);
            }
            serviceResponses.add(svcRsp);
        }
        response.setForVpc(ApiDBUtils.isOfferingForVpc(offering));
        
        response.setServices(serviceResponses);
        response.setObjectName("networkoffering");
        return response;
    }

    @Override
    public NetworkResponse createNetworkResponse(Network network) {
        // need to get network profile in order to retrieve dns information from there
        NetworkProfile profile = ApiDBUtils.getNetworkProfile(network.getId());
        NetworkResponse response = new NetworkResponse();
        response.setId(network.getId());
        response.setName(network.getName());
        response.setDisplaytext(network.getDisplayText());
        if (network.getBroadcastDomainType() != null) {
            response.setBroadcastDomainType(network.getBroadcastDomainType().toString());
        }

        if (network.getTrafficType() != null) {
        } else {
            response.setTrafficType(network.getTrafficType().name());
        }

        if (network.getGuestType() != null) {
            response.setType(network.getGuestType().toString());
        }

        response.setGateway(network.getGateway());

        // FIXME - either set netmask or cidr
        response.setCidr(network.getCidr());
        if (network.getCidr() != null) {
            response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
        }

        if (network.getBroadcastUri() != null) {
            String broadcastUri = network.getBroadcastUri().toString();
            response.setBroadcastUri(broadcastUri);
            String vlan="N/A";
            if (broadcastUri.startsWith("vlan")) {
                vlan = broadcastUri.substring("vlan://".length(), broadcastUri.length());
            }
            response.setVlan(vlan);
        }

        DataCenter zone = ApiDBUtils.findZoneById(network.getDataCenterId());
        response.setZoneId(network.getDataCenterId());
        response.setZoneName(zone.getName());
        response.setPhysicalNetworkId(network.getPhysicalNetworkId());

        // populate network offering information
        NetworkOffering networkOffering = ApiDBUtils.findNetworkOfferingById(network.getNetworkOfferingId());
        if (networkOffering != null) {
            response.setNetworkOfferingId(networkOffering.getId());
            response.setNetworkOfferingName(networkOffering.getName());
            response.setNetworkOfferingDisplayText(networkOffering.getDisplayText());
            response.setIsSystem(networkOffering.isSystemOnly());
            response.setNetworkOfferingAvailability(networkOffering.getAvailability().toString());
        }

        if (network.getAclType() != null) {
            response.setAclType(network.getAclType().toString());
        }
        response.setState(network.getState().toString());
        response.setRestartRequired(network.isRestartRequired());
        response.setRelated(network.getRelated());
        response.setNetworkDomain(network.getNetworkDomain());

        response.setDns1(profile.getDns1());
        response.setDns2(profile.getDns2());
        // populate capability
        Map> serviceCapabilitiesMap = ApiDBUtils.getNetworkCapabilities(network.getId(), network.getDataCenterId());
        List serviceResponses = new ArrayList();
        if (serviceCapabilitiesMap != null) {
            for (Service service : serviceCapabilitiesMap.keySet()) {
                ServiceResponse serviceResponse = new ServiceResponse();
                // skip gateway service
                if (service == Service.Gateway) {
                    continue;
                }
                serviceResponse.setName(service.getName());

                // set list of capabilities for the service

    @Override
                List capabilityResponses = new ArrayList();
                Map serviceCapabilities = serviceCapabilitiesMap.get(service);
                if (serviceCapabilities != null) {
                    for (Capability capability : serviceCapabilities.keySet()) {
                        CapabilityResponse capabilityResponse = new CapabilityResponse();
                        String capabilityValue = serviceCapabilities.get(capability);
                        capabilityResponse.setName(capability.getName());
                        capabilityResponse.setValue(capabilityValue);
                        capabilityResponse.setObjectName("capability");
                        capabilityResponses.add(capabilityResponse);
                    }
                    serviceResponse.setCapabilities(capabilityResponses);
                }

                serviceResponse.setObjectName("service");
                serviceResponses.add(serviceResponse);
            }
        }
        response.setServices(serviceResponses);

        if (network.getAclType() == null || network.getAclType() == ACLType.Account) {
            // get domain from network_domain table
            Pair domainNetworkDetails = ApiDBUtils.getDomainNetworkDetails(network.getId());
            response.setDomainId(domainNetworkDetails.first());
            response.setSubdomainAccess(domainNetworkDetails.second());
        }

        Long dedicatedDomainId = ApiDBUtils.getDedicatedNetworkDomain(network.getId());
        if (dedicatedDomainId != null) {
            Domain domain = ApiDBUtils.findDomainById(dedicatedDomainId);
            response.setDomainId(dedicatedDomainId);
            response.setDomainName(domain.getName());
        }

        response.setSpecifyIpRanges(network.getSpecifyIpRanges());
        response.setCanUseForDeploy(ApiDBUtils.canUseForDeploy(network));
        response.setVpcId(network.getVpcId());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Network, network.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("network");
        return response;
    }

    @Override
    public Long getSecurityGroupId(String groupName, long accountId) {
        SecurityGroup sg = ApiDBUtils.getSecurityGroup(groupName, accountId);
        if (sg == null) {
            return null;
        } else {
            return sg.getId();
        }
    }

    @Override
    public ProjectResponse createProjectResponse(Project project) {
        ProjectResponse response = new ProjectResponse();
        response.setId(project.getId());
        response.setName(project.getName());
        response.setDisplaytext(project.getDisplayText());
        response.setState(project.getState().toString());

        Domain domain = ApiDBUtils.findDomainById(project.getDomainId());
        response.setDomainId(domain.getId());
        response.setDomain(domain.getName());

        response.setOwner(ApiDBUtils.getProjectOwner(project.getId()).getAccountName());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Project, project.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setObjectName("project");
        return response;
    }
    public FirewallResponse createFirewallResponse(FirewallRule fwRule) {
        FirewallResponse response = new FirewallResponse();

        response.setId(fwRule.getId());
        response.setProtocol(fwRule.getProtocol());
        if (fwRule.getSourcePortStart() != null) {
            response.setStartPort(Integer.toString(fwRule.getSourcePortStart()));
        }

        if (fwRule.getSourcePortEnd() != null) {
            response.setEndPort(Integer.toString(fwRule.getSourcePortEnd()));
        }

        List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
        response.setPublicIpAddressId(ip.getId());
        response.setPublicIpAddress(ip.getAddress().addr());

        FirewallRule.State state = fwRule.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setIcmpCode(fwRule.getIcmpCode());
        response.setIcmpType(fwRule.getIcmpType());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.FirewallRule, fwRule.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);

        response.setState(stateToSet);
        response.setObjectName("firewallrule");
        return response;
    }
    
    @Override
    public NetworkACLResponse createNetworkACLResponse(FirewallRule networkACL) {
        NetworkACLResponse response = new NetworkACLResponse();

        response.setId(networkACL.getId());
        response.setProtocol(networkACL.getProtocol());
        if (networkACL.getSourcePortStart() != null) {
            response.setStartPort(Integer.toString(networkACL.getSourcePortStart()));
        }

        if (networkACL.getSourcePortEnd() != null) {
            response.setEndPort(Integer.toString(networkACL.getSourcePortEnd()));
        }

        List cidrs = ApiDBUtils.findFirewallSourceCidrs(networkACL.getId());
        response.setCidrList(StringUtils.join(cidrs, ","));

        response.setTrafficType(networkACL.getTrafficType().toString());

        FirewallRule.State state = networkACL.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }

        response.setIcmpCode(networkACL.getIcmpCode());
        response.setIcmpType(networkACL.getIcmpType());

        response.setState(stateToSet);
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.NetworkACL, networkACL.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        
        response.setObjectName("networkacl");
        return response;
    }

    public UserVmData newUserVmData(UserVm userVm) {
        UserVmData userVmData = new UserVmData();
        userVmData.setId(userVm.getId());
        userVmData.setName(userVm.getHostName());
        userVmData.setCreated(userVm.getCreated());
        userVmData.setGuestOsId(userVm.getGuestOSId());
        userVmData.setHaEnable(userVm.isHaEnabled());
        if (userVm.getState() != null) {
            userVmData.setState(userVm.getState().toString());
        }
        if (userVm.getDisplayName() != null) {
            userVmData.setDisplayName(userVm.getDisplayName());
        } else {
            userVmData.setDisplayName(userVm.getHostName());
        }
        userVmData.setInstanceName(userVm.getInstanceName());
        
        userVmData.setDomainId(userVm.getDomainId());

        if (userVm.getHypervisorType() != null) {
            userVmData.setHypervisor(userVm.getHypervisorType().toString());
        }

        if (userVm.getPassword() != null) {
            userVmData.setPassword(userVm.getPassword());
        }
        return userVmData;
    }

    public UserVmResponse newUserVmResponse(UserVmData userVmData, boolean caller_is_admin) {
        UserVmResponse userVmResponse = new UserVmResponse();

        userVmResponse.setHypervisor(userVmData.getHypervisor());
        userVmResponse.setId(userVmData.getId());
        userVmResponse.setName(userVmData.getName());

        userVmResponse.setDisplayName(userVmData.getDisplayName());

        populateAccount(userVmResponse, userVmData.getAccountId());
        populateDomain(userVmResponse, userVmData.getDomainId());

        userVmResponse.setCreated(userVmData.getCreated());
        userVmResponse.setState(userVmData.getState());
        userVmResponse.setHaEnable(userVmData.getHaEnable());
        userVmResponse.setGroupId(userVmData.getGroupId());
        userVmResponse.setGroup(userVmData.getGroup());
        userVmResponse.setZoneId(userVmData.getZoneId());
        userVmResponse.setZoneName(userVmData.getZoneName());
        if (caller_is_admin) {
            userVmResponse.setInstanceName(userVmData.getInstanceName());
            userVmResponse.setHostId(userVmData.getHostId());
            userVmResponse.setHostName(userVmData.getHostName());
        }
        userVmResponse.setTemplateId(userVmData.getTemplateId());
        userVmResponse.setTemplateName(userVmData.getTemplateName());
        userVmResponse.setTemplateDisplayText(userVmData.getTemplateDisplayText());
        userVmResponse.setPasswordEnabled(userVmData.getPasswordEnabled());
        userVmResponse.setIsoId(userVmData.getIsoId());
        userVmResponse.setIsoName(userVmData.getIsoName());
        userVmResponse.setIsoDisplayText(userVmData.getIsoDisplayText());
        userVmResponse.setServiceOfferingId(userVmData.getServiceOfferingId());
        userVmResponse.setServiceOfferingName(userVmData.getServiceOfferingName());
        userVmResponse.setCpuNumber(userVmData.getCpuNumber());
        userVmResponse.setCpuSpeed(userVmData.getCpuSpeed());
        userVmResponse.setMemory(userVmData.getMemory());
        userVmResponse.setCpuUsed(userVmData.getCpuUsed());
        userVmResponse.setNetworkKbsRead(userVmData.getNetworkKbsRead());
        userVmResponse.setNetworkKbsWrite(userVmData.getNetworkKbsWrite());
        userVmResponse.setGuestOsId(userVmData.getGuestOsId());
        userVmResponse.setRootDeviceId(userVmData.getRootDeviceId());
        userVmResponse.setRootDeviceType(userVmData.getRootDeviceType());
        userVmResponse.setPassword(userVmData.getPassword());
        userVmResponse.setJobId(userVmData.getJobId());
        userVmResponse.setJobStatus(userVmData.getJobStatus());
        userVmResponse.setForVirtualNetwork(userVmData.getForVirtualNetwork());

        Set securityGroupResponse = new HashSet();
        for (SecurityGroupData sgd : userVmData.getSecurityGroupList()) {
            if (sgd.getId() != null) {
                SecurityGroupResponse sgr = new SecurityGroupResponse();
                sgr.setId(sgd.getId());
                sgr.setName(sgd.getName());
                sgr.setDescription(sgd.getDescription());

                Account account = ApiDBUtils.findAccountByNameDomain(sgd.getAccountName(), sgd.getDomainId());
                if (account != null) {
                    populateAccount(sgr, account.getId());
                    populateDomain(sgr, account.getDomainId());
                }

                sgr.setObjectName(sgd.getObjectName());
                securityGroupResponse.add(sgr);
            }
        }
        userVmResponse.setSecurityGroupList(new ArrayList(securityGroupResponse));

        Set nicResponses = new HashSet();
        for (NicData nd : userVmData.getNics()) {
            NicResponse nr = new NicResponse();
            nr.setId(nd.getId());
            nr.setNetworkid(nd.getNetworkid());
            nr.setNetmask(nd.getNetmask());
            nr.setGateway(nd.getGateway());
            nr.setIpaddress(nd.getIpaddress());
            nr.setIsolationUri(nd.getIsolationUri());
            nr.setBroadcastUri(nd.getBroadcastUri());
            nr.setTrafficType(nd.getTrafficType());
            nr.setType(nd.getType());
            nr.setIsDefault(nd.getIsDefault());

            nr.setMacAddress(nd.getMacAddress());
            nr.setObjectName(nd.getObjectName());
            nicResponses.add(nr);
        }
        userVmResponse.setNics(new ArrayList(nicResponses));
        userVmResponse.setPublicIpId(userVmData.getPublicIpId());
        userVmResponse.setPublicIp(userVmData.getPublicIp());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.UserVm, userVmData.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        userVmResponse.setTags(tagResponses);

        return userVmResponse;
    }

    @Override
    public HypervisorCapabilitiesResponse createHypervisorCapabilitiesResponse(HypervisorCapabilities hpvCapabilities) {
        HypervisorCapabilitiesResponse hpvCapabilitiesResponse = new HypervisorCapabilitiesResponse();
        hpvCapabilitiesResponse.setId(hpvCapabilities.getId());
        hpvCapabilitiesResponse.setHypervisor(hpvCapabilities.getHypervisorType());
        hpvCapabilitiesResponse.setHypervisorVersion(hpvCapabilities.getHypervisorVersion());
        hpvCapabilitiesResponse.setIsSecurityGroupEnabled(hpvCapabilities.isSecurityGroupEnabled());
        hpvCapabilitiesResponse.setMaxGuestsLimit(hpvCapabilities.getMaxGuestsLimit());
        return hpvCapabilitiesResponse;
    }

    private void populateOwner(ControlledEntityResponse response, ControlledEntity object) {
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(object.getAccountId());

        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
            // find the project
            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
            response.setProjectId(project.getId());
            response.setProjectName(project.getName());
        } else {
            response.setAccountName(account.getAccountName());
        }

        Domain domain = ApiDBUtils.findDomainById(object.getDomainId());
        response.setDomainId(domain.getId());
        response.setDomainName(domain.getName());
    }

    private void populateAccount(ControlledEntityResponse response, long accountId) {
        Account account = ApiDBUtils.findAccountByIdIncludingRemoved(accountId);
        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
            // find the project
            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
            response.setProjectId(project.getId());
            response.setProjectName(project.getName());
        } else {
            response.setAccountName(account.getAccountName());
        }
    }

    private void populateDomain(ControlledEntityResponse response, long domainId) {
        Domain domain = ApiDBUtils.findDomainById(domainId);

        response.setDomainId(domain.getId());
        response.setDomainName(domain.getName());
    }

    @Override
    public ProjectAccountResponse createProjectAccountResponse(ProjectAccount projectAccount) {
        Account account = ApiDBUtils.findAccountById(projectAccount.getAccountId());
        ProjectAccountResponse projectAccountResponse = new ProjectAccountResponse();

        long projectId = projectAccount.getProjectId();
        projectAccountResponse.setProjectId(projectId);
        projectAccountResponse.setProjectName(ApiDBUtils.findProjectById(projectId).getName());

        projectAccountResponse.setId(account.getId());
        projectAccountResponse.setAccountName(account.getAccountName());
        projectAccountResponse.setAccountType(account.getType());
        projectAccountResponse.setRole(projectAccount.getAccountRole().toString());
        populateDomain(projectAccountResponse, account.getDomainId());

        // add all the users for an account as part of the response obj
        List usersForAccount = ApiDBUtils.listUsersByAccount(account.getAccountId());
        List userResponseList = new ArrayList();
        for (UserVO user : usersForAccount) {
            UserResponse userResponse = createUserResponse(user);
            userResponseList.add(userResponse);
        }

        projectAccountResponse.setUsers(userResponseList);
        projectAccountResponse.setObjectName("projectaccount");

        return projectAccountResponse;
    }

    @Override
    public ProjectInvitationResponse createProjectInvitationResponse(ProjectInvitation invite) {
        ProjectInvitationResponse response = new ProjectInvitationResponse();
        response.setId(invite.getId());
        response.setProjectId(invite.getProjectId());
        response.setProjectName(ApiDBUtils.findProjectById(invite.getProjectId()).getName());
        response.setInvitationState(invite.getState().toString());

        if (invite.getForAccountId() != null) {
            Account account = ApiDBUtils.findAccountById(invite.getForAccountId());
            response.setAccountName(account.getAccountName());

        } else {
            response.setEmail(invite.getEmail());
        }

        populateDomain(response, invite.getInDomainId());

        response.setObjectName("projectinvitation");
        return response;
    }

    @Override
    public SystemVmInstanceResponse createSystemVmInstanceResponse(VirtualMachine vm) {
        SystemVmInstanceResponse vmResponse = new SystemVmInstanceResponse();
        vmResponse.setId(vm.getId());
        vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
        vmResponse.setName(vm.getHostName());
        if (vm.getHostId() != null) {
            vmResponse.setHostId(vm.getHostId());
        }
        if (vm.getState() != null) {
            vmResponse.setState(vm.getState().toString());
        }
        if (vm.getType() == Type.DomainRouter) {
            VirtualRouter router = (VirtualRouter) vm;
            if (router.getRole() != null) {
                vmResponse.setRole(router.getRole().toString());
            }
        }
        vmResponse.setObjectName("systemvminstance");
        return vmResponse;
    }

    @Override
    public PhysicalNetworkResponse createPhysicalNetworkResponse(PhysicalNetwork result) {
        PhysicalNetworkResponse response = new PhysicalNetworkResponse();

        response.setZoneId(result.getDataCenterId());
        response.setNetworkSpeed(result.getSpeed());
        response.setVlan(result.getVnet());
        response.setDomainId(result.getDomainId());
        response.setId(result.getUuid());
        if (result.getBroadcastDomainRange() != null) {
            response.setBroadcastDomainRange(result.getBroadcastDomainRange().toString());
        }
        response.setIsolationMethods(result.getIsolationMethods());
        response.setTags(result.getTags());
        if (result.getState() != null) {
            response.setState(result.getState().toString());
        }

        response.setName(result.getName());

        response.setObjectName("physicalnetwork");
        return response;
    }

    @Override
    public ServiceResponse createNetworkServiceResponse(Service service) {
        ServiceResponse response = new ServiceResponse();
        response.setName(service.getName());

        // set list of capabilities required for the service
        List capabilityResponses = new ArrayList();
        Capability[] capabilities = service.getCapabilities();
        for (Capability cap : capabilities) {
            CapabilityResponse capabilityResponse = new CapabilityResponse();
            capabilityResponse.setName(cap.getName());
            capabilityResponse.setObjectName("capability");
            if (cap.getName().equals(Capability.SupportedLBIsolation.getName()) ||
                    cap.getName().equals(Capability.SupportedSourceNatTypes.getName()) ||
                    cap.getName().equals(Capability.RedundantRouter.getName())) {
                capabilityResponse.setCanChoose(true);
            } else {
                capabilityResponse.setCanChoose(false);
            }
            capabilityResponses.add(capabilityResponse);
        }
        response.setCapabilities(capabilityResponses);

        // set list of providers providing this service
        List serviceProviders = ApiDBUtils.getProvidersForService(service);
        List serviceProvidersResponses = new ArrayList();
        for (Network.Provider serviceProvider : serviceProviders) {
            // return only Virtual Router/JuniperSRX as a provider for the firewall
            if (service == Service.Firewall && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX)) {
                continue;
            }

            ProviderResponse serviceProviderResponse = createServiceProviderResponse(serviceProvider);
            serviceProvidersResponses.add(serviceProviderResponse);
        }
        response.setProviders(serviceProvidersResponses);

        response.setObjectName("networkservice");
        return response;

    }

    private ProviderResponse createServiceProviderResponse(Provider serviceProvider) {
        ProviderResponse response = new ProviderResponse();
        response.setName(serviceProvider.getName());
        boolean canEnableIndividualServices = ApiDBUtils.canElementEnableIndividualServices(serviceProvider);
        response.setCanEnableIndividualServices(canEnableIndividualServices);
        return response;
    }

    @Override
    public ProviderResponse createNetworkServiceProviderResponse(PhysicalNetworkServiceProvider result) {
        ProviderResponse response = new ProviderResponse();
        response.setId(result.getUuid());
        response.setName(result.getProviderName());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        response.setDestinationPhysicalNetworkId(result.getDestinationPhysicalNetworkId());
        response.setState(result.getState().toString());

        // set enabled services
        List services = new ArrayList();
        for (Service service : result.getEnabledServices()) {
            services.add(service.getName());
        }
        response.setServices(services);

        response.setObjectName("networkserviceprovider");
        return response;
    }

    @Override
    public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType result) {
        TrafficTypeResponse response = new TrafficTypeResponse();
        response.setId(result.getUuid());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        response.setTrafficType(result.getTrafficType().toString());
        response.setXenLabel(result.getXenNetworkLabel());
        response.setKvmLabel(result.getKvmNetworkLabel());
        response.setVmwareLabel(result.getVmwareNetworkLabel());

        response.setObjectName("traffictype");
        return response;
    }

    @Override
    public VirtualRouterProviderResponse createVirtualRouterProviderResponse(VirtualRouterProvider result) {
        VirtualRouterProviderResponse response = new VirtualRouterProviderResponse();
        response.setId(result.getId());
        response.setNspId(result.getNspId());
        response.setEnabled(result.isEnabled());

        response.setObjectName("virtualrouterelement");
        return response;
    }

    @Override
    public LBStickinessResponse createLBStickinessPolicyResponse(
            StickinessPolicy stickinessPolicy, LoadBalancer lb) {
        LBStickinessResponse spResponse = new LBStickinessResponse();
        spResponse.setlbRuleId(lb.getId());
        Account accountTemp = ApiDBUtils.findAccountById(lb.getAccountId());
        if (accountTemp != null) {
            spResponse.setAccountName(accountTemp.getAccountName());
            spResponse.setDomainId(accountTemp.getDomainId());
            spResponse.setDomainName(ApiDBUtils.findDomainById(
                    accountTemp.getDomainId()).getName());
        }

        List responses = new ArrayList();
        LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(
                stickinessPolicy);
        responses.add(ruleResponse);

        spResponse.setRules(responses);

        spResponse.setObjectName("stickinesspolicies");
        return spResponse;
    }

    @Override
    public LBStickinessResponse createLBStickinessPolicyResponse(
            List stickinessPolicies, LoadBalancer lb) {
        LBStickinessResponse spResponse = new LBStickinessResponse();

        if (lb == null) {
            return spResponse;
        }
        spResponse.setlbRuleId(lb.getId());
        Account account = ApiDBUtils.findAccountById(lb.getAccountId());
        if (account != null) {
            spResponse.setAccountName(account.getAccountName());
            spResponse.setDomainId(account.getDomainId());
            spResponse.setDomainName(ApiDBUtils.findDomainById(
                    account.getDomainId()).getName());
        }

        List responses = new ArrayList();
        for (StickinessPolicy stickinessPolicy : stickinessPolicies) {
            LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(stickinessPolicy);
            responses.add(ruleResponse);
        }
        spResponse.setRules(responses);

        spResponse.setObjectName("stickinesspolicies");
        return spResponse;
    }

    @Override
    public LDAPConfigResponse createLDAPConfigResponse(String hostname,
            Integer port, Boolean useSSL, String queryFilter,
            String searchBase, String bindDN) {
        LDAPConfigResponse lr = new LDAPConfigResponse();
        lr.setHostname(hostname);
        lr.setPort(port.toString());
        lr.setUseSSL(useSSL.toString());
        lr.setQueryFilter(queryFilter);
        lr.setBindDN(bindDN);
        lr.setSearchBase(searchBase);
        lr.setObjectName("ldapconfig");
        return lr;
    }

    @Override
    public StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result) {
        StorageNetworkIpRangeResponse response = new StorageNetworkIpRangeResponse();
        response.setUuid(result.getUuid());
    @Override
        response.setVlan(result.getVlan());
        response.setEndIp(result.getEndIp());
        response.setStartIp(result.getStartIp());
        response.setPodUuid(result.getPodUuid());
        response.setZoneUuid(result.getZoneUuid());
        response.setNetworkUuid(result.getNetworkUuid());
        response.setNetmask(result.getNetmask());
        response.setGateway(result.getGateway());
        response.setObjectName("storagenetworkiprange");
        return response;
    }
    
    @Override
    public Long getIdentiyId(String tableName, String token) {
        return ApiDispatcher.getIdentiyId(tableName, token);
    }
    
    @Override
    public ResourceTagResponse createResourceTagResponse(ResourceTag resourceTag, boolean keyValueOnly) {
        ResourceTagResponse response = new ResourceTagResponse();
        response.setKey(resourceTag.getKey());
        response.setValue(resourceTag.getValue());
        
        if (!keyValueOnly) {
    @Override
            response.setResourceType(resourceTag.getResourceType().toString());        
            response.setId(ApiDBUtils.getUuid(String.valueOf(resourceTag.getResourceId()),resourceTag.getResourceType()));
            Long accountId = resourceTag.getAccountId();
            Long domainId = resourceTag.getDomainId();
            if (accountId != null) {
                Account account = ApiDBUtils.findAccountByIdIncludingRemoved(resourceTag.getAccountId());

                if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
                    // find the project
                    Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
                    response.setProjectId(project.getId());
                    response.setProjectName(project.getName());
                } else {
                    response.setAccountName(account.getAccountName());
                }
            }
            
            if (domainId != null) {
                response.setDomainId(domainId);
                response.setDomainName(ApiDBUtils.findDomainById(domainId).getName());
            }
            
            response.setCustomer(resourceTag.getCustomer());
        }
        
        response.setObjectName("tag");
  
        return response;
    }
    
    @Override
    public VpcOfferingResponse createVpcOfferingResponse(VpcOffering offering) {
        VpcOfferingResponse response = new VpcOfferingResponse();
        response.setId(offering.getId());
        response.setName(offering.getName());
        response.setDisplayText(offering.getDisplayText());
        response.setIsDefault(offering.isDefault());
        response.setState(offering.getState().name());

        Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            serviceResponses.add(svcRsp);
        }
        response.setServices(serviceResponses);
        response.setObjectName("vpcoffering");
        return response;
    }
    
    public VpcResponse createVpcResponse(Vpc vpc) {
        VpcResponse response = new VpcResponse();
        response.setId(vpc.getId());
        response.setName(vpc.getName());
        response.setDisplayText(vpc.getDisplayText());
        response.setState(vpc.getState().name());
        response.setVpcOfferingId(vpc.getVpcOfferingId());
        response.setCidr(vpc.getCidr());
        response.setRestartRequired(vpc.isRestartRequired());
        response.setNetworkDomain(vpc.getNetworkDomain());

        Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId());
        List serviceResponses = new ArrayList();
        for (Service service : serviceProviderMap.keySet()) {
            ServiceResponse svcRsp = new ServiceResponse();
            // skip gateway service
            if (service == Service.Gateway) {
                continue;
            }
            svcRsp.setName(service.getName());
            List providers = new ArrayList();
            for (Provider provider : serviceProviderMap.get(service)) {
                if (provider != null) {
                    ProviderResponse providerRsp = new ProviderResponse();
                    providerRsp.setName(provider.getName());
                    providers.add(providerRsp);
                }
            }
            svcRsp.setProviders(providers);

            serviceResponses.add(svcRsp);
        }
        
        List networkResponses = new ArrayList();
        List networks = ApiDBUtils.listVpcNetworks(vpc.getId());
        for (Network network : networks) {
            NetworkResponse ntwkRsp = createNetworkResponse(network);
            networkResponses.add(ntwkRsp);
        }
        
        DataCenter zone = ApiDBUtils.findZoneById(vpc.getZoneId());
        response.setZoneId(vpc.getZoneId());
        response.setZoneName(zone.getName());
        
        response.setNetworks(networkResponses);
        response.setServices(serviceResponses);
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.Vpc, vpc.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        
        response.setObjectName("vpc");
        return response;
    }

    @Override
    public PrivateGatewayResponse createPrivateGatewayResponse(PrivateGateway result) {
        PrivateGatewayResponse response = new PrivateGatewayResponse();
        response.setId(result.getId());
        response.setVlan(result.getVlanTag());
        response.setGateway(result.getGateway());
        response.setNetmask(result.getNetmask());
        response.setVpcId(result.getVpcId());
        response.setZoneId(result.getZoneId());
        DataCenter zone = ApiDBUtils.findZoneById(result.getZoneId());
        response.setZoneName(zone.getName());
        response.setAddress(result.getIp4Address());
        response.setPhysicalNetworkId(result.getPhysicalNetworkId());
        
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        response.setState(result.getState().toString());
        
        response.setObjectName("privategateway");
        return response;
    }

    @Override
    public AutoScaleVmProfileResponse createAutoScaleVmProfileResponse(AutoScaleVmProfile profile) {
        AutoScaleVmProfileResponse response = new AutoScaleVmProfileResponse();
        response.setId(profile.getId());
        response.setZoneId(profile.getZoneId());
        response.setServiceOfferingId(profile.getServiceOfferingId());
        response.setTemplateId(profile.getTemplateId());
        response.setOtherDeployParams(profile.getOtherDeployParams());
        response.setSnmpCommunity(profile.getSnmpCommunity());
        response.setSnmpPort(profile.getSnmpPort());
        response.setDestroyVmGraceperiod(profile.getDestroyVmGraceperiod());
        response.setAutoscaleUserId(profile.getAutoScaleUserId());
        response.setObjectName("autoscalevmprofile");

        // Populates the account information in the response
        populateOwner(response, profile);
        return response;
    }

    @Override
    public AutoScalePolicyResponse createAutoScalePolicyResponse(AutoScalePolicy policy) {
        AutoScalePolicyResponse response = new AutoScalePolicyResponse();
        response.setId(policy.getId());
        response.setDuration(policy.getDuration());
        response.setQuietTime(policy.getQuietTime());
        response.setAction(policy.getAction());
        List vos = ApiDBUtils.getAutoScalePolicyConditions(policy.getId());
        ArrayList conditions = new ArrayList(vos.size());
        for (ConditionVO vo : vos) {
            conditions.add(createConditionResponse(vo));
        }
        response.setConditions(conditions);
        response.setObjectName("autoscalepolicy");

        // Populates the account information in the response
        populateOwner(response, policy);
        
        return response;
    }
    
    @Override
    public AutoScaleVmGroupResponse createAutoScaleVmGroupResponse(AutoScaleVmGroup vmGroup) {
        AutoScaleVmGroupResponse response = new AutoScaleVmGroupResponse();
        response.setId(vmGroup.getId());
        response.setMinMembers(vmGroup.getMinMembers());
        response.setMaxMembers(vmGroup.getMaxMembers());
        response.setState(vmGroup.getState());
        response.setInterval(vmGroup.getInterval());
        response.setProfileId(vmGroup.getProfileId());
        response.setLoadBalancerId(vmGroup.getProfileId());

        List scaleUpPoliciesResponse = new ArrayList();
        List scaleDownPoliciesResponse = new ArrayList();
        response.setScaleUpPolicies(scaleUpPoliciesResponse);
        response.setScaleDownPolicies(scaleDownPoliciesResponse);
        response.setObjectName("autoscalevmgroup");

        // Fetch policies for vmgroup
        List scaleUpPolicies = new ArrayList();
        List scaleDownPolicies = new ArrayList();
        ApiDBUtils.getAutoScaleVmGroupPolicies(vmGroup.getId(), scaleUpPolicies, scaleDownPolicies);
        // populate policies
        for (AutoScalePolicy autoScalePolicy : scaleUpPolicies) {
            scaleUpPoliciesResponse.add(createAutoScalePolicyResponse(autoScalePolicy));
        }
        for (AutoScalePolicy autoScalePolicy : scaleDownPolicies) {
            scaleDownPoliciesResponse.add(createAutoScalePolicyResponse(autoScalePolicy));
        }

        return response;
    }

    @Override
    public StaticRouteResponse createStaticRouteResponse(StaticRoute result) {
        StaticRouteResponse response = new StaticRouteResponse();
        response.setId(result.getId());
        response.setVpcId(result.getVpcId());
        response.setCidr(result.getCidr());
        
        StaticRoute.State state = result.getState();
        String stateToSet = state.toString();
        if (state.equals(FirewallRule.State.Revoke)) {
            stateToSet = "Deleting";
        }
        response.setState(stateToSet);
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        //set tag information
        List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.StaticRoute, result.getId());
        List tagResponses = new ArrayList();
        for (ResourceTag tag : tags) {
            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
            tagResponses.add(tagResponse);
        }
        response.setTags(tagResponses);
        response.setObjectName("staticroute");
        return response;
    }
  
    @Override
    public Site2SiteVpnGatewayResponse createSite2SiteVpnGatewayResponse(Site2SiteVpnGateway result) {
        Site2SiteVpnGatewayResponse response = new Site2SiteVpnGatewayResponse();
        response.setId(result.getId());
        response.setIp(ApiDBUtils.findIpAddressById(result.getAddrId()).getAddress().toString());
        response.setVpcId(result.getVpcId());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpngateway");
        
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        return response;
    }

    public Site2SiteCustomerGatewayResponse createSite2SiteCustomerGatewayResponse(Site2SiteCustomerGateway result) {
        Site2SiteCustomerGatewayResponse response = new Site2SiteCustomerGatewayResponse();
        response.setId(result.getId());
        response.setGatewayIp(result.getGatewayIp());
        response.setGuestCidrList(result.getGuestCidrList());
        response.setIpsecPsk(result.getIpsecPsk());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpncustomergateway");
        
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        return response;
    }

    @Override
    public Site2SiteVpnConnectionResponse createSite2SiteVpnConnectionResponse(Site2SiteVpnConnection result) {
        Site2SiteVpnConnectionResponse response = new Site2SiteVpnConnectionResponse();
        response.setId(result.getId());
        
        response.setVpnGatewayId(result.getVpnGatewayId()); 
        Long vpnGatewayId = result.getVpnGatewayId();
        if(vpnGatewayId != null) {
        	Site2SiteVpnGatewayVO vpnGateway = ApiDBUtils.findVpnGatewayById(vpnGatewayId);
        	
        	long ipId = vpnGateway.getAddrId();
        	IPAddressVO ipObj = ApiDBUtils.findIpAddressById(ipId);
        	response.setIp(ipObj.getAddress().addr());  
        }
        
        response.setCustomerGatewayId(result.getCustomerGatewayId()); 
        Long customerGatewayId = result.getCustomerGatewayId();
        if(customerGatewayId != null) {
        	Site2SiteCustomerGatewayVO customerGateway = ApiDBUtils.findCustomerGatewayById(customerGatewayId);
        	response.setGatewayIp(customerGateway.getGatewayIp());
        	response.setGuestCidrList(customerGateway.getGuestCidrList());
        	response.setIpsecPsk(customerGateway.getIpsecPsk());
        	response.setIkePolicy(customerGateway.getIkePolicy());
        	response.setEspPolicy(customerGateway.getEspPolicy());
        	response.setLifetime(customerGateway.getLifetime());
        }      
                
        populateAccount(response, result.getAccountId());
        populateDomain(response, result.getDomainId());
        
        response.setState(result.getState().toString());
        response.setCreated(result.getCreated());
        response.setRemoved(result.getRemoved());
        response.setObjectName("vpnconnection");
        return response;
    }

    @Override
    public CounterResponse createCounterResponse(Counter counter) {
        CounterResponse response = new CounterResponse();
        response.setId(counter.getId());
        response.setSource(counter.getSource().toString());
        response.setName(counter.getName());
        response.setValue(counter.getValue());
        response.setObjectName("counter");
        return response;
    }

    @Override
    public ConditionResponse createConditionResponse(Condition condition) {
        ConditionResponse response = new ConditionResponse();
        response.setId(condition.getId());
        CounterResponse counter;
        counter = createCounterResponse(ApiDBUtils.getCounter(condition.getCounterid()));
        response.setCounter(counter);
        response.setRelationalOperator(condition.getRelationalOperator().toString());
        response.setThreshold(condition.getThreshold());
        response.setObjectName("condition");
        populateOwner(response, condition);
        return response;
    }
}
File
ApiResponseHelper.java
Developer's decision
Combination
Kind of conflict
Class declaration
Comment
Import
Package declaration
Chunk
Conflicting content
<<<<<<< HEAD
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.vm;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
    @Inject
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
                    }
import com.cloud.service.dao.ServiceOfferingDao;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.ejb.Local;
import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.OnError;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.agent.api.ClusterSyncAnswer;
import com.cloud.agent.api.ClusterSyncCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.Commands;
import com.cloud.agent.manager.allocator.HostAllocator;
import com.cloud.alert.AlertManager;
import com.cloud.capacity.CapacityManager;
import com.cloud.cluster.ClusterManager;
import com.cloud.cluster.StackMaid;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ManagementServerException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.VirtualMachineMigrationException;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.ha.HighAvailabilityManager.WorkType;
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.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.resource.ResourceManager;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.Journal;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.ItWorkVO.Step;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

@Local(value = VirtualMachineManager.class)
public class VirtualMachineManagerImpl implements VirtualMachineManager, Listener {
            try {
    private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class);

    String _name;
    @Inject
    protected StorageManager _storageMgr;
    @Inject
    protected NetworkManager _networkMgr;
    @Inject
    protected AgentManager _agentMgr;
    @Inject
    protected VMInstanceDao _vmDao;
    @Inject
    protected ServiceOfferingDao _offeringDao;
    @Inject
    protected VMTemplateDao _templateDao;
    @Inject
    protected UserDao _userDao;
    @Inject
    protected AccountDao _accountDao;
    @Inject
    protected DomainDao _domainDao;
    @Inject
    protected ClusterManager _clusterMgr;
    @Inject
    protected ItWorkDao _workDao;
    @Inject
    protected UserVmDao _userVmDao;
    @Inject
    protected DomainRouterDao _routerDao;
    @Inject
    protected ConsoleProxyDao _consoleDao;
    @Inject
    protected SecondaryStorageVmDao _secondaryDao;
    @Inject
    protected NicDao _nicsDao;
    @Inject
    protected AccountManager _accountMgr;
    @Inject
    protected HostDao _hostDao;
    @Inject
    protected AlertManager _alertMgr;
    @Inject
    protected GuestOSCategoryDao _guestOsCategoryDao;
    @Inject
    protected GuestOSDao _guestOsDao;
    @Inject
    protected VolumeDao _volsDao;
    @Inject
    protected ConsoleProxyManager _consoleProxyMgr;
    @Inject
    protected ConfigurationManager _configMgr;
    @Inject
    protected CapacityManager _capacityMgr;
    @Inject
    protected HighAvailabilityManager _haMgr;
    protected HostPodDao _podDao;
    @Inject
    protected DataCenterDao _dcDao;
    @Inject
    protected StoragePoolDao _storagePoolDao;
    @Inject
    protected HypervisorGuruManager _hvGuruMgr;
    @Inject
    protected NetworkDao _networkDao;

    @Inject(adapter = DeploymentPlanner.class)
    protected Adapters _planners;

    @Inject(adapter = HostAllocator.class)
    protected Adapters _hostAllocators;

    @Inject
    protected ResourceManager _resourceMgr;

    Map> _vmGurus = new HashMap>();
    protected StateMachine2 _stateMachine;

    ScheduledExecutorService _executor = null;
    protected int _operationTimeout;

    protected int _retry;
    protected long _nodeId;
    protected long _cleanupWait;
    protected long _cleanupInterval;
    protected long _cancelWait;
    protected long _opWaitInterval;
    protected int _lockStateRetry;
    protected boolean _forceStop;

    @Override
    public  void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) {
        synchronized (_vmGurus) {
            _vmGurus.put(type, guru);
        }
    }

    @Override
    @DB
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Pair rootDiskOffering,
            List> dataDiskOfferings, List> networks, Map params, DeploymentPlan plan,
            HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocating entries for VM: " + vm);
        }

        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, params);

        vm.setDataCenterId(plan.getDataCenterId());
        if (plan.getPodId() != null) {
            vm.setPodId(plan.getPodId());
        }
        assert (plan.getClusterId() == null && plan.getPoolId() == null) : "We currently don't support cluster and pool preset yet";

        @SuppressWarnings("unchecked")
        VirtualMachineGuru guru = (VirtualMachineGuru) _vmGurus.get(vm.getType());

        Transaction txn = Transaction.currentTxn();
        txn.start();
        vm = guru.persist(vm);

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocating nics for " + vm);
        }
        
        try {
            _networkMgr.allocate(vmProfile, networks);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Concurrent operation while trying to allocate resources for the VM", e);
        }

        if (dataDiskOfferings == null) {
            dataDiskOfferings = new ArrayList>(0);
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocaing disks for " + vm);
        }

        if (template.getFormat() == ImageFormat.ISO) {
            _storageMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner);
        } else if (template.getFormat() == ImageFormat.BAREMETAL) {
            // Do nothing
        } else {
            _storageMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
        }

        for (Pair offering : dataDiskOfferings) {
            _storageMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
        }

        txn.commit();
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocation completed for VM: " + vm);
        }

        return vm;
    }

    @Override
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, Pair dataDiskOffering,
            List> networks, DeploymentPlan plan, HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        List> diskOfferings = new ArrayList>(1);
        if (dataDiskOffering != null) {
            diskOfferings.add(dataDiskOffering);
        }
        return allocate(vm, template, serviceOffering, new Pair(serviceOffering, rootSize), diskOfferings, networks, null, plan, hyperType, owner);
    }

    @Override
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, List> networks, DeploymentPlan plan,
            HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        return allocate(vm, template, serviceOffering, new Pair(serviceOffering, null), null, networks, null, plan, hyperType, owner);
    }

    @SuppressWarnings("unchecked")
    private  VirtualMachineGuru getVmGuru(T vm) {
        return (VirtualMachineGuru) _vmGurus.get(vm.getType());
    }

    @SuppressWarnings("unchecked")
    private  VirtualMachineGuru getBareMetalVmGuru(T vm) {
        return (VirtualMachineGuru) _vmGurus.get(VirtualMachine.Type.UserBareMetal);
    }

    @Override
    public  boolean expunge(T vm, User caller, Account account) throws ResourceUnavailableException {
        try {
            if (advanceExpunge(vm, caller, account)) {
                // Mark vms as removed
                remove(vm, caller, account);
                return true;
            } else {
                s_logger.info("Did not expunge " + vm);
                return false;
            }
        } catch (OperationTimedoutException e) {
            throw new CloudRuntimeException("Operation timed out", e);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Concurrent operation ", e);
        }
    }

    @Override
    public  boolean advanceExpunge(T vm, User caller, Account account) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        if (vm == null || vm.getRemoved() != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vm);
            }
            return true;
        }

        if (!this.advanceStop(vm, false, caller, account)) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to stop the VM so we can't expunge it.");
            }
        }

        try {
            if (!stateTransitTo(vm, VirtualMachine.Event.ExpungeOperation, vm.getHostId())) {
                s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
                return false;
            }
        } catch (NoTransitionException e) {
            s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
            return false;
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Destroying vm " + vm);
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        s_logger.debug("Cleaning up NICS");
        _networkMgr.cleanupNics(profile);
        // Clean up volumes based on the vm's instance id
        _storageMgr.cleanupVolumes(vm.getId());

        VirtualMachineGuru guru = getVmGuru(vm);
        guru.finalizeExpunge(vm);

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Expunged " + vm);
        }

        return true;
    }

    @Override
    public boolean start() {
        _executor.scheduleAtFixedRate(new CleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS);
        cancelWorkItems(_nodeId);
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean configure(String name, Map xmlParams) throws ConfigurationException {
        _name = name;

        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
        Map params = configDao.getConfiguration(xmlParams);

        _retry = NumbersUtil.parseInt(params.get(Config.StartRetry.key()), 10);

        ReservationContextImpl.setComponents(_userDao, _domainDao, _accountDao);
        VirtualMachineProfileImpl.setComponents(_offeringDao, _templateDao, _accountDao);

        _cancelWait = NumbersUtil.parseLong(params.get(Config.VmOpCancelInterval.key()), 3600);
        _cleanupWait = NumbersUtil.parseLong(params.get(Config.VmOpCleanupWait.key()), 3600);
        _cleanupInterval = NumbersUtil.parseLong(params.get(Config.VmOpCleanupInterval.key()), 86400) * 1000;
        _opWaitInterval = NumbersUtil.parseLong(params.get(Config.VmOpWaitInterval.key()), 120) * 1000;
        _lockStateRetry = NumbersUtil.parseInt(params.get(Config.VmOpLockStateRetry.key()), 5);
        _operationTimeout = NumbersUtil.parseInt(params.get(Config.Wait.key()), 1800) * 2;
        _forceStop = Boolean.parseBoolean(params.get(Config.VmDestroyForcestop.key()));

        _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vm-Operations-Cleanup"));
        _nodeId = _clusterMgr.getManagementNodeId();

        _agentMgr.registerForHostEvents(this, true, true, true);

        return true;
    }

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

    protected VirtualMachineManagerImpl() {
        setStateMachine();
    }

    @Override
    public  T start(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException {
        return start(vm, params, caller, account, null);
    }

    @Override
    public  T start(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException,
    ResourceUnavailableException {
        try {
            return advanceStart(vm, params, caller, account, planToDeploy);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to start a VM due to concurrent operation", e);
        }
    }

    protected boolean checkWorkItems(VMInstanceVO vm, State state) throws ConcurrentOperationException {
        while (true) {
            ItWorkVO vo = _workDao.findByOutstandingWork(vm.getId(), state);
            if (vo == null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to find work for VM: " + vm + " and state: " + state);
                }
                return true;
            }

            if (vo.getStep() == Step.Done) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Work for " + vm + " is " + vo.getStep());
                }
                return true;
            }

            if (vo.getSecondsTaskIsInactive() > _cancelWait) {
                s_logger.warn("The task item for vm " + vm + " has been inactive for " + vo.getSecondsTaskIsInactive());
                return false;
            }

            try {
                Thread.sleep(_opWaitInterval);
            } catch (InterruptedException e) {
                s_logger.info("Waiting for " + vm + " but is interrupted");
                throw new ConcurrentOperationException("Waiting for " + vm + " but is interrupted");
            }
            s_logger.debug("Waiting some more to make sure there's no activity on " + vm);
        }

    }

    @DB
    protected  Ternary changeToStartState(VirtualMachineGuru vmGuru, T vm, User caller, Account account)
            throws ConcurrentOperationException {
        long vmId = vm.getId();

        ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getType(), vm.getId());
        int retry = _lockStateRetry;
        while (retry-- != 0) {
            Transaction txn = Transaction.currentTxn();
            Ternary result = null;
            txn.start();
            try {
                Journal journal = new Journal.LogJournal("Creating " + vm, s_logger);
                work = _workDao.persist(work);
                ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account);

                if (stateTransitTo(vm, Event.StartRequested, null, work.getId())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId());
                    }
                    result = new Ternary(vmGuru.findById(vmId), context, work);
                    txn.commit();
                    return result;
                }
            } catch (NoTransitionException e) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to transition into Starting state due to " + e.getMessage());
                }
            } finally {
                if (result == null) {
                    txn.rollback();
                }
            }

            VMInstanceVO instance = _vmDao.findById(vmId);
            if (instance == null) {
                throw new ConcurrentOperationException("Unable to acquire lock on " + vm);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Determining why we're unable to update the state to Starting for " + instance + ".  Retry=" + retry);
            }

            State state = instance.getState();
            if (state == State.Running) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("VM is already started: " + vm);
                }
                return null;
            }

            if (state.isTransitional()) {
                if (!checkWorkItems(vm, state)) {
                    throw new ConcurrentOperationException("There are concurrent operations on " + vm);
                } else {
                    continue;
                }
            }

            if (state != State.Stopped) {
                s_logger.debug("VM " + vm + " is not in a state to be started: " + state);
                return null;
            }
        }

        throw new ConcurrentOperationException("Unable to change the state of " + vm);
    }

    protected  boolean changeState(T vm, Event event, Long hostId, ItWorkVO work, Step step) throws NoTransitionException {
        // FIXME: We should do this better.
            }
        Step previousStep = work.getStep();
        _workDao.updateStep(work, step);
        boolean result = false;
        try {
            result = stateTransitTo(vm, event, hostId);
            return result;
        } finally {
            if (!result) {
                _workDao.updateStep(work, previousStep);
            }
        }
    }

    @Override
    public  T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException,
    ConcurrentOperationException, ResourceUnavailableException {
        return advanceStart(vm, params, caller, account, null);
    }

    @Override
    public  T advanceStart(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy)
            throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
        long vmId = vm.getId();
        VirtualMachineGuru vmGuru;
        if (vm.getHypervisorType() == HypervisorType.BareMetal) {
            vmGuru = getBareMetalVmGuru(vm);
        } else {
            vmGuru = getVmGuru(vm);
        }

        vm = vmGuru.findById(vm.getId());
        Ternary start = changeToStartState(vmGuru, vm, caller, account);
        if (start == null) {
            return vmGuru.findById(vmId);
        }

        vm = start.first();
        ReservationContext ctx = start.second();
        ItWorkVO work = start.third();

        T startedVm = null;
        ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId());
        VMTemplateVO template = _templateDao.findById(vm.getTemplateId());

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Trying to deploy VM, vm has dcId: " + vm.getDataCenterIdToDeployIn() + " and podId: " + vm.getPodIdToDeployIn());
        }
        DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), null, null, null, null, ctx);
        if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("advanceStart: DeploymentPlan is provided, using dcId:" + planToDeploy.getDataCenterId() + ", podId: " + planToDeploy.getPodId() + ", clusterId: "
                        + planToDeploy.getClusterId() + ", hostId: " + planToDeploy.getHostId() + ", poolId: " + planToDeploy.getPoolId());
            }
            plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId(), ctx);
        }

        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());

        boolean canRetry = true;
        try {
            Journal journal = start.second().getJournal();

            ExcludeList avoids = null;
            if (planToDeploy != null) {
                avoids = planToDeploy.getAvoids();
            }
            if (avoids == null) {
                avoids = new ExcludeList();
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", clusters: " + avoids.getClustersToAvoid() + ", hosts: " + avoids.getHostsToAvoid());
            }


            boolean planChangedByVolume = false;
            boolean reuseVolume = true;
            DataCenterDeployment originalPlan = plan;

            int retry = _retry;
            boolean recreate = false;
            while (retry-- != 0) { // It's != so that it can match -1.

                if(reuseVolume){
                    // edit plan if this vm's ROOT volume is in READY state already
                    List vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
                    for (VolumeVO vol : vols) {
                        // make sure if the templateId is unchanged. If it is changed,
                        // let planner
                        // reassign pool for the volume even if it ready.
                        Long volTemplateId = vol.getTemplateId();
                        if (volTemplateId != null && volTemplateId.longValue() != template.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug(vol + " of " + vm + " is READY, but template ids don't match, let the planner reassign a new pool");
                            }
                            continue;
                        }
    
                        StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
                        if (!pool.isInMaintenance()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Root volume is ready, need to place VM in volume's cluster");
                            }
                            long rootVolDcId = pool.getDataCenterId();
                            Long rootVolPodId = pool.getPodId();
                            Long rootVolClusterId = pool.getClusterId();
                            if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
                                Long clusterIdSpecified = planToDeploy.getClusterId();
                                if (clusterIdSpecified != null && rootVolClusterId != null) {
                                    if (rootVolClusterId.longValue() != clusterIdSpecified.longValue()) {
                                        // cannot satisfy the plan passed in to the
                                        // planner
                                        if (s_logger.isDebugEnabled()) {
                                            s_logger.debug("Cannot satisfy the deployment plan passed in since the ready Root volume is in different cluster. volume's cluster: " + rootVolClusterId
                                                    + ", cluster specified: " + clusterIdSpecified);
                                        }
                                        throw new ResourceUnavailableException("Root volume is ready in different cluster, Deployment plan provided cannot be satisfied, unable to create a deployment for "
                                                + vm, Cluster.class, clusterIdSpecified);
                                    }
                                }
                                plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), vol.getPoolId(), null, ctx);
                            }else{
                                plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, ctx);
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug(vol + " is READY, changing deployment plan to use this pool's dcId: " + rootVolDcId + " , podId: " + rootVolPodId + " , and clusterId: " + rootVolClusterId);
                                }
                                planChangedByVolume = true;
                            }
                        }
                    }
                }
                
                VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, account, params);
                DeployDestination dest = null;
                for (DeploymentPlanner planner : _planners) {
                    if (planner.canHandle(vmProfile, plan, avoids)) {
                        dest = planner.plan(vmProfile, plan, avoids);
                    } else {
                        continue;
                    }
                    if (dest != null) {
                        avoids.addHost(dest.getHost().getId());
                        journal.record("Deployment found ", vmProfile, dest);
                        break;
                    }
                }

                if (dest == null) {
                    if (planChangedByVolume) {
                        plan = originalPlan;
                        planChangedByVolume = false;
                        //do not enter volume reuse for next retry, since we want to look for resorces outside the volume's cluster
                        reuseVolume = false;
                        continue;
                    }
                    throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
                }

        }
                long destHostId = dest.getHost().getId();
                vm.setPodId(dest.getPod().getId());

                try {
                    if (!changeState(vm, Event.OperationRetry, destHostId, work, Step.Prepare)) {
                        throw new ConcurrentOperationException("Unable to update the state of the Virtual Machine");
                    }
                } catch (NoTransitionException e1) {
                    throw new ConcurrentOperationException(e1.getMessage());
                }

                try {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("VM is being created in podId: " + vm.getPodIdToDeployIn());
                    }
                    _networkMgr.prepare(vmProfile, dest, ctx); 
                    if (vm.getHypervisorType() != HypervisorType.BareMetal) {
                        _storageMgr.prepare(vmProfile, dest, recreate);
                        recreate = false;
                    }
                    //since StorageMgr succeeded in volume creation, reuse Volume for further tries until current cluster has capacity
                    if(!reuseVolume){
                        reuseVolume = true;
                    }
                    
                    Commands cmds = null;
                    vmGuru.finalizeVirtualMachineProfile(vmProfile, dest, ctx);

                    VirtualMachineTO vmTO = hvGuru.implement(vmProfile);

                    cmds = new Commands(OnError.Stop);
                    cmds.addCommand(new StartCommand(vmTO));

                    vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx);


                    work = _workDao.findById(work.getId());
                    if (work == null || work.getStep() != Step.Prepare) {
                        throw new ConcurrentOperationException("Work steps have been changed: " + work);
                    _workDao.updateStep(work, Step.Starting);

                    _agentMgr.send(destHostId, cmds);
                    
                    _workDao.updateStep(work, Step.Started);
                    
                    
                    StartAnswer startAnswer = cmds.getAnswer(StartAnswer.class);
                    if (startAnswer != null && startAnswer.getResult()) {
                        String host_guid = startAnswer.getHost_guid();
                        if( host_guid != null ) {
                            HostVO finalHost = _resourceMgr.findHostByGuid(host_guid);
                            if (finalHost == null ) {
                                throw new CloudRuntimeException("Host Guid " + host_guid + " doesn't exist in DB, something wrong here");
                            }
                            destHostId = finalHost.getId();
                        }
                        if (vmGuru.finalizeStart(vmProfile, destHostId, cmds, ctx)) {
                            if (!changeState(vm, Event.OperationSucceeded, destHostId, work, Step.Done)) {
                                throw new ConcurrentOperationException("Unable to transition to a new state.");
                            }
                            startedVm = vm;
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Start completed for VM " + vm);
                            }
                            return startedVm;
                        } else {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.info("The guru did not like the answers so stopping " + vm);
                            }
                           
                            StopCommand cmd = new StopCommand(vm.getInstanceName());
                            StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd);
                            if (answer == null || !answer.getResult()) {
                                s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers")); 
                                _haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop);
                                throw new ExecutionException("Unable to stop " + vm + " so we are unable to retry the start operation");
                            }
    @Override
                            if (vmGuru.recreateNeeded(vmProfile, destHostId, cmds, ctx)) {
                            	recreate = true;
                            } else {
                            	throw new ExecutionException("Unable to start " + vm + " due to error in finalizeStart, not retrying");
                            }
                        }
                    }
                    s_logger.info("Unable to start VM on " + dest.getHost() + " due to " + (startAnswer == null ? " no start answer" : startAnswer.getDetails()));
                    
                } catch (OperationTimedoutException e) {
                    s_logger.debug("Unable to send the start command to host " + dest.getHost());
                    if (e.isActive()) {
                        _haMgr.scheduleStop(vm, destHostId, WorkType.CheckStop);
                    }
                    canRetry = false;
                    throw new AgentUnavailableException("Unable to start " + vm.getHostName(), destHostId, e);
                } catch (ResourceUnavailableException e) {
                    s_logger.info("Unable to contact resource.", e);
                    if (!avoids.add(e)) {
                        if (e.getScope() == Volume.class || e.getScope() == Nic.class) {
                            throw e;
                        } else {
                            s_logger.warn("unexpected ResourceUnavailableException : " + e.getScope().getName(), e);
                            throw e;
                        }
                    }
                } catch (InsufficientCapacityException e) {
                    s_logger.info("Insufficient capacity ", e);
                    if (!avoids.add(e)) {
                        if (e.getScope() == Volume.class || e.getScope() == Nic.class) {
                            throw e;
                        } else {
                            s_logger.warn("unexpected InsufficientCapacityException : " + e.getScope().getName(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Failed to start instance " + vm, e);
                    throw new AgentUnavailableException("Unable to start instance due to " + e.getMessage(), destHostId, e);
                } finally {
                    if (startedVm == null && canRetry) {
                        Step prevStep = work.getStep();
                        _workDao.updateStep(work, Step.Release);
                        if (prevStep == Step.Started || prevStep == Step.Starting) {
                            cleanup(vmGuru, vmProfile, work, Event.OperationFailed, false, caller, account);
                        } else {
                            //if step is not starting/started, send cleanup command with force=true
                            cleanup(vmGuru, vmProfile, work, Event.OperationFailed, true, caller, account);
                        }
                    }
                }
            }
        } finally {
            if (startedVm == null) {
                if (canRetry) {
                    try {
                        changeState(vm, Event.OperationFailed, null, work, Step.Done);
                    } catch (NoTransitionException e) {
                        throw new ConcurrentOperationException(e.getMessage());
                    }
                }
            }
        }

        return startedVm;
    }

    @Override
    public  boolean stop(T vm, User user, Account account) throws ResourceUnavailableException {
        try {
            return advanceStop(vm, false, user, account);
        } catch (OperationTimedoutException e) {
            throw new AgentUnavailableException("Unable to stop vm because the operation to stop timed out", vm.getHostId(), e);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to stop vm because of a concurrent operation", e);
        }
    }

    protected  boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) {
        VMInstanceVO vm = profile.getVirtualMachine();
        StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
        try {
            Answer answer = _agentMgr.send(vm.getHostId(), stop);
            if (!answer.getResult()) {
                s_logger.debug("Unable to stop VM due to " + answer.getDetails());
                return false;
            }

            guru.finalizeStop(profile, (StopAnswer) answer);
        } catch (AgentUnavailableException e) {
            if (!force) {
                return false;
            }
        } catch (OperationTimedoutException e) {
            if (!force) {
                return false;
            }
        }

        return true;
    }

    protected  boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile, ItWorkVO work, Event event, boolean force, User user, Account account) {
        T vm = profile.getVirtualMachine();
        State state = vm.getState();
        s_logger.debug("Cleaning up resources for the vm " + vm + " in " + state + " state");
        if (state == State.Starting) {
            Step step = work.getStep();
            if (step == Step.Starting && !force) {
                s_logger.warn("Unable to cleanup vm " + vm + "; work state is incorrect: " + step);
                return false;
            }

            if (step == Step.Started || step == Step.Starting || step == Step.Release) {
                if (vm.getHostId() != null) {
                    if (!sendStop(guru, profile, force)) {
                        s_logger.warn("Failed to stop vm " + vm + " in " + State.Starting + " state as a part of cleanup process");
                        return false;
                    }
                }
            }

            if (step != Step.Release && step != Step.Prepare && step != Step.Started && step != Step.Starting) {
                s_logger.debug("Cleanup is not needed for vm " + vm + "; work state is incorrect: " + step);
                return true;
            }
        } else if (state == State.Stopping) {
            if (vm.getHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Stopping + " state as a part of cleanup process");
                    return false;
                }
            }
        } else if (state == State.Migrating) {
            if (vm.getHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process");
                    return false;
                }
            }
            if (vm.getLastHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process");
                    return false;
                }
            }
        } else if (state == State.Running) {
            if (!sendStop(guru, profile, force)) {
                s_logger.warn("Failed to stop vm " + vm + " in " + State.Running + " state as a part of cleanup process");
                return false;
            }
        }

        try {
            _networkMgr.release(profile, force);
            s_logger.debug("Successfully released network resources for the vm " + vm);
        } catch (Exception e) {
            s_logger.warn("Unable to release some network resources.", e);
        }

        _storageMgr.release(profile);
        s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state");
        return true;
    }

    @Override
    public  boolean advanceStop(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        State state = vm.getState();
        if (state == State.Stopped) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM is already stopped: " + vm);
            }
            return true;
        }

        if (state == State.Destroyed || state == State.Expunging || state == State.Error) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Stopped called on " + vm + " but the state is " + state);
            }
            return true;
        }
        // grab outstanding work item if any
        ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found an outstanding work item for this vm " + vm + " with state:" + vm.getState() + ", work id:" + work.getId());
            }
        }
        Long hostId = vm.getHostId();
        if (hostId == null) {
            if (!forced) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("HostId is null but this is not a forced stop, cannot stop vm " + vm + " with state:" + vm.getState());
                }
                return false;
            }
            try {
                stateTransitTo(vm, Event.AgentReportStopped, null, null);
            } catch (NoTransitionException e) {
                s_logger.warn(e.getMessage());
            }
            // mark outstanding work item if any as done
            if (work != null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Updating work item to Done, id:" + work.getId());
                }
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }
            return true;
        }

        VirtualMachineGuru vmGuru = getVmGuru(vm);
        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);

        try {
            if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
                throw new ConcurrentOperationException("VM is being operated on.");
            }
        } catch (NoTransitionException e1) {
            if (!forced) {
                throw new CloudRuntimeException("We cannot stop " + vm + " when it is in state " + vm.getState());
            }
            boolean doCleanup = false;
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to transition the state but we're moving on because it's forced stop");
            }
            if (state == State.Starting || state == State.Migrating) {
                if (work != null) {
                    doCleanup = true;
                } else {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to cleanup VM: " + vm + " ,since outstanding work item is not found");
                    }
                    throw new CloudRuntimeException("Work item not found, We cannot stop " + vm + " when it is in state " + vm.getState());
                }
            } else if (state == State.Stopping) {
                doCleanup = true;
            }

            if (doCleanup) {
                if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) {
                    try {
                        if (s_logger.isDebugEnabled()) {
                            s_logger.debug("Updating work item to Done, id:" + work.getId());
                        }
                        return changeState(vm, Event.AgentReportStopped, null, work, Step.Done);
                    } catch (NoTransitionException e) {
                        s_logger.warn("Unable to cleanup " + vm);
                        return false;
                    }
                } else {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Failed to cleanup VM: " + vm);
                    }
                    throw new CloudRuntimeException("Failed to cleanup " + vm + " , current state " + vm.getState());
                }
            _networkMgr.release(profile, forced);

        if (vm.getState() != State.Stopping) {
            throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState());
        }

        vmGuru.prepareStop(profile);
        
        StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
        boolean stopped = false;
        StopAnswer answer = null;
        try {
            answer = (StopAnswer) _agentMgr.send(vm.getHostId(), stop);
            stopped = answer.getResult();
            if (!stopped) {
                throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
            }
            vmGuru.finalizeStop(profile, answer);

        } catch (AgentUnavailableException e) {
        } catch (OperationTimedoutException e) {
        } finally {
            if (!stopped) {
                if (!forced) {
                    s_logger.warn("Unable to stop vm " + vm);
                    try {
                        stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
                    } catch (NoTransitionException e) {
                        s_logger.warn("Unable to transition the state " + vm);
                    }
                    return false;
                } else {
                    s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop");
                    vmGuru.finalizeStop(profile, answer);
                }
            }
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug(vm + " is stopped on the host.  Proceeding to release resource held.");
        }

        try {
            s_logger.debug("Successfully released network resources for the vm " + vm);
        } catch (Exception e) {
            s_logger.warn("Unable to release some network resources.", e);
        }

        try {
            if (vm.getHypervisorType() != HypervisorType.BareMetal) {
                _storageMgr.release(profile);
                s_logger.debug("Successfully released storage resources for the vm " + vm);
            }
        } catch (Exception e) {
            s_logger.warn("Unable to release storage resources.", e);
        }

        try {
            if (work != null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Updating the outstanding work item to Done, id:" + work.getId());
                }
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }

            return stateTransitTo(vm, Event.OperationSucceeded, null, null);
        } catch (NoTransitionException e) {
            s_logger.warn(e.getMessage());
            return false;
        }
    }

    private void setStateMachine() {
        _stateMachine = VirtualMachine.State.getStateMachine();
    }

    protected boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId, String reservationId) throws NoTransitionException {
        vm.setReservationId(reservationId);
        return _stateMachine.transitTo(vm, e, new Pair(vm.getHostId(), hostId), _vmDao);
    }

    @Override
    public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) throws NoTransitionException {
        State oldState = vm.getState();
        if (oldState == State.Starting) {
            if (e == Event.OperationSucceeded) {
                vm.setLastHostId(hostId);
            }
        } else if (oldState == State.Stopping) {
            if (e == Event.OperationSucceeded) {
                vm.setLastHostId(vm.getHostId());
            }
        }
        return _stateMachine.transitTo(vm, e, new Pair(vm.getHostId(), hostId), _vmDao);
    }

    @Override
    public  boolean remove(T vm, User user, Account caller) {
        return _vmDao.remove(vm.getId());
    }

    @Override
    public  boolean destroy(T vm, User user, Account caller) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Destroying vm " + vm);
        }
        if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging || vm.getRemoved() != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vm);
            }
            return true;
        }

        if (!advanceStop(vm, _forceStop, user, caller)) {
            s_logger.debug("Unable to stop " + vm);
            return false;
        }

        try {
            if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) {
                s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
                return false;
            }
        } catch (NoTransitionException e) {
            s_logger.debug(e.getMessage());
            return false;
        }

        return true;
    }

    protected boolean checkVmOnHost(VirtualMachine vm, long hostId) throws AgentUnavailableException, OperationTimedoutException {
        CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(hostId, new CheckVirtualMachineCommand(vm.getInstanceName()));
        long vmId = vm.getId();
        if (!answer.getResult() || answer.getState() == State.Stopped) {
            return false;
        }

        return true;
    }

    @Override
    public  T storageMigration(T vm, StoragePool destPool) {
        VirtualMachineGuru vmGuru = getVmGuru(vm);

        long vmId = vm.getId();
        vm = vmGuru.findById(vmId);

        try {
            stateTransitTo(vm, VirtualMachine.Event.StorageMigrationRequested, null);
        } catch (NoTransitionException e) {
            s_logger.debug("Unable to migrate vm: " + e.toString());
            throw new CloudRuntimeException("Unable to migrate vm: " + e.toString());
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        boolean migrationResult = false;
        try {
            migrationResult = _storageMgr.StorageMigration(profile, destPool);

            if (migrationResult) {
                //if the vm is migrated to different pod in basic mode, need to reallocate ip

                if (vm.getPodIdToDeployIn() != destPool.getPodId()) {
                    DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), destPool.getPodId(), null, null, null, null);
                    VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, null, null, null, null);
                    _networkMgr.reallocate(vmProfile, plan);
                }

                //when start the vm next time, don;'t look at last_host_id, only choose the host based on volume/storage pool
                vm.setLastHostId(null);
                vm.setPodId(destPool.getPodId());
            } else {
                s_logger.debug("Storage migration failed");
            }
        } catch (ConcurrentOperationException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientVirtualNetworkCapcityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
                }
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientAddressCapacityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientCapacityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } finally {
            try {
                stateTransitTo(vm, VirtualMachine.Event.AgentReportStopped, null);
            } catch (NoTransitionException e) {
                s_logger.debug("Failed to change vm state: " + e.toString());
                throw new CloudRuntimeException("Failed to change vm state: " + e.toString());
            }
        }

        return vm;
    }

    @Override
    public  T migrate(T vm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
    VirtualMachineMigrationException {
        s_logger.info("Migrating " + vm + " to " + dest);

        long dstHostId = dest.getHost().getId();
        Host fromHost = _hostDao.findById(srcHostId);
        if (fromHost == null) {
            s_logger.info("Unable to find the host to migrate from: " + srcHostId);
            throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
        }

        if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
            s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
            throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
        }

        VirtualMachineGuru vmGuru = getVmGuru(vm);

        vm = vmGuru.findById(vmId);
        if (vm == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find the vm " + vm);
            }
            throw new ManagementServerException("Unable to find a virtual machine with id " + vmId);
        }

        if (vm.getState() != State.Running) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
            }
            throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString());
        }

        short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
        if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
            alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE;
        } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
            alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        _networkMgr.prepareNicForMigration(profile, dest);
        _storageMgr.prepareForMigration(profile, dest);

        VirtualMachineTO to = toVmTO(profile);
        PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);

        ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
        work.setStep(Step.Prepare);
        work.setResourceType(ItWorkVO.ResourceType.Host);
        work.setResourceId(dstHostId);
        work = _workDao.persist(work);

        PrepareForMigrationAnswer pfma = null;
        try {
            pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
            if (!pfma.getResult()) {
                String msg = "Unable to prepare for migration due to " + pfma.getDetails();
                pfma = null;
                throw new AgentUnavailableException(msg, dstHostId);
            }
        } catch (OperationTimedoutException e1) {
            work.setStep(Step.Done);
            throw new AgentUnavailableException("Operation timed out", dstHostId);
        } finally {
            if (pfma == null) {
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }
        }

        vm.setLastHostId(srcHostId);
        try {
            if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
                s_logger.info("Migration cancelled because state has changed: " + vm);
                throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
            }
        } catch (NoTransitionException e1) {
            s_logger.info("Migration cancelled because " + e1.getMessage());
            throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
        }

        boolean migrated = false;
        try {
            boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
            MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
            mc.setHostGuid(dest.getHost().getGuid());

            try {
                MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
                if (!ma.getResult()) {
                    s_logger.error("Unable to migrate due to " + ma.getDetails());
                    return null;
                }
            } catch (OperationTimedoutException e) {
                if (e.isActive()) {
                    s_logger.warn("Active migration command so scheduling a restart for " + vm);
                    _haMgr.scheduleRestart(vm, true);
                }
                throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
            }

                if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
                    throw new ConcurrentOperationException("Unable to change the state for " + vm);
                }
            } catch (NoTransitionException e1) {
                throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
            }

            try {
                if (!checkVmOnHost(vm, dstHostId)) {
                    s_logger.error("Unable to complete migration for " + vm);
                    try {
                        _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null);
                    } catch (AgentUnavailableException e) {
                        s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
                    }
                    cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                    return null;
                }
            } catch (OperationTimedoutException e) {
            }

            migrated = true;
            return vm;
        } finally {
            if (!migrated) {
                s_logger.info("Migration was unsuccessful.  Cleaning up: " + vm);

                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
                        + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed.  Please check logs.");
                try {
                    _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null);
                } catch (AgentUnavailableException ae) {
                    s_logger.info("Looks like the destination Host is unavailable for cleanup");
                }

                try {
                    stateTransitTo(vm, Event.OperationFailed, srcHostId);
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
            }

            _workDao.update(work.getId(), work);
        }
    }

    @Override
    public VirtualMachineTO toVmTO(VirtualMachineProfile profile) {
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getVirtualMachine().getHypervisorType());
        VirtualMachineTO to = hvGuru.implement(profile);
        return to;
    }

    protected void cancelWorkItems(long nodeId) {
        GlobalLock scanLock = GlobalLock.getInternLock("vmmgr.cancel.workitem");

        try {
            if (scanLock.lock(3)) {
                try {
                    List works = _workDao.listWorkInProgressFor(nodeId);
                    for (ItWorkVO work : works) {
                        s_logger.info("Handling unfinished work item: " + work);
                        try {
                            VMInstanceVO vm = _vmDao.findById(work.getInstanceId());
                            if (vm != null) {
                                if (work.getType() == State.Starting) {
                                    _haMgr.scheduleRestart(vm, true);
                                    work.setManagementServerId(_nodeId);
                                    _workDao.update(work.getId(), work);
                                } else if (work.getType() == State.Stopping) {
                                    _haMgr.scheduleStop(vm, vm.getHostId(), WorkType.CheckStop);
                                    work.setManagementServerId(_nodeId);
                                    _workDao.update(work.getId(), work);
                                } else if (work.getType() == State.Migrating) {
                                    _haMgr.scheduleMigration(vm);
                                    work.setStep(Step.Done);
                                    _workDao.update(work.getId(), work);
                                }
                            }
                        } catch (Exception e) {
                            s_logger.error("Error while handling " + work, e);
                        }
                    }
                } finally {
                    scanLock.unlock();
                }
            }
        } finally {
            scanLock.releaseRef();
        }
    }

    @Override
    public boolean migrateAway(VirtualMachine.Type vmType, long vmId, long srcHostId) throws InsufficientServerCapacityException, VirtualMachineMigrationException {
        VirtualMachineGuru vmGuru = _vmGurus.get(vmType);
        VMInstanceVO vm = vmGuru.findById(vmId);
        if (vm == null) {
            s_logger.debug("Unable to find a VM for " + vmId);
            return true;
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);

        Long hostId = vm.getHostId();
        if (hostId == null) {
            s_logger.debug("Unable to migrate because the VM doesn't have a host id: " + vm);
            return true;
        }

        Host host = _hostDao.findById(hostId);

        DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), null, null, null);
        ExcludeList excludes = new ExcludeList();
        excludes.addHost(hostId);

        DeployDestination dest = null;
        while (true) {
            for (DeploymentPlanner planner : _planners) {
                if (planner.canHandle(profile, plan, excludes)) {
                    dest = planner.plan(profile, plan, excludes);
                } else {
                    continue;
                }

                if (dest != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Planner " + planner + " found " + dest + " for migrating to.");
                    }
                    break;
                }
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Planner " + planner + " was unable to find anything.");
                }
            }

            if (dest == null) {
                throw new InsufficientServerCapacityException("Unable to find a server to migrate to.", host.getClusterId());
            }

            excludes.addHost(dest.getHost().getId());
            VMInstanceVO vmInstance = null;
            try {
                vmInstance = migrate(vm, srcHostId, dest);
            } catch (ResourceUnavailableException e) {
                s_logger.debug("Unable to migrate to unavailable " + dest);
            } catch (ConcurrentOperationException e) {
                s_logger.debug("Unable to migrate VM due to: " + e.getMessage());
            } catch (ManagementServerException e) {
                s_logger.debug("Unable to migrate VM: " + e.getMessage());
            } catch (VirtualMachineMigrationException e) {
                s_logger.debug("Got VirtualMachineMigrationException, Unable to migrate: " + e.getMessage());
                if (vm.getState() == State.Starting) {
                    s_logger.debug("VM seems to be still Starting, we should retry migration later");
                    throw e;
                } else {
                    s_logger.debug("Unable to migrate VM, VM is not in Running or even Starting state, current state: " + vm.getState().toString());
                }
            }
            if (vmInstance != null) {
                return true;
            }
            try {
                boolean result = advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                return result;
            } catch (ResourceUnavailableException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            } catch (ConcurrentOperationException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            } catch (OperationTimedoutException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            }
            return false;
        }
    }

    protected class CleanupTask implements Runnable {
        @Override
        public void run() {
            s_logger.trace("VM Operation Thread Running");
            try {
                _workDao.cleanup(_cleanupWait);
            } catch (Exception e) {
                s_logger.error("VM Operations failed due to ", e);
            }
        }
    }

    @Override
    public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
        Enumeration en = _hostAllocators.enumeration();
        boolean isMachineUpgradable = true;
        while (isMachineUpgradable && en.hasMoreElements()) {
            final HostAllocator allocator = en.nextElement();
            isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
        }

        return isMachineUpgradable;
    }

    @Override
    public  T reboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException {
        try {
            return advanceReboot(vm, params, caller, account);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to reboot a VM due to concurrent operation", e);
        }
    }

    @Override
    public  T advanceReboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException,
    ConcurrentOperationException, ResourceUnavailableException {
        T rebootedVm = null;

        DataCenter dc = _configMgr.getZone(vm.getDataCenterIdToDeployIn());
        Host host = _hostDao.findById(vm.getHostId());
        Cluster cluster = null;
        if (host != null) {
            cluster = _configMgr.getCluster(host.getClusterId());
        }
        HostPodVO pod = _configMgr.getPod(host.getPodId());
        DeployDestination dest = new DeployDestination(dc, pod, cluster, host);

        try {

            Commands cmds = new Commands(OnError.Stop);
            cmds.addCommand(new RebootCommand(vm.getInstanceName()));
            _agentMgr.send(host.getId(), cmds);

            Answer rebootAnswer = cmds.getAnswer(RebootAnswer.class);
            if (rebootAnswer != null && rebootAnswer.getResult()) {
                rebootedVm = vm;
                return rebootedVm;
            }
            s_logger.info("Unable to reboot VM " + vm + " on " + dest.getHost() + " due to " + (rebootAnswer == null ? " no reboot answer" : rebootAnswer.getDetails()));
        } catch (OperationTimedoutException e) {
            s_logger.warn("Unable to send the reboot command to host " + dest.getHost() + " for the vm " + vm + " due to operation timeout", e);
            throw new CloudRuntimeException("Failed to reboot the vm on host " + dest.getHost());
        }

        return rebootedVm;
    }

    @Override
    public VMInstanceVO findByIdAndType(VirtualMachine.Type type, long vmId) {
        VirtualMachineGuru guru = _vmGurus.get(type);
        return guru.findById(vmId);
    }

    public Command cleanup(String vmName) {
        return new StopCommand(vmName);
    }

    public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) {  
        Commands commands = new Commands(OnError.Continue);

        Map infos = convertToInfos(startup);

        final List vms = _vmDao.listByHostId(hostId);
        s_logger.debug("Found " + vms.size() + " VMs for host " + hostId);
        for (VMInstanceVO vm : vms) {
            AgentVmInfo info = infos.remove(vm.getId());
            VMInstanceVO castedVm = null;
            if (info == null) {
                info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
            } 
            castedVm = info.guru.findById(vm.getId());

            HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
            Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
            if (command != null) {
                commands.addCommand(command);
            }
        }
        
        for (final AgentVmInfo left : infos.values()) {
            boolean found = false;
            for (VirtualMachineGuru vmGuru : _vmGurus.values()) {
                VMInstanceVO vm = vmGuru.findByName(left.name);
                if (vm != null) {
                    found = true;
                    HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                    if(hvGuru.trackVmHostChange()) {
                        Command command = compareState(hostId, vm, left, true, true);
                        if (command != null) {
                            commands.addCommand(command);
                        }
                    } else {
                        s_logger.warn("Stopping a VM, VM " + left.name + " migrate from Host " + vm.getHostId() + " to Host " + hostId );
                        commands.addCommand(cleanup(left.name));
                    }
                    break;
                }
            }
            if ( ! found ) {
                s_logger.warn("Stopping a VM that we have no record of : " + left.name);
                commands.addCommand(cleanup(left.name));
            }
        }

        return commands;
    }

    public Commands deltaHostSync(long hostId, Map newStates) {
        Map states = convertDeltaToInfos(newStates);
        Commands commands = new Commands(OnError.Continue);

        for (Map.Entry entry : states.entrySet()) {
            AgentVmInfo info = entry.getValue();

            VMInstanceVO vm = info.vm;

            Command command = null;
            if (vm != null) {
                HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                command = compareState(hostId, vm, info, false, hvGuru.trackVmHostChange());
            } else {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Cleaning up a VM that is no longer found: " + info.name);
                }
                command = cleanup(info.name);
            }

            if (command != null) {
                commands.addCommand(command);
            }
        }

        return commands;
    }



    public void deltaSync(Map> newStates) {
        Map states = convertToInfos(newStates);

        for (Map.Entry entry : states.entrySet()) {
            AgentVmInfo info = entry.getValue();
            VMInstanceVO vm = info.vm;
            Command command = null;
            if (vm != null) {
                Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
                long hId = host.getId();

                HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                command = compareState(hId, vm, info, false, hvGuru.trackVmHostChange());
            } else {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Cleaning up a VM that is no longer found : " + info.name);
                }
                command = cleanup(info.name);
            }
            if (command != null){
                try {
                    Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
                    if (host != null){
                        Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
                        if (!answer.getResult()) {
                            s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                        }
                    }
                } catch (Exception e) {
                    s_logger.warn("Unable to stop a VM due to " + e.getMessage());
                }
            }
        }
    }


    public void fullSync(final long clusterId, Map> newStates) {
    	if (newStates==null)return;
        Map infos = convertToInfos(newStates);
        Set set_vms = Collections.synchronizedSet(new HashSet());
        set_vms.addAll(_vmDao.listByClusterId(clusterId));
        set_vms.addAll(_vmDao.listLHByClusterId(clusterId));

        for (VMInstanceVO vm : set_vms) {
            if (vm.isRemoved() || vm.getState() == State.Destroyed  || vm.getState() == State.Expunging) continue;
            AgentVmInfo info =  infos.remove(vm.getId());
            VMInstanceVO castedVm = null;
            if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting))  
            		||  (info != null && (info.state == State.Running && vm.getState() == State.Starting))) 
            {
            	s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " +  (info == null ? "Stopped" : "Running") + " on agent");
                info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
           		
                // Bug 13850- grab outstanding work item if any for this VM state so that we mark it as DONE after we change VM state, else it will remain pending
                ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
                if (work != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Found an outstanding work item for this vm " + vm + " in state:" + vm.getState() + ", work id:" + work.getId());
                    }
                vm.setState(State.Running); // set it as running and let HA take care of it
           		_vmDao.persist(vm);
           		
                if (work != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Updating outstanding work item to Done, id:" + work.getId());
                    }
                    work.setStep(Step.Done);
                    _workDao.update(work.getId(), work);
                }
           		
                castedVm = info.guru.findById(vm.getId());
                try {
                    Host host = _hostDao.findByGuid(info.getHostUuid());
                    long hostId = host == null ? (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId()) : host.getId();
                    HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
                    Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
                    if (command != null){
                        Answer answer = _agentMgr.send(hostId, command);
                        if (!answer.getResult()) {
                            s_logger.warn("Failed to update state of the VM due to " + answer.getDetails());
                        }
                    }
                } catch (Exception e) {
                    s_logger.warn("Unable to update state of the VM due to exception " + e.getMessage());
                    e.printStackTrace();
                }
            }
            else if (info != null && (vm.getState() == State.Stopped || vm.getState() == State.Stopping)) {
            	 Host host = _hostDao.findByGuid(info.getHostUuid());
                 if (host != null){
                    s_logger.warn("Stopping a VM which is stopped/stopping " + info.name);
                    vm.setState(State.Stopped); // set it as stop and clear it from host
                    vm.setHostId(null);
                    _vmDao.persist(vm);
                     try {
	                     Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
	                     if (!answer.getResult()) {
	                         s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
	                     }
                     }
                     catch (Exception e) {
                         s_logger.warn("Unable to stop a VM due to " + e.getMessage());
                     }
                 }
            }
            else
            // host id can change
	        if (info != null && vm.getState() == State.Running){
	           // check for host id changes
	           Host host = _hostDao.findByGuid(info.getHostUuid());
	            if (host != null && (vm.getHostId() == null || host.getId() != vm.getHostId())){
    	        	s_logger.info("Found vm " + vm.getInstanceName() + " with inconsistent host in db, new host is " +  host.getId());
        			try {
						stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, host.getId());
					} catch (NoTransitionException e) {
						s_logger.warn(e.getMessage());
					}
        		}
            }
             /* else if(info == null && vm.getState() == State.Stopping) { //Handling CS-13376
                        s_logger.warn("Marking the VM as Stopped as it was still stopping on the CS" +vm.getName());
                        vm.setState(State.Stopped); // Setting the VM as stopped on the DB and clearing it from the host
                        vm.setLastHostId(vm.getHostId());
                        vm.setHostId(null);
                        _vmDao.persist(vm);
                 }*/
        }

        for (final AgentVmInfo left : infos.values()) {
        	if (VirtualMachineName.isValidVmName(left.name)) continue;  // if the vm follows cloudstack naming ignore it for stopping
            try {
                Host host = _hostDao.findByGuid(left.getHostUuid());
                if (host != null){
                    s_logger.warn("Stopping a VM which we do not have any record of " + left.name);
                    Answer answer = _agentMgr.send(host.getId(), cleanup(left.name));
                    if (!answer.getResult()) {
                        s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                    }
                }
            } else {
            } catch (Exception e) {
                s_logger.warn("Unable to stop a VM due to " + e.getMessage());
            }
        }

    }



    protected Map convertToInfos(final Map> newStates) {
        final HashMap map = new HashMap();
        if (newStates == null) {
            return map;
        }
        Collection> vmGurus = _vmGurus.values();
        boolean is_alien_vm = true;
        long alien_vm_count = -1;
        for (Map.Entry> entry : newStates.entrySet()) {
        	is_alien_vm = true;
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();
                VMInstanceVO vm = vmGuru.findByName(name);
                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().second(), entry.getValue().first()));
                    is_alien_vm = false;
                    break;
                }
                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue().second(), entry.getValue().first()));
                    is_alien_vm = false;
                    break;
                }
            }
            // alien VMs
            if (is_alien_vm){
            	map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, null, entry.getValue().second(), entry.getValue().first()));
            	s_logger.warn("Found an alien VM " + entry.getKey());
            }
        }
        return map;
    }

        } catch (NoTransitionException e1) {
    protected Map convertToInfos(StartupRoutingCommand cmd) { 
        final Map states = cmd.getVmStates();
        final HashMap map = new HashMap();
        if (states == null) {
            return map;
        }
        Collection> vmGurus = _vmGurus.values();

        for (Map.Entry entry : states.entrySet()) {
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();
                VMInstanceVO vm = vmGuru.findByName(name);
                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().getState(), entry.getValue().getHost() ));
                    break;
                }
                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue().getState(), entry.getValue().getHost() ));
                    break;
                }
            }
        }

        return map;
    }

    protected Map convertDeltaToInfos(final Map states) {
        final HashMap map = new HashMap();

        if (states == null) {
            return map;
        }

        Collection> vmGurus = _vmGurus.values();

        for (Map.Entry entry : states.entrySet()) {
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();

                VMInstanceVO vm = vmGuru.findByName(name);

                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue()));
                    break;
                }

                    //
                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue()));
                    break;
                }
            }
        }

        return map;
    }



    /**
     * compareState does as its name suggests and compares the states between
     * management server and agent. It returns whether something should be
     * cleaned up
     * 
     */
    protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) {
        State agentState = info.state;
        final String agentName = info.name;
        final State serverState = vm.getState();
        final String serverName = vm.getInstanceName();

        Command command = null;
        s_logger.debug("VM " + serverName + ": cs state = " + serverState + " and realState = " + agentState);
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("VM " + serverName + ": cs state = " + serverState + " and realState = " + agentState);
        }

        if (agentState == State.Error) {
            agentState = State.Stopped;

            short alertType = AlertManager.ALERT_TYPE_USERVM;
            if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER;
            } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY;
            } else if (VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_SSVM;
            }

            HostPodVO podVO = _podDao.findById(vm.getPodIdToDeployIn());
            DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterIdToDeployIn());
            HostVO hostVO = _hostDao.findById(vm.getHostId());

            String hostDesc = "name: " + hostVO.getName() + " (id:" + hostVO.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();
            _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc
                    + " due to storage failure", "Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped due to storage failure.");
        }

        if (trackExternalChange) {
            if (serverState == State.Starting) {
                if (vm.getHostId() != null && vm.getHostId() != hostId) {
                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
                            + vm.getInstanceName());
                    return null;
                }
            }
            if (vm.getHostId() == null || hostId != vm.getHostId()) {
                try {
                    stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
                } catch (NoTransitionException e) {
                }
            }
        }

        // during VM migration time, don't sync state will agent status update
        if (serverState == State.Migrating) {
            s_logger.debug("Skipping vm in migrating state: " + vm);
            return null;
        }

        if (trackExternalChange) {
            if (serverState == State.Starting) {
                if (vm.getHostId() != null && vm.getHostId() != hostId) {
                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
                            + vm.getInstanceName());
                    return null;
                }
            }

            if (serverState == State.Running) {
                try {
                    // we had a bug that sometimes VM may be at Running State
                    // but host_id is null, we will cover it here.
                    // means that when CloudStack DB lost of host information,
                    // we will heal it with the info reported from host
                    //
                    if (vm.getHostId() == null || hostId != vm.getHostId()) {
                        if (s_logger.isDebugEnabled()) {
                            s_logger.debug("detected host change when VM " + vm + " is at running state, VM could be live-migrated externally from host " + vm.getHostId() + " to host " + hostId);
                        }

                        stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
                    }
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
            }
        }

        if (agentState == serverState) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Both states are " + agentState + " for " + vm);
            }
            assert (agentState == State.Stopped || agentState == State.Running) : "If the states we send up is changed, this must be changed.";
            if (agentState == State.Running) {
                try {
                    stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, hostId);
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
                // FIXME: What if someone comes in and sets it to stopping? Then
                // what?
                return null;
            }

            s_logger.debug("State matches but the agent said stopped so let's send a cleanup command anyways.");
            return cleanup(agentName);
        }

        if (agentState == State.Shutdowned) {
            if (serverState == State.Running || serverState == State.Starting || serverState == State.Stopping) {
                try {
                    advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                } catch (AgentUnavailableException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                } catch (OperationTimedoutException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                } catch (ConcurrentOperationException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                }
            } else {
                s_logger.debug("Sending cleanup to a shutdowned vm: " + agentName);
                command = cleanup(agentName);
            }
        } else if (agentState == State.Stopped) {
            // This state means the VM on the agent was detected previously
            // and now is gone. This is slightly different than if the VM
            // was never completed but we still send down a Stop Command
            // to ensure there's cleanup.
            if (serverState == State.Running) {
                // Our records showed that it should be running so let's restart
                // it.
                _haMgr.scheduleRestart(vm, false);
            } else if (serverState == State.Stopping) {
                _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop);
                s_logger.debug("Scheduling a check stop for VM in stopping mode: " + vm);
            } else if (serverState == State.Starting) {
                s_logger.debug("Ignoring VM in starting mode: " + vm.getInstanceName());
                _haMgr.scheduleRestart(vm, false);
            }
            command = cleanup(agentName);
        } else if (agentState == State.Running) {
            if (serverState == State.Starting) {
                if (fullSync) {
                    try {
                        ensureVmRunningContext(hostId, vm, Event.AgentReportRunning);
                    } catch (OperationTimedoutException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    } catch (ResourceUnavailableException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    }catch (InsufficientAddressCapacityException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    }catch (NoTransitionException e) {
                        s_logger.warn(e.getMessage());
                    }
                }
            } else if (serverState == State.Stopping) {
                s_logger.debug("Scheduling a stop command for " + vm);
                _haMgr.scheduleStop(vm, hostId, WorkType.Stop);
            } else {
                s_logger.debug("server VM state " + serverState + " does not meet expectation of a running VM report from agent");

                // just be careful not to stop VM for things we don't handle
                // command = cleanup(agentName);
            }
        }
        return command;
    }

    private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException, InsufficientAddressCapacityException {
        VirtualMachineGuru vmGuru = getVmGuru(vm);

        s_logger.debug("VM state is starting on full sync so updating it to running");
        vm = findByIdAndType(vm.getType(), vm.getId());

        // grab outstanding work item if any
        ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found an outstanding work item for this vm " + vm + " in state:" + vm.getState() + ", work id:" + work.getId());
            }
        }

        try {
            stateTransitTo(vm, cause, hostId);
            s_logger.warn(e1.getMessage());
        }

        s_logger.debug("VM's " + vm + " state is starting on full sync so updating it to Running");
        vm = vmGuru.findById(vm.getId()); // this should ensure vm has the most
        // up to date info

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        List nics = _nicsDao.listByVmId(profile.getId());
        for (NicVO nic : nics) {
            Network network = _networkMgr.getNetwork(nic.getNetworkId());
            NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, 
                    _networkMgr.isSecurityGroupSupportedInNetwork(network), _networkMgr.getNetworkTag(profile.getHypervisorType(), network));
            profile.addNic(nicProfile);
        }

        Commands cmds = new Commands(OnError.Stop);
        s_logger.debug("Finalizing commands that need to be send to complete Start process for the vm " + vm);

        if (vmGuru.finalizeCommandsOnStart(cmds, profile)) {
            if (cmds.size() != 0) {
                _agentMgr.send(vm.getHostId(), cmds);
            }

            if (vmGuru.finalizeStart(profile, vm.getHostId(), cmds, null)) {
                stateTransitTo(vm, cause, vm.getHostId());
            } else {
                s_logger.error("Unable to finish finialization for running vm: " + vm);
            }
        } else {
            s_logger.error("Unable to finalize commands on start for vm: " + vm);
        }

        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Updating outstanding work item to Done, id:" + work.getId());
            }
            work.setStep(Step.Done);
            _workDao.update(work.getId(), work);
        }
    }

    @Override
    public boolean isRecurring() {
        return true;
    }

    @Override

    public boolean processAnswers(long agentId, long seq, Answer[] answers) {
        for (final Answer answer : answers) {
            if (answer instanceof ClusterSyncAnswer) {
                ClusterSyncAnswer hs = (ClusterSyncAnswer) answer;
                if (!hs.isExceuted()){
                    deltaSync(hs.getNewStates());
                    hs.setExecuted();
                }
            }
        }
        return true;
    }

    @Override
    public boolean processTimeout(long agentId, long seq) {
        return true;
    }

    @Override
    public int getTimeout() {
        return -1;
    }

    @Override
    public boolean processCommands(long agentId, long seq, Command[] cmds) {
        boolean processed = false;
        for (Command cmd : cmds) {
            if (cmd instanceof PingRoutingCommand) {
                PingRoutingCommand ping = (PingRoutingCommand) cmd;
                if (ping.getNewStates() != null && ping.getNewStates().size() > 0) {
                    Commands commands = deltaHostSync(agentId, ping.getNewStates());
                    if (commands.size() > 0) {
                        try {
                            _agentMgr.send(agentId, commands, this);
                        } catch (final AgentUnavailableException e) {
                            s_logger.warn("Agent is now unavailable", e);
                        }
                    }
                }
                processed = true;
            }
        }
        return processed;
    }

    @Override
    public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
        return null;
    }

    public boolean processDisconnect(long agentId, Status state) {
        return true;
    }

    @Override
    public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
        if (!(cmd instanceof StartupRoutingCommand)) {
            return;
        }

        if (forRebalance) {
            s_logger.debug("Not processing listener " + this + " as connect happens on rebalance process");
            return;
        }

        if (forRebalance) {
            s_logger.debug("Not processing listener " + this + " as connect happens on rebalance process");
            return;
        }

        Long clusterId = agent.getClusterId();
        long agentId = agent.getId();
        if (agent.getHypervisorType() == HypervisorType.XenServer) { // only for Xen
        	StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
        	HashMap> allStates = startup.getClusterVMStateChanges();
        	if (allStates != null){
        		this.fullSync(clusterId, allStates);
        	}
        	
        	// initiate the cron job
            ClusterSyncCommand syncCmd = new ClusterSyncCommand(Integer.parseInt(Config.ClusterDeltaSyncInterval.getDefaultValue()), clusterId);
            try {
                long seq_no = _agentMgr.send(agentId, new Commands(syncCmd), this);
                s_logger.debug("Cluster VM sync started with jobid " + seq_no);
            } catch (AgentUnavailableException e) {
                s_logger.fatal("The Cluster VM sync process failed for cluster id " + clusterId + " with ", e);
            }
        }
        else { // for others KVM and VMWare 
            StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
            Commands commands = fullHostSync(agentId, startup);

            if (commands.size() > 0) {
                s_logger.debug("Sending clean commands to the agent");

                try {
                    boolean error = false;
                    Answer[] answers = _agentMgr.send(agentId, commands);
                    for (Answer answer : answers) {
                        if (!answer.getResult()) {
                            s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                            error = true;
                        }
                    }
                    if (error) {
                        throw new ConnectionException(true, "Unable to stop VMs");
                    }
                } catch (final AgentUnavailableException e) {
                    s_logger.warn("Agent is unavailable now", e);
                    throw new ConnectionException(true, "Unable to sync", e);
                } catch (final OperationTimedoutException e) {
                    s_logger.warn("Agent is unavailable now", e);
                    throw new ConnectionException(true, "Unable to sync", e);
                }
            }

        }
    }

    protected class TransitionTask implements Runnable {
        @Override
        public void run() {
            GlobalLock lock = GlobalLock.getInternLock("TransitionChecking");
            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 {
                lock.addRef();
                List instances = _vmDao.findVMInTransition(new Date(new Date().getTime() - (_operationTimeout * 1000)), State.Starting, State.Stopping);
                for (VMInstanceVO instance : instances) {
                    State state = instance.getState();
                    if (state == State.Stopping) {
                        _haMgr.scheduleStop(instance, instance.getHostId(), WorkType.CheckStop);
                    } else if (state == State.Starting) {
                        _haMgr.scheduleRestart(instance, true);
                    }
                }
            } catch (Exception e) {
                s_logger.warn("Caught the following exception on transition checking", e);
            } finally {
                StackMaid.current().exitCleanup();
                lock.unlock();
            }
        }
    }

    protected class AgentVmInfo {
        public String name;
        public State state;
        public String hostUuid;
        public VMInstanceVO vm;
        public VirtualMachineGuru guru;

        @SuppressWarnings("unchecked")
        public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state, String host) {
            this.name = name;
            this.state = state;
            this.vm = vm;
            this.guru = (VirtualMachineGuru) guru;
            this.hostUuid = host;
        }

        public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state) {
            this(name, guru, vm, state, null);
        }

        public String getHostUuid() {
            return hostUuid;
        }
    }

    @Override
    public VMInstanceVO findById(long vmId) {
        return _vmDao.findById(vmId);
    }
    
    @Override
    public void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId) {
        ServiceOfferingVO newServiceOffering = _offeringDao.findById(newServiceOfferingId);
        if (newServiceOffering == null) {
            throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOfferingId);
        }

        // Check that the VM is stopped
        if (!vmInstance.getState().equals(State.Stopped)) {
            s_logger.warn("Unable to upgrade virtual machine " + vmInstance.toString() + " in state " + vmInstance.getState());
            throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vmInstance.toString() + " " +
            		"in state " + vmInstance.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 (vmInstance.getServiceOfferingId() == newServiceOffering.getId()) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Not upgrading vm " + vmInstance.toString() + " since it already has the requested " +
                		"service offering (" + newServiceOffering.getName() + ")");
            }

            throw new InvalidParameterValueException("Not upgrading vm " + vmInstance.toString() + " since it already " +
            		"has the requested service offering (" + newServiceOffering.getName() + ")");
        }

        ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId());

        // Check that the service offering being upgraded to has the same Guest IP type as the VM's current service offering
        // NOTE: With the new network refactoring in 2.2, we shouldn't need the check for same guest IP type anymore.
        /*
         * 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()) {
import com.cloud.hypervisor.HypervisorGuruManager;
            throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vmInstance.toString()
                    + ", cannot switch between local storage and shared storage service offerings.  Current offering " +
                    "useLocalStorage=" + currentServiceOffering.getUseLocalStorage()
                    + ", target offering useLocalStorage=" + newServiceOffering.getUseLocalStorage());
        }
        
        // if vm is a system vm, check if it is a system service offering, if yes return with error as it cannot be used for user vms
        if (currentServiceOffering.getSystemUse() != newServiceOffering.getSystemUse()) {
            throw new InvalidParameterValueException("isSystem property is different for current service offering and new service offering");
        }

        // Check that there are enough resources to upgrade the service offering
        if (!isVirtualMachineUpgradable(vmInstance, 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);
        }
    }
    
    @Override
    public boolean upgradeVmDb(long vmId, long serviceOfferingId) {
        VMInstanceVO vmForUpdate = _vmDao.createForUpdate();
        vmForUpdate.setServiceOfferingId(serviceOfferingId);
        ServiceOffering newSvcOff = _configMgr.getServiceOffering(serviceOfferingId);
        vmForUpdate.setHaEnabled(newSvcOff.getOfferHA());
        }
        vmForUpdate.setLimitCpuUse(newSvcOff.getLimitCpuUse());
        vmForUpdate.setServiceOfferingId(newSvcOff.getId());
        return _vmDao.update(vmId, vmForUpdate);
    }
    
    @Override
    public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, 
                                                    ResourceUnavailableException, InsufficientCapacityException {
        
        s_logger.debug("Adding vm " + vm + " to network " + network);
        VMInstanceVO vmVO = _vmDao.findById(vm.getId());
        ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), 
                _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
        
        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, 
                null, null, null);
        
        DataCenter dc = _configMgr.getZone(network.getDataCenterId());
        Host host = _hostDao.findById(vm.getHostId()); 
        DeployDestination dest = new DeployDestination(dc, null, null, host);
        
        //check vm state
        if (vm.getState() == State.Running) {
            //1) allocate and prepare nic
            NicProfile nic = _networkMgr.createNicForVm(network, requested, context, vmProfile, true);
            
            //2) Convert vmProfile to vmTO
            HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
            VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
            
            //3) Convert nicProfile to NicTO
            NicTO nicTO = toNicTO(nic, vmProfile.getVirtualMachine().getHypervisorType());
            
            //4) plug the nic to the vm
            VirtualMachineGuru vmGuru = getVmGuru(vmVO);
            
            s_logger.debug("Plugging nic for vm " + vm + " in network " + network);
            if (vmGuru.plugNic(network, nicTO, vmTO, context, dest)) {
                s_logger.debug("Nic is plugged successfully for vm " + vm + " in network " + network + ". Vm  is a part of network now");
                return nic;
                s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network);
                return null;
            }
        } else if (vm.getState() == State.Stopped) {
            //1) allocate nic
            return _networkMgr.createNicForVm(network, requested, context, vmProfile, false);
        } else {
            s_logger.warn("Unable to add vm " + vm + " to network  " + network);
            throw new ResourceUnavailableException("Unable to add vm " + vm + " to network, is not in the right state",
                    DataCenter.class, vm.getDataCenterIdToDeployIn());
        }
    }


    @Override
    public NicTO toNicTO(NicProfile nic, HypervisorType hypervisorType) {
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(hypervisorType);
        
        NicTO nicTO = hvGuru.toNicTO(nic);
        return nicTO;
    }
    
    @Override
    public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException {
        VMInstanceVO vmVO = _vmDao.findById(vm.getId());
        ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), 
                _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
        
        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, 
                null, null, null);
        
        DataCenter dc = _configMgr.getZone(network.getDataCenterId());
        Host host = _hostDao.findById(vm.getHostId()); 
        DeployDestination dest = new DeployDestination(dc, null, null, host);
        VirtualMachineGuru vmGuru = getVmGuru(vmVO);
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
        VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
        
        Nic nic = null;
        
        if (broadcastUri != null) {
            nic = _nicsDao.findByInstanceIdNetworkIdAndBroadcastUri(network.getId(), vm.getId(), broadcastUri.toString());
        } else {
            nic = _networkMgr.getNicInNetwork(vm.getId(), network.getId());
        }
        
        NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), 
                _networkMgr.getNetworkRate(network.getId(), vm.getId()), 
                _networkMgr.isSecurityGroupSupportedInNetwork(network), 
                _networkMgr.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
        
        //1) Unplug the nic
        NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType());
        s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network);
        boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest);
        if (result) {
            s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
        } else {
            s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
            return false;
        }
        
        //2) Release the nic
        _networkMgr.releaseNic(vmProfile, nic);
        s_logger.debug("Successfully released nic " + nic +  "for vm " + vm);
        
        //3) Remove the nic
        _networkMgr.removeNic(vmProfile, nic);
        return result;
    }
   
}
=======
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.vm;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.ejb.Local;
import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.OnError;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.agent.api.ClusterSyncAnswer;
import com.cloud.agent.api.ClusterSyncCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.Commands;
import com.cloud.agent.manager.allocator.HostAllocator;
import com.cloud.alert.AlertManager;
import com.cloud.capacity.CapacityManager;
import com.cloud.cluster.ClusterManager;
import com.cloud.cluster.StackMaid;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ManagementServerException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.VirtualMachineMigrationException;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.ha.HighAvailabilityManager.WorkType;
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.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.resource.ResourceManager;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.Journal;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.ItWorkVO.Step;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

@Local(value = VirtualMachineManager.class)
public class VirtualMachineManagerImpl implements VirtualMachineManager, Listener {
    private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class);

    String _name;
    @Inject
    protected StorageManager _storageMgr;
    @Inject
    protected NetworkManager _networkMgr;
    @Inject
    protected AgentManager _agentMgr;
    @Inject
    protected VMInstanceDao _vmDao;
    @Inject
    protected ServiceOfferingDao _offeringDao;
    @Inject
    protected VMTemplateDao _templateDao;
    @Inject
    protected UserDao _userDao;
    @Inject
    protected AccountDao _accountDao;
    @Inject
    protected DomainDao _domainDao;
    @Inject
    protected ClusterManager _clusterMgr;
    @Inject
    protected ItWorkDao _workDao;
    @Inject
    protected UserVmDao _userVmDao;
    @Inject
    protected DomainRouterDao _routerDao;
    @Inject
    protected ConsoleProxyDao _consoleDao;
    @Inject
    protected SecondaryStorageVmDao _secondaryDao;
    @Inject
    protected NicDao _nicsDao;
    @Inject
    protected AccountManager _accountMgr;
    @Inject
    protected HostDao _hostDao;
    @Inject
    protected AlertManager _alertMgr;
    @Inject
    protected GuestOSCategoryDao _guestOsCategoryDao;
    @Inject
    protected GuestOSDao _guestOsDao;
    @Inject
    protected VolumeDao _volsDao;
    @Inject
    protected ConsoleProxyManager _consoleProxyMgr;
    @Inject
    protected ConfigurationManager _configMgr;
    @Inject
    protected CapacityManager _capacityMgr;
    @Inject
    protected HighAvailabilityManager _haMgr;
    @Inject
    protected HostPodDao _podDao;
    @Inject
    protected DataCenterDao _dcDao;
    @Inject
    protected StoragePoolDao _storagePoolDao;
    @Inject
    protected HypervisorGuruManager _hvGuruMgr;
    @Inject
    protected NetworkDao _networkDao;

    @Inject(adapter = DeploymentPlanner.class)
    protected Adapters _planners;

    @Inject(adapter = HostAllocator.class)
    protected Adapters _hostAllocators;

    @Inject
    protected ResourceManager _resourceMgr;

    Map> _vmGurus = new HashMap>();
    protected StateMachine2 _stateMachine;

    ScheduledExecutorService _executor = null;
    protected int _operationTimeout;

    protected int _retry;
    protected long _nodeId;
    protected long _cleanupWait;
    protected long _cleanupInterval;
    protected long _cancelWait;
    protected long _opWaitInterval;
    protected int _lockStateRetry;
    protected boolean _forceStop;

    @Override
    public  void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) {
        synchronized (_vmGurus) {
            _vmGurus.put(type, guru);
        }
    }

    @Override
    @DB
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Pair rootDiskOffering,
            List> dataDiskOfferings, List> networks, Map params, DeploymentPlan plan,
            HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocating entries for VM: " + vm);
        }

        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, params);

        vm.setDataCenterId(plan.getDataCenterId());
        if (plan.getPodId() != null) {
            vm.setPodId(plan.getPodId());
        }
        assert (plan.getClusterId() == null && plan.getPoolId() == null) : "We currently don't support cluster and pool preset yet";

        @SuppressWarnings("unchecked")
        VirtualMachineGuru guru = (VirtualMachineGuru) _vmGurus.get(vm.getType());

        Transaction txn = Transaction.currentTxn();
        txn.start();
        vm = guru.persist(vm);

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocating nics for " + vm);
        }
        
        try {
            _networkMgr.allocate(vmProfile, networks);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Concurrent operation while trying to allocate resources for the VM", e);
        }

        if (dataDiskOfferings == null) {
            dataDiskOfferings = new ArrayList>(0);
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocaing disks for " + vm);
        }

        if (template.getFormat() == ImageFormat.ISO) {
            if (vo == null) {
            _storageMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner);
        } else if (template.getFormat() == ImageFormat.BAREMETAL) {
            // Do nothing
        } else {
            _storageMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
        }

        for (Pair offering : dataDiskOfferings) {
            _storageMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
        }

        txn.commit();
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocation completed for VM: " + vm);
        }

        return vm;
    }

    @Override
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, Pair dataDiskOffering,
            List> networks, DeploymentPlan plan, HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        List> diskOfferings = new ArrayList>(1);
        if (dataDiskOffering != null) {
            diskOfferings.add(dataDiskOffering);
        }
        return allocate(vm, template, serviceOffering, new Pair(serviceOffering, rootSize), diskOfferings, networks, null, plan, hyperType, owner);
    }

    @Override
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, List> networks, DeploymentPlan plan,
            HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        return allocate(vm, template, serviceOffering, new Pair(serviceOffering, null), null, networks, null, plan, hyperType, owner);
    }

    @SuppressWarnings("unchecked")
    private  VirtualMachineGuru getVmGuru(T vm) {

        return (VirtualMachineGuru) _vmGurus.get(vm.getType());
    }

    @SuppressWarnings("unchecked")
    private  VirtualMachineGuru getBareMetalVmGuru(T vm) {
        return (VirtualMachineGuru) _vmGurus.get(VirtualMachine.Type.UserBareMetal);
    }

    @Override
    public  boolean expunge(T vm, User caller, Account account) throws ResourceUnavailableException {
        try {
            if (advanceExpunge(vm, caller, account)) {
                // Mark vms as removed
                remove(vm, caller, account);
                return true;
            } else {
                s_logger.info("Did not expunge " + vm);
                return false;
            }
        } catch (OperationTimedoutException e) {
            throw new CloudRuntimeException("Operation timed out", e);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Concurrent operation ", e);
        }
    }

    @Override
    public  boolean advanceExpunge(T vm, User caller, Account account) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        if (vm == null || vm.getRemoved() != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vm);
            }
            return true;
        }

        if (!this.advanceStop(vm, false, caller, account)) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to stop the VM so we can't expunge it.");
            }
        }

        try {
            if (!stateTransitTo(vm, VirtualMachine.Event.ExpungeOperation, vm.getHostId())) {
                s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
                return false;
            }
        } catch (NoTransitionException e) {

            s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
            return false;
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Destroying vm " + vm);
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        s_logger.debug("Cleaning up NICS");
        _networkMgr.cleanupNics(profile);
        // Clean up volumes based on the vm's instance id
        _storageMgr.cleanupVolumes(vm.getId());

        VirtualMachineGuru guru = getVmGuru(vm);
        guru.finalizeExpunge(vm);

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Expunged " + vm);
        }

        return true;
    }

    @Override
    public boolean start() {
        _executor.scheduleAtFixedRate(new CleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS);
        cancelWorkItems(_nodeId);
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean configure(String name, Map xmlParams) throws ConfigurationException {
        _name = name;

        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
        Map params = configDao.getConfiguration(xmlParams);

        _retry = NumbersUtil.parseInt(params.get(Config.StartRetry.key()), 10);

        ReservationContextImpl.setComponents(_userDao, _domainDao, _accountDao);
        VirtualMachineProfileImpl.setComponents(_offeringDao, _templateDao, _accountDao);
        _cancelWait = NumbersUtil.parseLong(params.get(Config.VmOpCancelInterval.key()), 3600);
        _cleanupWait = NumbersUtil.parseLong(params.get(Config.VmOpCleanupWait.key()), 3600);
        _cleanupInterval = NumbersUtil.parseLong(params.get(Config.VmOpCleanupInterval.key()), 86400) * 1000;
        _opWaitInterval = NumbersUtil.parseLong(params.get(Config.VmOpWaitInterval.key()), 120) * 1000;
        _lockStateRetry = NumbersUtil.parseInt(params.get(Config.VmOpLockStateRetry.key()), 5);
        _operationTimeout = NumbersUtil.parseInt(params.get(Config.Wait.key()), 1800) * 2;
        _forceStop = Boolean.parseBoolean(params.get(Config.VmDestroyForcestop.key()));

        _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vm-Operations-Cleanup"));
        _nodeId = _clusterMgr.getManagementNodeId();

        _agentMgr.registerForHostEvents(this, true, true, true);

        return true;
    }

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

    protected VirtualMachineManagerImpl() {
        setStateMachine();
    }

    @Override
    public  T start(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException {
        return start(vm, params, caller, account, null);
    }

    @Override
    public  T start(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException,
    ResourceUnavailableException {
        try {
            return advanceStart(vm, params, caller, account, planToDeploy);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to start a VM due to concurrent operation", e);
        }
    }

    protected boolean checkWorkItems(VMInstanceVO vm, State state) throws ConcurrentOperationException {
        while (true) {
            ItWorkVO vo = _workDao.findByOutstandingWork(vm.getId(), state);
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to find work for VM: " + vm + " and state: " + state);
                }
                return true;
            }

            if (vo.getStep() == Step.Done) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Work for " + vm + " is " + vo.getStep());
                }
                return true;
            }

            if (vo.getSecondsTaskIsInactive() > _cancelWait) {
                s_logger.warn("The task item for vm " + vm + " has been inactive for " + vo.getSecondsTaskIsInactive());
                return false;
            }

            try {
                Thread.sleep(_opWaitInterval);
            } catch (InterruptedException e) {
                s_logger.info("Waiting for " + vm + " but is interrupted");
                throw new ConcurrentOperationException("Waiting for " + vm + " but is interrupted");
            }
            s_logger.debug("Waiting some more to make sure there's no activity on " + vm);
        }

    }

    @DB
    protected  Ternary changeToStartState(VirtualMachineGuru vmGuru, T vm, User caller, Account account)
            throws ConcurrentOperationException {
        long vmId = vm.getId();

        ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getType(), vm.getId());
        int retry = _lockStateRetry;
        while (retry-- != 0) {
            Transaction txn = Transaction.currentTxn();
            Ternary result = null;
            txn.start();
            try {
                Journal journal = new Journal.LogJournal("Creating " + vm, s_logger);
                work = _workDao.persist(work);

        }
                ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account);

                if (stateTransitTo(vm, Event.StartRequested, null, work.getId())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId());
                    }
                    result = new Ternary(vmGuru.findById(vmId), context, work);
                    txn.commit();
                    return result;
                }
            } catch (NoTransitionException e) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to transition into Starting state due to " + e.getMessage());
                }
            } finally {
                if (result == null) {
                    txn.rollback();
                }
            }

            VMInstanceVO instance = _vmDao.findById(vmId);
            if (instance == null) {
                throw new ConcurrentOperationException("Unable to acquire lock on " + vm);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Determining why we're unable to update the state to Starting for " + instance + ".  Retry=" + retry);
            }

            State state = instance.getState();
            if (state == State.Running) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("VM is already started: " + vm);
                }
                return null;
            }

            if (state.isTransitional()) {
                if (!checkWorkItems(vm, state)) {
                    throw new ConcurrentOperationException("There are concurrent operations on " + vm);
                } else {
                    continue;
                }
            }

            if (state != State.Stopped) {
                s_logger.debug("VM " + vm + " is not in a state to be started: " + state);
                return null;
            }
        }

        throw new ConcurrentOperationException("Unable to change the state of " + vm);
    }

    protected  boolean changeState(T vm, Event event, Long hostId, ItWorkVO work, Step step) throws NoTransitionException {
        // FIXME: We should do this better.
        Step previousStep = work.getStep();
        _workDao.updateStep(work, step);
        boolean result = false;
        try {
            result = stateTransitTo(vm, event, hostId);
            return result;
        } finally {
            if (!result) {
                _workDao.updateStep(work, previousStep);
            }
        }
    }

    @Override
    public  T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException,
    ConcurrentOperationException, ResourceUnavailableException {
        return advanceStart(vm, params, caller, account, null);
    }

    @Override
    public  T advanceStart(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy)
            throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
        long vmId = vm.getId();
        VirtualMachineGuru vmGuru;
        if (vm.getHypervisorType() == HypervisorType.BareMetal) {
            vmGuru = getBareMetalVmGuru(vm);
        } else {
            vmGuru = getVmGuru(vm);
        }

        vm = vmGuru.findById(vm.getId());
        Ternary start = changeToStartState(vmGuru, vm, caller, account);
        if (start == null) {
            return vmGuru.findById(vmId);
        vm = start.first();
        ReservationContext ctx = start.second();
        ItWorkVO work = start.third();

        T startedVm = null;
        ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId());
        VMTemplateVO template = _templateDao.findById(vm.getTemplateId());

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Trying to deploy VM, vm has dcId: " + vm.getDataCenterIdToDeployIn() + " and podId: " + vm.getPodIdToDeployIn());
        }
        DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), null, null, null, null, ctx);
        if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("advanceStart: DeploymentPlan is provided, using dcId:" + planToDeploy.getDataCenterId() + ", podId: " + planToDeploy.getPodId() + ", clusterId: "
                        + planToDeploy.getClusterId() + ", hostId: " + planToDeploy.getHostId() + ", poolId: " + planToDeploy.getPoolId());
            }
            plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId(), ctx);
        }

        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());

        boolean canRetry = true;
        try {
            Journal journal = start.second().getJournal();

            ExcludeList avoids = null;
            if (planToDeploy != null) {
                avoids = planToDeploy.getAvoids();
            }
            if (avoids == null) {
                avoids = new ExcludeList();
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", clusters: " + avoids.getClustersToAvoid() + ", hosts: " + avoids.getHostsToAvoid());
            }


            boolean planChangedByVolume = false;
            boolean reuseVolume = true;
            DataCenterDeployment originalPlan = plan;
            int retry = _retry;
            boolean recreate = false;
            while (retry-- != 0) { // It's != so that it can match -1.

                if(reuseVolume){
                    // edit plan if this vm's ROOT volume is in READY state already
                    List vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
                    for (VolumeVO vol : vols) {
                        // make sure if the templateId is unchanged. If it is changed,
                        // let planner
                        // reassign pool for the volume even if it ready.
                        Long volTemplateId = vol.getTemplateId();
                        if (volTemplateId != null && volTemplateId.longValue() != template.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug(vol + " of " + vm + " is READY, but template ids don't match, let the planner reassign a new pool");
                            }
                            continue;
                        }
    
                        StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
                        if (!pool.isInMaintenance()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Root volume is ready, need to place VM in volume's cluster");
                            }
                            long rootVolDcId = pool.getDataCenterId();
                            Long rootVolPodId = pool.getPodId();
                            Long rootVolClusterId = pool.getClusterId();
                            if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
                                Long clusterIdSpecified = planToDeploy.getClusterId();
                                if (clusterIdSpecified != null && rootVolClusterId != null) {
                                    if (rootVolClusterId.longValue() != clusterIdSpecified.longValue()) {
                                        // cannot satisfy the plan passed in to the
                                        // planner
                                        if (s_logger.isDebugEnabled()) {
                    vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx);
                                            s_logger.debug("Cannot satisfy the deployment plan passed in since the ready Root volume is in different cluster. volume's cluster: " + rootVolClusterId
                                                    + ", cluster specified: " + clusterIdSpecified);
                                        }
                                        throw new ResourceUnavailableException("Root volume is ready in different cluster, Deployment plan provided cannot be satisfied, unable to create a deployment for "
                                                + vm, Cluster.class, clusterIdSpecified);
                                    }
                                }
                                plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), vol.getPoolId(), null, ctx);
                            }else{
                                plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, ctx);
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug(vol + " is READY, changing deployment plan to use this pool's dcId: " + rootVolDcId + " , podId: " + rootVolPodId + " , and clusterId: " + rootVolClusterId);
                                }
                                planChangedByVolume = true;
                            }
                        }
                    }
                }
                
                VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, account, params);
                DeployDestination dest = null;
                for (DeploymentPlanner planner : _planners) {
                    if (planner.canHandle(vmProfile, plan, avoids)) {
                        dest = planner.plan(vmProfile, plan, avoids);
                    } else {
                        continue;
                    }
                    if (dest != null) {
                        avoids.addHost(dest.getHost().getId());
                        journal.record("Deployment found ", vmProfile, dest);
                        break;
                    }
                }

                if (dest == null) {
                    if (planChangedByVolume) {
                        plan = originalPlan;
                        planChangedByVolume = false;
                        //do not enter volume reuse for next retry, since we want to look for resorces outside the volume's cluster
                        reuseVolume = false;
                        continue;
                    }
                    throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
                }

                long destHostId = dest.getHost().getId();
                vm.setPodId(dest.getPod().getId());

                try {
                    if (!changeState(vm, Event.OperationRetry, destHostId, work, Step.Prepare)) {
                        throw new ConcurrentOperationException("Unable to update the state of the Virtual Machine");
                    }
                } catch (NoTransitionException e1) {
                    throw new ConcurrentOperationException(e1.getMessage());
                }

                try {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("VM is being created in podId: " + vm.getPodIdToDeployIn());
                    }
                    _networkMgr.prepare(vmProfile, dest, ctx); 
                    if (vm.getHypervisorType() != HypervisorType.BareMetal) {
                        _storageMgr.prepare(vmProfile, dest, recreate);
                        recreate = false;
                    }
                    //since StorageMgr succeeded in volume creation, reuse Volume for further tries until current cluster has capacity
                    if(!reuseVolume){
                        reuseVolume = true;
                    }
                    
                    Commands cmds = null;
                    vmGuru.finalizeVirtualMachineProfile(vmProfile, dest, ctx);

                    VirtualMachineTO vmTO = hvGuru.implement(vmProfile);

                    cmds = new Commands(OnError.Stop);
                    cmds.addCommand(new StartCommand(vmTO));


                    work = _workDao.findById(work.getId());
                    if (work == null || work.getStep() != Step.Prepare) {
                        throw new ConcurrentOperationException("Work steps have been changed: " + work);
                    }
                    _workDao.updateStep(work, Step.Starting);

                    _agentMgr.send(destHostId, cmds);
                    
                    _workDao.updateStep(work, Step.Started);
                    
                    
                    StartAnswer startAnswer = cmds.getAnswer(StartAnswer.class);
                    if (startAnswer != null && startAnswer.getResult()) {
                        String host_guid = startAnswer.getHost_guid();
                        if( host_guid != null ) {
                            HostVO finalHost = _resourceMgr.findHostByGuid(host_guid);
                            if (finalHost == null ) {
                                throw new CloudRuntimeException("Host Guid " + host_guid + " doesn't exist in DB, something wrong here");
                            }
                            destHostId = finalHost.getId();
                        }
                        if (vmGuru.finalizeStart(vmProfile, destHostId, cmds, ctx)) {
                            if (!changeState(vm, Event.OperationSucceeded, destHostId, work, Step.Done)) {
                                throw new ConcurrentOperationException("Unable to transition to a new state.");
                            }
                            startedVm = vm;
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Start completed for VM " + vm);
                            }
                            return startedVm;
                        } else {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.info("The guru did not like the answers so stopping " + vm);
                            }
                           
                            StopCommand cmd = new StopCommand(vm.getInstanceName());
                            StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd);
                            if (answer == null || !answer.getResult()) {
                                s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers")); 
                                _haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop);
                                throw new ExecutionException("Unable to stop " + vm + " so we are unable to retry the start operation");
                            }
                            if (vmGuru.recreateNeeded(vmProfile, destHostId, cmds, ctx)) {
                            	recreate = true;
                            } else {
                            	throw new ExecutionException("Unable to start " + vm + " due to error in finalizeStart, not retrying");
                            }
                        }
                    }
                    s_logger.info("Unable to start VM on " + dest.getHost() + " due to " + (startAnswer == null ? " no start answer" : startAnswer.getDetails()));
                    
                } catch (OperationTimedoutException e) {
                    s_logger.debug("Unable to send the start command to host " + dest.getHost());
                    if (e.isActive()) {
                        _haMgr.scheduleStop(vm, destHostId, WorkType.CheckStop);
                    }
                    canRetry = false;
                    throw new AgentUnavailableException("Unable to start " + vm.getHostName(), destHostId, e);
                } catch (ResourceUnavailableException e) {
                    s_logger.info("Unable to contact resource.", e);
                    if (!avoids.add(e)) {
                        if (e.getScope() == Volume.class || e.getScope() == Nic.class) {
                            throw e;
                        } else {
                            s_logger.warn("unexpected ResourceUnavailableException : " + e.getScope().getName(), e);
                            throw e;
                        }
                    }
                } catch (InsufficientCapacityException e) {
                    s_logger.info("Insufficient capacity ", e);
                    if (!avoids.add(e)) {
                        if (e.getScope() == Volume.class || e.getScope() == Nic.class) {
                            throw e;
                        } else {
                            s_logger.warn("unexpected InsufficientCapacityException : " + e.getScope().getName(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Failed to start instance " + vm, e);
                    throw new AgentUnavailableException("Unable to start instance due to " + e.getMessage(), destHostId, e);
                } finally {
                    if (startedVm == null && canRetry) {
                        Step prevStep = work.getStep();
                        _workDao.updateStep(work, Step.Release);
                        if (prevStep == Step.Started || prevStep == Step.Starting) {
                            cleanup(vmGuru, vmProfile, work, Event.OperationFailed, false, caller, account);
                        } else {
                            //if step is not starting/started, send cleanup command with force=true
                            cleanup(vmGuru, vmProfile, work, Event.OperationFailed, true, caller, account);
                        }
                    }
                }
            }
        } finally {
            if (startedVm == null) {
                if (canRetry) {
                    try {
                        changeState(vm, Event.OperationFailed, null, work, Step.Done);
                    } catch (NoTransitionException e) {
                        throw new ConcurrentOperationException(e.getMessage());
                    }
                }
            }
        }

        return startedVm;
    }

    @Override
    public  boolean stop(T vm, User user, Account account) throws ResourceUnavailableException {
        try {
            return advanceStop(vm, false, user, account);
        } catch (OperationTimedoutException e) {
            throw new AgentUnavailableException("Unable to stop vm because the operation to stop timed out", vm.getHostId(), e);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to stop vm because of a concurrent operation", e);
    }

    protected  boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) {
        VMInstanceVO vm = profile.getVirtualMachine();
        StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
        try {
            Answer answer = _agentMgr.send(vm.getHostId(), stop);
            if (!answer.getResult()) {
                s_logger.debug("Unable to stop VM due to " + answer.getDetails());
                return false;
            }

            guru.finalizeStop(profile, (StopAnswer) answer);
        } catch (AgentUnavailableException e) {
            if (!force) {
                return false;
            }
        } catch (OperationTimedoutException e) {
            if (!force) {
                return false;
            }
        }

        return true;
    }

    protected  boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile, ItWorkVO work, Event event, boolean force, User user, Account account) {
        T vm = profile.getVirtualMachine();
        State state = vm.getState();
        s_logger.debug("Cleaning up resources for the vm " + vm + " in " + state + " state");
        if (state == State.Starting) {
            Step step = work.getStep();
            if (step == Step.Starting && !force) {
                s_logger.warn("Unable to cleanup vm " + vm + "; work state is incorrect: " + step);
                return false;
            }

            if (step == Step.Started || step == Step.Starting || step == Step.Release) {
                if (vm.getHostId() != null) {
                    if (!sendStop(guru, profile, force)) {
                        s_logger.warn("Failed to stop vm " + vm + " in " + State.Starting + " state as a part of cleanup process");
                        return false;
                    }
                }
            }

            if (step != Step.Release && step != Step.Prepare && step != Step.Started && step != Step.Starting) {
                s_logger.debug("Cleanup is not needed for vm " + vm + "; work state is incorrect: " + step);
                return true;
            }
        } else if (state == State.Stopping) {
            if (vm.getHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Stopping + " state as a part of cleanup process");
                    return false;
                }
            }
        } else if (state == State.Migrating) {
            if (vm.getHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process");
                    return false;
                }
            }
            if (vm.getLastHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process");
                    return false;
                }
            }
        } else if (state == State.Running) {
            if (!sendStop(guru, profile, force)) {
                s_logger.warn("Failed to stop vm " + vm + " in " + State.Running + " state as a part of cleanup process");
                return false;
            }
        }

        try {
            _networkMgr.release(profile, force);
            s_logger.debug("Successfully released network resources for the vm " + vm);
        } catch (Exception e) {
            s_logger.warn("Unable to release some network resources.", e);
        }

        _storageMgr.release(profile);
        s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state");
        return true;
    }

    @Override
    public  boolean advanceStop(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        State state = vm.getState();
        if (state == State.Stopped) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM is already stopped: " + vm);
            }
            return true;
        }

        if (state == State.Destroyed || state == State.Expunging || state == State.Error) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Stopped called on " + vm + " but the state is " + state);
            }
            return true;
        }
        // grab outstanding work item if any
        ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found an outstanding work item for this vm " + vm + " with state:" + vm.getState() + ", work id:" + work.getId());
            }
        }
        Long hostId = vm.getHostId();
        if (hostId == null) {
            if (!forced) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("HostId is null but this is not a forced stop, cannot stop vm " + vm + " with state:" + vm.getState());
                }
                return false;
            }
            try {
                stateTransitTo(vm, Event.AgentReportStopped, null, null);
            } catch (NoTransitionException e) {
                s_logger.warn(e.getMessage());
            }
            // mark outstanding work item if any as done
            if (work != null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Updating work item to Done, id:" + work.getId());
                }
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }
            return true;
        }

        VirtualMachineGuru vmGuru = getVmGuru(vm);
        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);

        try {
            if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
                throw new ConcurrentOperationException("VM is being operated on.");
            }
        } catch (NoTransitionException e1) {
            if (!forced) {
                throw new CloudRuntimeException("We cannot stop " + vm + " when it is in state " + vm.getState());
            }
            boolean doCleanup = false;
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to transition the state but we're moving on because it's forced stop");
            }
            if (state == State.Starting || state == State.Migrating) {
                if (work != null) {
                    doCleanup = true;
                } else {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to cleanup VM: " + vm + " ,since outstanding work item is not found");
                    }
                    throw new CloudRuntimeException("Work item not found, We cannot stop " + vm + " when it is in state " + vm.getState());
                }
            } else if (state == State.Stopping) {
                doCleanup = true;
            }

            if (doCleanup) {
                if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) {
                    try {
                        if (s_logger.isDebugEnabled()) {
                            s_logger.debug("Updating work item to Done, id:" + work.getId());
                        }
                        return changeState(vm, Event.AgentReportStopped, null, work, Step.Done);
                    } catch (NoTransitionException e) {
                        s_logger.warn("Unable to cleanup " + vm);
                        return false;
                    }
                } else {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Failed to cleanup VM: " + vm);
                    }
                    throw new CloudRuntimeException("Failed to cleanup " + vm + " , current state " + vm.getState());
                }
            }
        }

        if (vm.getState() != State.Stopping) {
            throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState());
        }

        vmGuru.prepareStop(profile);
        
        StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
        boolean stopped = false;
        StopAnswer answer = null;
        try {
            answer = (StopAnswer) _agentMgr.send(vm.getHostId(), stop);
            stopped = answer.getResult();
            if (!stopped) {
                throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
            }
            vmGuru.finalizeStop(profile, answer);

        } catch (AgentUnavailableException e) {
        } catch (OperationTimedoutException e) {
        } finally {
            if (!stopped) {
                if (!forced) {
                    s_logger.warn("Unable to stop vm " + vm);
                    try {
                        stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
                    } catch (NoTransitionException e) {
                        s_logger.warn("Unable to transition the state " + vm);
                    }
                    return false;
                } else {
                    s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop");
                    vmGuru.finalizeStop(profile, answer);
                }
            }
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug(vm + " is stopped on the host.  Proceeding to release resource held.");
        }

        try {
            _networkMgr.release(profile, forced);
            s_logger.debug("Successfully released network resources for the vm " + vm);
        } catch (Exception e) {
            s_logger.warn("Unable to release some network resources.", e);
        }

        try {
            if (vm.getHypervisorType() != HypervisorType.BareMetal) {
                _storageMgr.release(profile);
                s_logger.debug("Successfully released storage resources for the vm " + vm);
            }
        } catch (Exception e) {
            s_logger.warn("Unable to release storage resources.", e);
        }

        try {
            if (work != null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Updating the outstanding work item to Done, id:" + work.getId());
                }
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }

            return stateTransitTo(vm, Event.OperationSucceeded, null, null);
        } catch (NoTransitionException e) {
            s_logger.warn(e.getMessage());
            return false;
        }
    }

    private void setStateMachine() {
        _stateMachine = VirtualMachine.State.getStateMachine();
    }

    protected boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId, String reservationId) throws NoTransitionException {
        vm.setReservationId(reservationId);
        return _stateMachine.transitTo(vm, e, new Pair(vm.getHostId(), hostId), _vmDao);
    }

    @Override
    public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) throws NoTransitionException {
        State oldState = vm.getState();
        if (oldState == State.Starting) {
            if (e == Event.OperationSucceeded) {
                vm.setLastHostId(hostId);
            }
        } else if (oldState == State.Stopping) {
            if (e == Event.OperationSucceeded) {
                vm.setLastHostId(vm.getHostId());
            }
        }
        return _stateMachine.transitTo(vm, e, new Pair(vm.getHostId(), hostId), _vmDao);
    }

    @Override
    public  boolean remove(T vm, User user, Account caller) {
        return _vmDao.remove(vm.getId());
    }

    @Override
    public  boolean destroy(T vm, User user, Account caller) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Destroying vm " + vm);
        }
        if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging || vm.getRemoved() != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vm);
            }
            return true;
        }

        if (!advanceStop(vm, _forceStop, user, caller)) {
            s_logger.debug("Unable to stop " + vm);
            return false;
        }

        try {
            if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) {
                s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
                return false;
            }
        } catch (NoTransitionException e) {
            s_logger.debug(e.getMessage());
            return false;
        }

        return true;
    }

    protected boolean checkVmOnHost(VirtualMachine vm, long hostId) throws AgentUnavailableException, OperationTimedoutException {
        CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(hostId, new CheckVirtualMachineCommand(vm.getInstanceName()));
        if (!answer.getResult() || answer.getState() == State.Stopped) {
            return false;
        }

        return true;
    }

    @Override
    public  T storageMigration(T vm, StoragePool destPool) {
        VirtualMachineGuru vmGuru = getVmGuru(vm);

        long vmId = vm.getId();
        vm = vmGuru.findById(vmId);

        try {
            stateTransitTo(vm, VirtualMachine.Event.StorageMigrationRequested, null);
        } catch (NoTransitionException e) {
            s_logger.debug("Unable to migrate vm: " + e.toString());
            throw new CloudRuntimeException("Unable to migrate vm: " + e.toString());
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        boolean migrationResult = false;
        try {
            migrationResult = _storageMgr.StorageMigration(profile, destPool);

            if (migrationResult) {
                //if the vm is migrated to different pod in basic mode, need to reallocate ip

                if (vm.getPodIdToDeployIn() != destPool.getPodId()) {
                    DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), destPool.getPodId(), null, null, null, null);
                    VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, null, null, null, null);
                    _networkMgr.reallocate(vmProfile, plan);
                }

                //when start the vm next time, don;'t look at last_host_id, only choose the host based on volume/storage pool
                vm.setLastHostId(null);
                vm.setPodId(destPool.getPodId());
            } else {
                s_logger.debug("Storage migration failed");
            }
        } catch (ConcurrentOperationException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientVirtualNetworkCapcityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientAddressCapacityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientCapacityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } finally {
            try {
                stateTransitTo(vm, VirtualMachine.Event.AgentReportStopped, null);
            } catch (NoTransitionException e) {
                s_logger.debug("Failed to change vm state: " + e.toString());
                throw new CloudRuntimeException("Failed to change vm state: " + e.toString());
            }
        }

        return vm;
    }

    @Override
    public  T migrate(T vm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
    VirtualMachineMigrationException {
        s_logger.info("Migrating " + vm + " to " + dest);

        long dstHostId = dest.getHost().getId();
        Host fromHost = _hostDao.findById(srcHostId);
        if (fromHost == null) {
            s_logger.info("Unable to find the host to migrate from: " + srcHostId);
            throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
        }

        if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
                if (e.isActive()) {
            s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
            throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
        }

        VirtualMachineGuru vmGuru = getVmGuru(vm);

        long vmId = vm.getId();
        vm = vmGuru.findById(vmId);
        if (vm == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find the vm " + vm);
            }
            throw new ManagementServerException("Unable to find a virtual machine with id " + vmId);
        }

        if (vm.getState() != State.Running) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
            }
            throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString());
        }

        short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
        if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
            alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE;
        } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
            alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        _networkMgr.prepareNicForMigration(profile, dest);
        _storageMgr.prepareForMigration(profile, dest);

        VirtualMachineTO to = toVmTO(profile);
        PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);

        ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
        work.setStep(Step.Prepare);
        work.setResourceType(ItWorkVO.ResourceType.Host);
        work.setResourceId(dstHostId);
        work = _workDao.persist(work);

        PrepareForMigrationAnswer pfma = null;
        try {
                }
            pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
            if (!pfma.getResult()) {
                String msg = "Unable to prepare for migration due to " + pfma.getDetails();
                pfma = null;
                throw new AgentUnavailableException(msg, dstHostId);
            }
        } catch (OperationTimedoutException e1) {
            throw new AgentUnavailableException("Operation timed out", dstHostId);
        } finally {
            if (pfma == null) {
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }
        }

        vm.setLastHostId(srcHostId);
        try {
            if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
                s_logger.info("Migration cancelled because state has changed: " + vm);
                throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
            }
        } catch (NoTransitionException e1) {
            s_logger.info("Migration cancelled because " + e1.getMessage());
            throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
        }

        boolean migrated = false;
        try {
            boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
            MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
            mc.setHostGuid(dest.getHost().getGuid());

            try {
                MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
                if (!ma.getResult()) {
                    s_logger.error("Unable to migrate due to " + ma.getDetails());
                    return null;
                }
            } catch (OperationTimedoutException e) {
                    s_logger.warn("Active migration command so scheduling a restart for " + vm);
                    _haMgr.scheduleRestart(vm, true);
                }
                throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
            }

            try {
                if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
                    throw new ConcurrentOperationException("Unable to change the state for " + vm);
                }
            } catch (NoTransitionException e1) {
                throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
            }

            try {
                if (!checkVmOnHost(vm, dstHostId)) {
                    s_logger.error("Unable to complete migration for " + vm);
                    try {
                        _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null);
                    } catch (AgentUnavailableException e) {
                        s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
                    }
                    cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                    return null;
                }
            } catch (OperationTimedoutException e) {
            }

            migrated = true;
            return vm;
        } finally {
            if (!migrated) {
                s_logger.info("Migration was unsuccessful.  Cleaning up: " + vm);

                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
                        + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed.  Please check logs.");
                try {
                    _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null);
                } catch (AgentUnavailableException ae) {
                    s_logger.info("Looks like the destination Host is unavailable for cleanup");

                try {
                    stateTransitTo(vm, Event.OperationFailed, srcHostId);
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
            }

            work.setStep(Step.Done);
            _workDao.update(work.getId(), work);
        }
    }

    @Override
    public VirtualMachineTO toVmTO(VirtualMachineProfile profile) {
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getVirtualMachine().getHypervisorType());
        VirtualMachineTO to = hvGuru.implement(profile);
        return to;
    }

    protected void cancelWorkItems(long nodeId) {
        GlobalLock scanLock = GlobalLock.getInternLock("vmmgr.cancel.workitem");

        try {
            if (scanLock.lock(3)) {
                try {
                    List works = _workDao.listWorkInProgressFor(nodeId);
                    for (ItWorkVO work : works) {
                        s_logger.info("Handling unfinished work item: " + work);
                        try {
                            VMInstanceVO vm = _vmDao.findById(work.getInstanceId());
                            if (vm != null) {
                                if (work.getType() == State.Starting) {
                                    _haMgr.scheduleRestart(vm, true);
                                    work.setManagementServerId(_nodeId);
                                    _workDao.update(work.getId(), work);
                                } else if (work.getType() == State.Stopping) {
                                    _haMgr.scheduleStop(vm, vm.getHostId(), WorkType.CheckStop);
                                    work.setManagementServerId(_nodeId);
                                    _workDao.update(work.getId(), work);
                                } else if (work.getType() == State.Migrating) {
                                    _haMgr.scheduleMigration(vm);
                                    work.setStep(Step.Done);
                                    _workDao.update(work.getId(), work);
                                }
                            }
                        } catch (Exception e) {
                            s_logger.error("Error while handling " + work, e);
                        }
                    }
                } finally {
                    scanLock.unlock();
                }
            }
        } finally {
            scanLock.releaseRef();
        }
    }

    @Override
    public boolean migrateAway(VirtualMachine.Type vmType, long vmId, long srcHostId) throws InsufficientServerCapacityException, VirtualMachineMigrationException {
        VirtualMachineGuru vmGuru = _vmGurus.get(vmType);
        VMInstanceVO vm = vmGuru.findById(vmId);
        if (vm == null) {
            s_logger.debug("Unable to find a VM for " + vmId);
            return true;
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);

        Long hostId = vm.getHostId();
        if (hostId == null) {
            s_logger.debug("Unable to migrate because the VM doesn't have a host id: " + vm);
            return true;
        }

        Host host = _hostDao.findById(hostId);

        DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), null, null, null);
        ExcludeList excludes = new ExcludeList();
        excludes.addHost(hostId);

        DeployDestination dest = null;
        while (true) {
            for (DeploymentPlanner planner : _planners) {
                if (planner.canHandle(profile, plan, excludes)) {
                    dest = planner.plan(profile, plan, excludes);
                } else {
                    continue;
                }

                if (dest != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Planner " + planner + " found " + dest + " for migrating to.");
                    }
                    break;
                }
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Planner " + planner + " was unable to find anything.");
                }
            }

            if (dest == null) {
                throw new InsufficientServerCapacityException("Unable to find a server to migrate to.", host.getClusterId());
            }

            excludes.addHost(dest.getHost().getId());
            VMInstanceVO vmInstance = null;
            try {
                vmInstance = migrate(vm, srcHostId, dest);
            } catch (ResourceUnavailableException e) {
                s_logger.debug("Unable to migrate to unavailable " + dest);
            } catch (ConcurrentOperationException e) {
                s_logger.debug("Unable to migrate VM due to: " + e.getMessage());
            } catch (ManagementServerException e) {
                s_logger.debug("Unable to migrate VM: " + e.getMessage());
            } catch (VirtualMachineMigrationException e) {
                s_logger.debug("Got VirtualMachineMigrationException, Unable to migrate: " + e.getMessage());
                if (vm.getState() == State.Starting) {
                    s_logger.debug("VM seems to be still Starting, we should retry migration later");
                    throw e;
                } else {
                    s_logger.debug("Unable to migrate VM, VM is not in Running or even Starting state, current state: " + vm.getState().toString());
                }
            }
            if (vmInstance != null) {
                return true;
            }
            try {
    public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) {  
                boolean result = advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                return result;
            } catch (ResourceUnavailableException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            } catch (ConcurrentOperationException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            } catch (OperationTimedoutException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            }
            return false;
        }
    }

    protected class CleanupTask implements Runnable {
        @Override
        public void run() {
            s_logger.trace("VM Operation Thread Running");
            try {
                _workDao.cleanup(_cleanupWait);
            } catch (Exception e) {
                s_logger.error("VM Operations failed due to ", e);
            }
        }
    }

    @Override
    public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
        Enumeration en = _hostAllocators.enumeration();
        boolean isMachineUpgradable = true;
        while (isMachineUpgradable && en.hasMoreElements()) {
            final HostAllocator allocator = en.nextElement();
            isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
        }

        return isMachineUpgradable;
    }

    @Override
    public  T reboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException {
        try {
            return advanceReboot(vm, params, caller, account);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to reboot a VM due to concurrent operation", e);
        }
    }

    @Override
            }
    public  T advanceReboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException,
    ConcurrentOperationException, ResourceUnavailableException {
        T rebootedVm = null;

        DataCenter dc = _configMgr.getZone(vm.getDataCenterIdToDeployIn());
        Host host = _hostDao.findById(vm.getHostId());
        Cluster cluster = null;
        if (host != null) {
            cluster = _configMgr.getCluster(host.getClusterId());
        }
        HostPodVO pod = _configMgr.getPod(host.getPodId());
        DeployDestination dest = new DeployDestination(dc, pod, cluster, host);

        try {

            Commands cmds = new Commands(OnError.Stop);
            cmds.addCommand(new RebootCommand(vm.getInstanceName()));
            _agentMgr.send(host.getId(), cmds);

            Answer rebootAnswer = cmds.getAnswer(RebootAnswer.class);
            if (rebootAnswer != null && rebootAnswer.getResult()) {
                rebootedVm = vm;
                return rebootedVm;
            }
            s_logger.info("Unable to reboot VM " + vm + " on " + dest.getHost() + " due to " + (rebootAnswer == null ? " no reboot answer" : rebootAnswer.getDetails()));
        } catch (OperationTimedoutException e) {
            s_logger.warn("Unable to send the reboot command to host " + dest.getHost() + " for the vm " + vm + " due to operation timeout", e);
            throw new CloudRuntimeException("Failed to reboot the vm on host " + dest.getHost());
        }

        return rebootedVm;
    }

    @Override
    public VMInstanceVO findByIdAndType(VirtualMachine.Type type, long vmId) {
        VirtualMachineGuru guru = _vmGurus.get(type);
        return guru.findById(vmId);
    }

    public Command cleanup(String vmName) {
        return new StopCommand(vmName);
    }

        Commands commands = new Commands(OnError.Continue);

        Map infos = convertToInfos(startup);

        final List vms = _vmDao.listByHostId(hostId);
        s_logger.debug("Found " + vms.size() + " VMs for host " + hostId);
        for (VMInstanceVO vm : vms) {
            AgentVmInfo info = infos.remove(vm.getId());
            VMInstanceVO castedVm = null;
            if (info == null) {
                info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
            } 
            castedVm = info.guru.findById(vm.getId());

            HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
            Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
            if (command != null) {
                commands.addCommand(command);
            }
        }
        
        for (final AgentVmInfo left : infos.values()) {
            boolean found = false;
            for (VirtualMachineGuru vmGuru : _vmGurus.values()) {
                VMInstanceVO vm = vmGuru.findByName(left.name);
                if (vm != null) {
                    found = true;
                    HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                    if(hvGuru.trackVmHostChange()) {
                        Command command = compareState(hostId, vm, left, true, true);
                        if (command != null) {
                            commands.addCommand(command);
                        }
                    } else {
                        s_logger.warn("Stopping a VM, VM " + left.name + " migrate from Host " + vm.getHostId() + " to Host " + hostId );
                        commands.addCommand(cleanup(left.name));
                    }
                    break;
                }
            }
            if ( ! found ) {
                s_logger.warn("Stopping a VM that we have no record of : " + left.name);
                commands.addCommand(cleanup(left.name));
        }

        return commands;
    }

    public Commands deltaHostSync(long hostId, Map newStates) {
        Map states = convertDeltaToInfos(newStates);
        Commands commands = new Commands(OnError.Continue);

        for (Map.Entry entry : states.entrySet()) {
            AgentVmInfo info = entry.getValue();

            VMInstanceVO vm = info.vm;

            Command command = null;
            if (vm != null) {
                HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                command = compareState(hostId, vm, info, false, hvGuru.trackVmHostChange());
            } else {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Cleaning up a VM that is no longer found: " + info.name);
                }
                command = cleanup(info.name);
            }

            if (command != null) {
                commands.addCommand(command);
            }
        }

        return commands;
    }



    public void deltaSync(Map> newStates) {
        Map states = convertToInfos(newStates);

        for (Map.Entry entry : states.entrySet()) {
            AgentVmInfo info = entry.getValue();
            VMInstanceVO vm = info.vm;
            Command command = null;
            if (vm != null) {
                Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
                long hId = host.getId();

                HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                command = compareState(hId, vm, info, false, hvGuru.trackVmHostChange());
            } else {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Cleaning up a VM that is no longer found : " + info.name);
                }
                command = cleanup(info.name);
            }
            if (command != null){
                try {
                    Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
                    if (host != null){
                        Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
                        if (!answer.getResult()) {
                            s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                        }
                    }
                } catch (Exception e) {
                    s_logger.warn("Unable to stop a VM due to " + e.getMessage());
                }
            }
        }
    }


    public void fullSync(final long clusterId, Map> newStates) {
    	if (newStates==null)return;
        Map infos = convertToInfos(newStates);
        Set set_vms = Collections.synchronizedSet(new HashSet());
        set_vms.addAll(_vmDao.listByClusterId(clusterId));
        set_vms.addAll(_vmDao.listLHByClusterId(clusterId));

        for (VMInstanceVO vm : set_vms) {
            if (vm.isRemoved() || vm.getState() == State.Destroyed  || vm.getState() == State.Expunging) continue;
            AgentVmInfo info =  infos.remove(vm.getId());
            VMInstanceVO castedVm = null;
            if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting))  
            		||  (info != null && (info.state == State.Running && vm.getState() == State.Starting))) 
            {
            	s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " +  (info == null ? "Stopped" : "Running") + " on agent");
                info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
           		
                // Bug 13850- grab outstanding work item if any for this VM state so that we mark it as DONE after we change VM state, else it will remain pending
                ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
                if (work != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Found an outstanding work item for this vm " + vm + " in state:" + vm.getState() + ", work id:" + work.getId());
                    }
                }
                vm.setState(State.Running); // set it as running and let HA take care of it
           		_vmDao.persist(vm);
           		
                if (work != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Updating outstanding work item to Done, id:" + work.getId());
                    }
                    work.setStep(Step.Done);
                    _workDao.update(work.getId(), work);
                }
           		
                castedVm = info.guru.findById(vm.getId());
                try {
                    Host host = _hostDao.findByGuid(info.getHostUuid());
                    long hostId = host == null ? (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId()) : host.getId();
                    HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
                    Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
                    if (command != null){
                        Answer answer = _agentMgr.send(hostId, command);
                        if (!answer.getResult()) {
                            s_logger.warn("Failed to update state of the VM due to " + answer.getDetails());
                        }
                    }
                } catch (Exception e) {
                    s_logger.warn("Unable to update state of the VM due to exception " + e.getMessage());
                    e.printStackTrace();
                }
            }
            else if (info != null && (vm.getState() == State.Stopped || vm.getState() == State.Stopping)) {
            	 Host host = _hostDao.findByGuid(info.getHostUuid());
                 if (host != null){
                    s_logger.warn("Stopping a VM which is stopped/stopping " + info.name);
                    vm.setState(State.Stopped); // set it as stop and clear it from host
                    vm.setHostId(null);
                    _vmDao.persist(vm);
                     try {
	                     Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
	                     if (!answer.getResult()) {
	                         s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
	                     }
                     }
                     catch (Exception e) {
                         s_logger.warn("Unable to stop a VM due to " + e.getMessage());
                     }
                 }
            }
            else
            // host id can change
	        if (info != null && vm.getState() == State.Running){
	           // check for host id changes
	           Host host = _hostDao.findByGuid(info.getHostUuid());
	            if (host != null && (vm.getHostId() == null || host.getId() != vm.getHostId())){
    	        	s_logger.info("Found vm " + vm.getInstanceName() + " with inconsistent host in db, new host is " +  host.getId());
        			try {
						stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, host.getId());
					} catch (NoTransitionException e) {
						s_logger.warn(e.getMessage());
					}
        		}
            }
             /* else if(info == null && vm.getState() == State.Stopping) { //Handling CS-13376
                        s_logger.warn("Marking the VM as Stopped as it was still stopping on the CS" +vm.getName());
                        vm.setState(State.Stopped); // Setting the VM as stopped on the DB and clearing it from the host
                        vm.setLastHostId(vm.getHostId());
                        vm.setHostId(null);
                        _vmDao.persist(vm);
                 }*/
        }

        for (final AgentVmInfo left : infos.values()) {
        	if (VirtualMachineName.isValidVmName(left.name)) continue;  // if the vm follows cloudstack naming ignore it for stopping
            try {
                Host host = _hostDao.findByGuid(left.getHostUuid());
                if (host != null){
                    s_logger.warn("Stopping a VM which we do not have any record of " + left.name);
                    Answer answer = _agentMgr.send(host.getId(), cleanup(left.name));
                    if (!answer.getResult()) {
                        s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                    }
                }
            } catch (Exception e) {
                s_logger.warn("Unable to stop a VM due to " + e.getMessage());
            }
        }

    }



    protected Map convertToInfos(final Map> newStates) {
        final HashMap map = new HashMap();
        if (newStates == null) {
            return map;
        }
        Collection> vmGurus = _vmGurus.values();
        boolean is_alien_vm = true;
        long alien_vm_count = -1;
        for (Map.Entry> entry : newStates.entrySet()) {
        	is_alien_vm = true;
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();
                VMInstanceVO vm = vmGuru.findByName(name);
                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().second(), entry.getValue().first()));
                    is_alien_vm = false;
                    break;
                }
                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue().second(), entry.getValue().first()));
                    is_alien_vm = false;
                    break;
                }
            }
            // alien VMs
            if (is_alien_vm){
            	map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, null, entry.getValue().second(), entry.getValue().first()));
            	s_logger.warn("Found an alien VM " + entry.getKey());
            }
        }
        return map;
    }

    protected Map convertToInfos(StartupRoutingCommand cmd) { 
        final Map states = cmd.getVmStates();
        final HashMap map = new HashMap();
        if (states == null) {
            return map;
        }
        Collection> vmGurus = _vmGurus.values();

        for (Map.Entry entry : states.entrySet()) {
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();
                VMInstanceVO vm = vmGuru.findByName(name);
                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().getState(), entry.getValue().getHost() ));
                    break;
                }
                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue().getState(), entry.getValue().getHost() ));
                    break;
                }
            }
        }

        return map;
    }

    protected Map convertDeltaToInfos(final Map states) {
        final HashMap map = new HashMap();

        if (states == null) {
            return map;
        }

        Collection> vmGurus = _vmGurus.values();

        for (Map.Entry entry : states.entrySet()) {
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();

                VMInstanceVO vm = vmGuru.findByName(name);

                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue()));
                    break;
                }

                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue()));
                    break;
                }
            }
        }

        return map;
    }



    /**
     * compareState does as its name suggests and compares the states between
     * management server and agent. It returns whether something should be
     * cleaned up
     * 
     */
    protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) {
        State agentState = info.state;
        final String agentName = info.name;
        final State serverState = vm.getState();
        final String serverName = vm.getInstanceName();

        Command command = null;
        s_logger.debug("VM " + serverName + ": cs state = " + serverState + " and realState = " + agentState);
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("VM " + serverName + ": cs state = " + serverState + " and realState = " + agentState);
        }

        if (agentState == State.Error) {
            agentState = State.Stopped;

            short alertType = AlertManager.ALERT_TYPE_USERVM;
            if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
            if (!lock.lock(30)) {
                alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER;
            } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY;
            } else if (VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_SSVM;
            }

            HostPodVO podVO = _podDao.findById(vm.getPodIdToDeployIn());
            DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterIdToDeployIn());
            HostVO hostVO = _hostDao.findById(vm.getHostId());

            String hostDesc = "name: " + hostVO.getName() + " (id:" + hostVO.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();
            _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc
                    + " due to storage failure", "Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped due to storage failure.");
        }

        if (trackExternalChange) {
            if (serverState == State.Starting) {
                if (vm.getHostId() != null && vm.getHostId() != hostId) {
                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
                            + vm.getInstanceName());
                    return null;
                }
            }
            if (vm.getHostId() == null || hostId != vm.getHostId()) {
                try {
                    stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
                } catch (NoTransitionException e) {
                }
            }
        }

        // during VM migration time, don't sync state will agent status update
        if (serverState == State.Migrating) {
            s_logger.debug("Skipping vm in migrating state: " + vm);
            return null;
        }

        if (trackExternalChange) {
            if (serverState == State.Starting) {
                if (vm.getHostId() != null && vm.getHostId() != hostId) {
                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
                            + vm.getInstanceName());
                    return null;
                }
            }

            if (serverState == State.Running) {
                try {
                    //
                    // we had a bug that sometimes VM may be at Running State
                    // but host_id is null, we will cover it here.
                    // means that when CloudStack DB lost of host information,
                    // we will heal it with the info reported from host
                    //
                    if (vm.getHostId() == null || hostId != vm.getHostId()) {
                        if (s_logger.isDebugEnabled()) {
                            s_logger.debug("detected host change when VM " + vm + " is at running state, VM could be live-migrated externally from host " + vm.getHostId() + " to host " + hostId);
                        }

                        stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
                    }
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
            }
        }

        if (agentState == serverState) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Both states are " + agentState + " for " + vm);
            }
            assert (agentState == State.Stopped || agentState == State.Running) : "If the states we send up is changed, this must be changed.";
            if (agentState == State.Running) {
                try {
                    stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, hostId);
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
                s_logger.debug("Couldn't lock the db");
                // FIXME: What if someone comes in and sets it to stopping? Then
                // what?
                return null;
            }

            s_logger.debug("State matches but the agent said stopped so let's send a cleanup command anyways.");
            return cleanup(agentName);
        }

        if (agentState == State.Shutdowned) {
            if (serverState == State.Running || serverState == State.Starting || serverState == State.Stopping) {
                try {
                    advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                } catch (AgentUnavailableException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                } catch (OperationTimedoutException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                } catch (ConcurrentOperationException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                }
            } else {
                s_logger.debug("Sending cleanup to a shutdowned vm: " + agentName);
                command = cleanup(agentName);
            }
        } else if (agentState == State.Stopped) {
            // This state means the VM on the agent was detected previously
            // and now is gone. This is slightly different than if the VM
            // was never completed but we still send down a Stop Command
            // to ensure there's cleanup.
            if (serverState == State.Running) {
                // Our records showed that it should be running so let's restart
                // it.
                _haMgr.scheduleRestart(vm, false);
            } else if (serverState == State.Stopping) {
                _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop);
                s_logger.debug("Scheduling a check stop for VM in stopping mode: " + vm);
            } else if (serverState == State.Starting) {
                s_logger.debug("Ignoring VM in starting mode: " + vm.getInstanceName());
                _haMgr.scheduleRestart(vm, false);
            }
            command = cleanup(agentName);
        } else if (agentState == State.Running) {
            if (serverState == State.Starting) {
                if (fullSync) {
                    try {
                        ensureVmRunningContext(hostId, vm, Event.AgentReportRunning);
                    } catch (OperationTimedoutException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    } catch (ResourceUnavailableException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    }catch (InsufficientAddressCapacityException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    }catch (NoTransitionException e) {
                        s_logger.warn(e.getMessage());
                    }
                }
            } else if (serverState == State.Stopping) {
                s_logger.debug("Scheduling a stop command for " + vm);
                _haMgr.scheduleStop(vm, hostId, WorkType.Stop);
            } else {
                s_logger.debug("server VM state " + serverState + " does not meet expectation of a running VM report from agent");

                // just be careful not to stop VM for things we don't handle
                // command = cleanup(agentName);
            }
        }
        return command;
    }

    private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException, InsufficientAddressCapacityException {
        VirtualMachineGuru vmGuru = getVmGuru(vm);

        s_logger.debug("VM state is starting on full sync so updating it to running");
        vm = findByIdAndType(vm.getType(), vm.getId());

        // grab outstanding work item if any
        ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found an outstanding work item for this vm " + vm + " in state:" + vm.getState() + ", work id:" + work.getId());
            }
        }

        try {
            stateTransitTo(vm, cause, hostId);
        } catch (NoTransitionException e1) {
            s_logger.warn(e1.getMessage());
        }

        s_logger.debug("VM's " + vm + " state is starting on full sync so updating it to Running");
        vm = vmGuru.findById(vm.getId()); // this should ensure vm has the most
        // up to date info

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        List nics = _nicsDao.listByVmId(profile.getId());
        for (NicVO nic : nics) {
            Network network = _networkMgr.getNetwork(nic.getNetworkId());
            NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, 
                    _networkMgr.isSecurityGroupSupportedInNetwork(network), _networkMgr.getNetworkTag(profile.getHypervisorType(), network));
            profile.addNic(nicProfile);
        }

        Commands cmds = new Commands(OnError.Stop);
        s_logger.debug("Finalizing commands that need to be send to complete Start process for the vm " + vm);

        if (vmGuru.finalizeCommandsOnStart(cmds, profile)) {
            if (cmds.size() != 0) {
                _agentMgr.send(vm.getHostId(), cmds);
            }

            if (vmGuru.finalizeStart(profile, vm.getHostId(), cmds, null)) {
                stateTransitTo(vm, cause, vm.getHostId());
            } else {
                s_logger.error("Unable to finish finialization for running vm: " + vm);
            }
        } else {
            s_logger.error("Unable to finalize commands on start for vm: " + vm);
        }

        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Updating outstanding work item to Done, id:" + work.getId());
            }
            work.setStep(Step.Done);
            _workDao.update(work.getId(), work);
        }
    }

    @Override
    public boolean isRecurring() {
        return true;
    }

    @Override
    public boolean processAnswers(long agentId, long seq, Answer[] answers) {
        for (final Answer answer : answers) {
            if (answer instanceof ClusterSyncAnswer) {
                ClusterSyncAnswer hs = (ClusterSyncAnswer) answer;
                if (!hs.isExceuted()){
                    deltaSync(hs.getNewStates());
                    hs.setExecuted();
                }
            }
        }
        return true;
    }

    @Override
    public boolean processTimeout(long agentId, long seq) {
        return true;
    }

    @Override
    public int getTimeout() {
        return -1;
    }

    @Override
    public boolean processCommands(long agentId, long seq, Command[] cmds) {
        boolean processed = false;
        for (Command cmd : cmds) {
            if (cmd instanceof PingRoutingCommand) {
                PingRoutingCommand ping = (PingRoutingCommand) cmd;
                if (ping.getNewStates() != null && ping.getNewStates().size() > 0) {
                    Commands commands = deltaHostSync(agentId, ping.getNewStates());
                    if (commands.size() > 0) {
                        try {
                            _agentMgr.send(agentId, commands, this);
                        } catch (final AgentUnavailableException e) {
                return;
                            s_logger.warn("Agent is now unavailable", e);
                        }
                    }
                }
                processed = true;
            }
        }
        return processed;
    }

    @Override
    public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
        return null;
    }

    @Override
    public boolean processDisconnect(long agentId, Status state) {
        return true;
    }

    @Override
    public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
        if (!(cmd instanceof StartupRoutingCommand)) {
            return;
        }

        if (forRebalance) {
            s_logger.debug("Not processing listener " + this + " as connect happens on rebalance process");
            return;
        }

        if (forRebalance) {
            s_logger.debug("Not processing listener " + this + " as connect happens on rebalance process");
            return;
        }

        Long clusterId = agent.getClusterId();
        long agentId = agent.getId();
        if (agent.getHypervisorType() == HypervisorType.XenServer) { // only for Xen
        	StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
        	HashMap> allStates = startup.getClusterVMStateChanges();
        	if (allStates != null){
        		this.fullSync(clusterId, allStates);
        	}
        	
        	// initiate the cron job
            ClusterSyncCommand syncCmd = new ClusterSyncCommand(Integer.parseInt(Config.ClusterDeltaSyncInterval.getDefaultValue()), clusterId);
            try {
                long seq_no = _agentMgr.send(agentId, new Commands(syncCmd), this);
                s_logger.debug("Cluster VM sync started with jobid " + seq_no);
            } catch (AgentUnavailableException e) {
                s_logger.fatal("The Cluster VM sync process failed for cluster id " + clusterId + " with ", e);
            }
        }
        else { // for others KVM and VMWare 
            StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
            Commands commands = fullHostSync(agentId, startup);

            if (commands.size() > 0) {
                s_logger.debug("Sending clean commands to the agent");

                try {
                    boolean error = false;
                    Answer[] answers = _agentMgr.send(agentId, commands);
                    for (Answer answer : answers) {
                        if (!answer.getResult()) {
                            s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                            error = true;
                        }
                    }
                    if (error) {
                        throw new ConnectionException(true, "Unable to stop VMs");
                    }
                } catch (final AgentUnavailableException e) {
                    s_logger.warn("Agent is unavailable now", e);
                    throw new ConnectionException(true, "Unable to sync", e);
                } catch (final OperationTimedoutException e) {
                    s_logger.warn("Agent is unavailable now", e);
                    throw new ConnectionException(true, "Unable to sync", e);
                }
            }

        }
    }

    protected class TransitionTask implements Runnable {
        @Override
        public void run() {
            GlobalLock lock = GlobalLock.getInternLock("TransitionChecking");
            if (lock == null) {
                s_logger.debug("Couldn't get the global lock");
                return;
            }

            }
            try {
                lock.addRef();
                List instances = _vmDao.findVMInTransition(new Date(new Date().getTime() - (_operationTimeout * 1000)), State.Starting, State.Stopping);
                for (VMInstanceVO instance : instances) {
                    State state = instance.getState();
                    if (state == State.Stopping) {
                        _haMgr.scheduleStop(instance, instance.getHostId(), WorkType.CheckStop);
                    } else if (state == State.Starting) {
                        _haMgr.scheduleRestart(instance, true);
                    }
                }
            } catch (Exception e) {
                s_logger.warn("Caught the following exception on transition checking", e);
            } finally {
                StackMaid.current().exitCleanup();
                lock.unlock();
            }
        }
    }

    protected class AgentVmInfo {
        public String name;
        public State state;
        public String hostUuid;
        public VMInstanceVO vm;
        public VirtualMachineGuru guru;

        @SuppressWarnings("unchecked")
        public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state, String host) {
            this.name = name;
            this.state = state;
            this.vm = vm;
            this.guru = (VirtualMachineGuru) guru;
            this.hostUuid = host;
        }

        public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state) {
            this(name, guru, vm, state, null);
        }

        public String getHostUuid() {
            return hostUuid;
        }
    }

    @Override
    public VMInstanceVO findById(long vmId) {
        return _vmDao.findById(vmId);
    }
    
    @Override
    public void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId) {
        ServiceOfferingVO newServiceOffering = _offeringDao.findById(newServiceOfferingId);
        if (newServiceOffering == null) {
            throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOfferingId);
        }

        // Check that the VM is stopped
        if (!vmInstance.getState().equals(State.Stopped)) {
            s_logger.warn("Unable to upgrade virtual machine " + vmInstance.toString() + " in state " + vmInstance.getState());
            throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vmInstance.toString() + " " +
            		"in state " + vmInstance.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 (vmInstance.getServiceOfferingId() == newServiceOffering.getId()) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Not upgrading vm " + vmInstance.toString() + " since it already has the requested " +
                		"service offering (" + newServiceOffering.getName() + ")");
            }

            throw new InvalidParameterValueException("Not upgrading vm " + vmInstance.toString() + " since it already " +
            		"has the requested service offering (" + newServiceOffering.getName() + ")");
        }

        ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId());

        // Check that the service offering being upgraded to has the same Guest IP type as the VM's current service offering
        // NOTE: With the new network refactoring in 2.2, we shouldn't need the check for same guest IP type anymore.
        /*
         * 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 " + vmInstance.toString()
                    + ", cannot switch between local storage and shared storage service offerings.  Current offering " +
                    "useLocalStorage=" + currentServiceOffering.getUseLocalStorage()
                    + ", target offering useLocalStorage=" + newServiceOffering.getUseLocalStorage());
        }
        
        // if vm is a system vm, check if it is a system service offering, if yes return with error as it cannot be used for user vms
        if (currentServiceOffering.getSystemUse() != newServiceOffering.getSystemUse()) {
            throw new InvalidParameterValueException("isSystem property is different for current service offering and new service offering");
        }

        // Check that there are enough resources to upgrade the service offering
        if (!isVirtualMachineUpgradable(vmInstance, 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);
        }
    }
    
    @Override
    public boolean upgradeVmDb(long vmId, long serviceOfferingId) {
        VMInstanceVO vmForUpdate = _vmDao.createForUpdate();
        vmForUpdate.setServiceOfferingId(serviceOfferingId);
        ServiceOffering newSvcOff = _configMgr.getServiceOffering(serviceOfferingId);
        vmForUpdate.setHaEnabled(newSvcOff.getOfferHA());
        vmForUpdate.setLimitCpuUse(newSvcOff.getLimitCpuUse());
        vmForUpdate.setServiceOfferingId(newSvcOff.getId());
        return _vmDao.update(vmId, vmForUpdate);
    }
    
    @Override
    public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, 
                                                    ResourceUnavailableException, InsufficientCapacityException {
        
        s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
        VMInstanceVO vmVO = _vmDao.findById(vm.getId());
        ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), 
                _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
        
        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, 
                null, null, null);
        
        DataCenter dc = _configMgr.getZone(network.getDataCenterId());
        Host host = _hostDao.findById(vm.getHostId()); 
        DeployDestination dest = new DeployDestination(dc, null, null, host);
        
        //check vm state
        if (vm.getState() == State.Running) {
            //1) allocate and prepare nic
            NicProfile nic = _networkMgr.createNicForVm(network, requested, context, vmProfile, true);
            
            //2) Convert vmProfile to vmTO
            HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
            VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
            
            //3) Convert nicProfile to NicTO
            NicTO nicTO = toNicTO(nic, vmProfile.getVirtualMachine().getHypervisorType());
            
            //4) plug the nic to the vm
            VirtualMachineGuru vmGuru = getVmGuru(vmVO);
            
            s_logger.debug("Plugging nic for vm " + vm + " in network " + network);
            if (vmGuru.plugNic(network, nicTO, vmTO, context, dest)) {
                s_logger.debug("Nic is plugged successfully for vm " + vm + " in network " + network + ". Vm  is a part of network now");
                return nic;
            } else {
                s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network);
                return null;
            }
        } else if (vm.getState() == State.Stopped) {
            //1) allocate nic
            return _networkMgr.createNicForVm(network, requested, context, vmProfile, false);
        } else {
            s_logger.warn("Unable to add vm " + vm + " to network  " + network);
            throw new ResourceUnavailableException("Unable to add vm " + vm + " to network, is not in the right state",
                    DataCenter.class, vm.getDataCenterIdToDeployIn());
        }
    }


    @Override
    public NicTO toNicTO(NicProfile nic, HypervisorType hypervisorType) {
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(hypervisorType);
        
        NicTO nicTO = hvGuru.toNicTO(nic);
        return nicTO;
    }
    
    @Override
    public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException {
        VMInstanceVO vmVO = _vmDao.findById(vm.getId());
        ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), 
                _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
        
        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, 
                null, null, null);
        
        DataCenter dc = _configMgr.getZone(network.getDataCenterId());
        Host host = _hostDao.findById(vm.getHostId()); 
        DeployDestination dest = new DeployDestination(dc, null, null, host);
        VirtualMachineGuru vmGuru = getVmGuru(vmVO);
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
        VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
        
        Nic nic = null;
        
        if (broadcastUri != null) {
            nic = _nicsDao.findByInstanceIdNetworkIdAndBroadcastUri(network.getId(), vm.getId(), broadcastUri.toString());
        } else {
            nic = _networkMgr.getNicInNetwork(vm.getId(), network.getId());
        }
        
        NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), 
                _networkMgr.getNetworkRate(network.getId(), vm.getId()), 
                _networkMgr.isSecurityGroupSupportedInNetwork(network), 
                _networkMgr.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
        
        //1) Unplug the nic
        NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType());
        s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network);
        boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest);
        if (result) {
            s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
        } else {
            s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
            return false;
        }
        
        //2) Release the nic
        _networkMgr.releaseNic(vmProfile, nic);
        s_logger.debug("Successfully released nic " + nic +  "for vm " + vm);
        
        //3) Remove the nic
        _networkMgr.removeNic(vmProfile, nic);
        return result;
    }
   
}
>>>>>>> 165b85fab5ea301289fceca30b53618d0453d36b
Solution content
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                }
            }
        return _name;
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.vm;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.ejb.Local;
import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.OnError;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.agent.api.ClusterSyncAnswer;
import com.cloud.agent.api.ClusterSyncCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.Commands;
import com.cloud.agent.manager.allocator.HostAllocator;
import com.cloud.alert.AlertManager;
import com.cloud.capacity.CapacityManager;
import com.cloud.cluster.ClusterManager;
import com.cloud.cluster.StackMaid;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
    }
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ManagementServerException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.VirtualMachineMigrationException;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.ha.HighAvailabilityManager.WorkType;
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.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.resource.ResourceManager;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.Journal;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.ItWorkVO.Step;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;

@Local(value = VirtualMachineManager.class)
public class VirtualMachineManagerImpl implements VirtualMachineManager, Listener {
    private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class);

    String _name;
    @Inject
    protected StorageManager _storageMgr;
    @Inject
    protected NetworkManager _networkMgr;
    @Inject
    protected AgentManager _agentMgr;
    @Inject
    protected VMInstanceDao _vmDao;
    @Inject

    protected ServiceOfferingDao _offeringDao;
    @Inject
    protected VMTemplateDao _templateDao;
    @Inject
    protected UserDao _userDao;
    @Inject
    protected AccountDao _accountDao;
    @Inject
    protected DomainDao _domainDao;
    @Inject
    protected ClusterManager _clusterMgr;
    @Inject
    protected ItWorkDao _workDao;
    @Inject
    protected UserVmDao _userVmDao;
    @Inject
    protected DomainRouterDao _routerDao;
    @Inject
    protected ConsoleProxyDao _consoleDao;
    @Inject
    protected SecondaryStorageVmDao _secondaryDao;
    @Inject
    protected NicDao _nicsDao;
    @Inject
    protected AccountManager _accountMgr;
    @Inject
    protected HostDao _hostDao;
    @Inject
    protected AlertManager _alertMgr;
    @Inject
    protected GuestOSCategoryDao _guestOsCategoryDao;
    @Inject
    protected GuestOSDao _guestOsDao;
    @Inject
    protected VolumeDao _volsDao;
    @Inject
    protected ConsoleProxyManager _consoleProxyMgr;
    @Inject
    protected ConfigurationManager _configMgr;
    @Inject
    protected CapacityManager _capacityMgr;
    @Inject
    protected HighAvailabilityManager _haMgr;
    @Inject
    protected HostPodDao _podDao;
    @Inject
    protected DataCenterDao _dcDao;
    @Inject
    protected StoragePoolDao _storagePoolDao;
    @Inject
    protected HypervisorGuruManager _hvGuruMgr;
    @Inject
    protected NetworkDao _networkDao;

    @Inject(adapter = DeploymentPlanner.class)
    protected Adapters _planners;

    @Inject(adapter = HostAllocator.class)
    protected Adapters _hostAllocators;

    @Inject
    protected ResourceManager _resourceMgr;

    Map> _vmGurus = new HashMap>();
    protected StateMachine2 _stateMachine;

    ScheduledExecutorService _executor = null;
    protected int _operationTimeout;

    protected int _retry;
    protected long _nodeId;
    protected long _cleanupWait;
    protected long _cleanupInterval;
    protected long _cancelWait;
    protected long _opWaitInterval;
    protected int _lockStateRetry;
    protected boolean _forceStop;

    @Override
    public  void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) {
        synchronized (_vmGurus) {
            _vmGurus.put(type, guru);
        }
    }

    @Override
    @DB
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Pair rootDiskOffering,
            List> dataDiskOfferings, List> networks, Map params, DeploymentPlan plan,
            HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocating entries for VM: " + vm);
        }

        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, params);

        vm.setDataCenterId(plan.getDataCenterId());
        if (plan.getPodId() != null) {
            vm.setPodId(plan.getPodId());
        }
        assert (plan.getClusterId() == null && plan.getPoolId() == null) : "We currently don't support cluster and pool preset yet";

        @SuppressWarnings("unchecked")
        VirtualMachineGuru guru = (VirtualMachineGuru) _vmGurus.get(vm.getType());

        Transaction txn = Transaction.currentTxn();
        txn.start();
        vm = guru.persist(vm);

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocating nics for " + vm);
        }
        
        try {
            _networkMgr.allocate(vmProfile, networks);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Concurrent operation while trying to allocate resources for the VM", e);
        }

        if (dataDiskOfferings == null) {
            dataDiskOfferings = new ArrayList>(0);
        }

        if (s_logger.isDebugEnabled()) {
        } catch (ConcurrentOperationException e) {
            s_logger.debug("Allocaing disks for " + vm);
        }

        if (template.getFormat() == ImageFormat.ISO) {
            _storageMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner);
        } else if (template.getFormat() == ImageFormat.BAREMETAL) {
            // Do nothing
        } else {
            _storageMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
        }

        for (Pair offering : dataDiskOfferings) {
            _storageMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
        }

        txn.commit();
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Allocation completed for VM: " + vm);
        }

        return vm;
    }

    @Override
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, Pair dataDiskOffering,
            List> networks, DeploymentPlan plan, HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        List> diskOfferings = new ArrayList>(1);
        if (dataDiskOffering != null) {
            diskOfferings.add(dataDiskOffering);
        }
        return allocate(vm, template, serviceOffering, new Pair(serviceOffering, rootSize), diskOfferings, networks, null, plan, hyperType, owner);
    }

    @Override
    public  T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, List> networks, DeploymentPlan plan,
            HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
        return allocate(vm, template, serviceOffering, new Pair(serviceOffering, null), null, networks, null, plan, hyperType, owner);
    }

    @SuppressWarnings("unchecked")
    private  VirtualMachineGuru getVmGuru(T vm) {
        return (VirtualMachineGuru) _vmGurus.get(vm.getType());
    }

    @SuppressWarnings("unchecked")
    private  VirtualMachineGuru getBareMetalVmGuru(T vm) {
        return (VirtualMachineGuru) _vmGurus.get(VirtualMachine.Type.UserBareMetal);
    }

    @Override
    public  boolean expunge(T vm, User caller, Account account) throws ResourceUnavailableException {
        try {
            if (advanceExpunge(vm, caller, account)) {
                // Mark vms as removed
                remove(vm, caller, account);
                return true;
            } else {
                s_logger.info("Did not expunge " + vm);
                return false;
            }
        } catch (OperationTimedoutException e) {
            throw new CloudRuntimeException("Operation timed out", e);
            throw new CloudRuntimeException("Concurrent operation ", e);
        }
    }

    @Override
    public  boolean advanceExpunge(T vm, User caller, Account account) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        if (vm == null || vm.getRemoved() != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vm);
            }
            return true;
        }

        if (!this.advanceStop(vm, false, caller, account)) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to stop the VM so we can't expunge it.");
            }
        }

        try {
            if (!stateTransitTo(vm, VirtualMachine.Event.ExpungeOperation, vm.getHostId())) {
                s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
                return false;
            }
        } catch (NoTransitionException e) {
            s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
            return false;
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Destroying vm " + vm);
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        s_logger.debug("Cleaning up NICS");
        _networkMgr.cleanupNics(profile);
        // Clean up volumes based on the vm's instance id
        _storageMgr.cleanupVolumes(vm.getId());

        VirtualMachineGuru guru = getVmGuru(vm);
        guru.finalizeExpunge(vm);

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Expunged " + vm);
        }

        return true;
    }

    @Override
    public boolean start() {
        _executor.scheduleAtFixedRate(new CleanupTask(), _cleanupInterval, _cleanupInterval, TimeUnit.SECONDS);
        cancelWorkItems(_nodeId);
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean configure(String name, Map xmlParams) throws ConfigurationException {
        _name = name;

        ComponentLocator locator = ComponentLocator.getCurrentLocator();
        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
        Map params = configDao.getConfiguration(xmlParams);

        _retry = NumbersUtil.parseInt(params.get(Config.StartRetry.key()), 10);

        ReservationContextImpl.setComponents(_userDao, _domainDao, _accountDao);
        VirtualMachineProfileImpl.setComponents(_offeringDao, _templateDao, _accountDao);

        _cancelWait = NumbersUtil.parseLong(params.get(Config.VmOpCancelInterval.key()), 3600);
        _cleanupWait = NumbersUtil.parseLong(params.get(Config.VmOpCleanupWait.key()), 3600);
        _cleanupInterval = NumbersUtil.parseLong(params.get(Config.VmOpCleanupInterval.key()), 86400) * 1000;
        _opWaitInterval = NumbersUtil.parseLong(params.get(Config.VmOpWaitInterval.key()), 120) * 1000;
        _lockStateRetry = NumbersUtil.parseInt(params.get(Config.VmOpLockStateRetry.key()), 5);
        _operationTimeout = NumbersUtil.parseInt(params.get(Config.Wait.key()), 1800) * 2;
        _forceStop = Boolean.parseBoolean(params.get(Config.VmDestroyForcestop.key()));

        _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vm-Operations-Cleanup"));
        _nodeId = _clusterMgr.getManagementNodeId();

        _agentMgr.registerForHostEvents(this, true, true, true);

        return true;
    }

    @Override
    public String getName() {
    protected VirtualMachineManagerImpl() {
        setStateMachine();
    }

    @Override
    public  T start(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException {
        return start(vm, params, caller, account, null);
    }

    @Override
    public  T start(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException,
    ResourceUnavailableException {
        try {
            return advanceStart(vm, params, caller, account, planToDeploy);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to start a VM due to concurrent operation", e);
        }
    }

                    continue;
    protected boolean checkWorkItems(VMInstanceVO vm, State state) throws ConcurrentOperationException {
        while (true) {
            ItWorkVO vo = _workDao.findByOutstandingWork(vm.getId(), state);
            if (vo == null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to find work for VM: " + vm + " and state: " + state);
                }
                return true;
            }

            if (vo.getStep() == Step.Done) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Work for " + vm + " is " + vo.getStep());
                }
                return true;
            }

            if (vo.getSecondsTaskIsInactive() > _cancelWait) {
                s_logger.warn("The task item for vm " + vm + " has been inactive for " + vo.getSecondsTaskIsInactive());
                return false;
            }

            try {
                Thread.sleep(_opWaitInterval);
            } catch (InterruptedException e) {
                s_logger.info("Waiting for " + vm + " but is interrupted");
                throw new ConcurrentOperationException("Waiting for " + vm + " but is interrupted");
            }
            s_logger.debug("Waiting some more to make sure there's no activity on " + vm);
        }

    }

    @DB
    protected  Ternary changeToStartState(VirtualMachineGuru vmGuru, T vm, User caller, Account account)
            throws ConcurrentOperationException {
        long vmId = vm.getId();

        ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Starting, vm.getType(), vm.getId());
        int retry = _lockStateRetry;
        while (retry-- != 0) {
            Transaction txn = Transaction.currentTxn();
            Ternary result = null;
            txn.start();
            try {
                Journal journal = new Journal.LogJournal("Creating " + vm, s_logger);
                work = _workDao.persist(work);
                ReservationContextImpl context = new ReservationContextImpl(work.getId(), journal, caller, account);

                if (stateTransitTo(vm, Event.StartRequested, null, work.getId())) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Successfully transitioned to start state for " + vm + " reservation id = " + work.getId());
                    }
                    result = new Ternary(vmGuru.findById(vmId), context, work);
                    txn.commit();
                    return result;
                }
            } catch (NoTransitionException e) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Unable to transition into Starting state due to " + e.getMessage());
                }
            } finally {
                if (result == null) {
                    txn.rollback();
                }
            }

            VMInstanceVO instance = _vmDao.findById(vmId);
            if (instance == null) {
                throw new ConcurrentOperationException("Unable to acquire lock on " + vm);
            }

            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Determining why we're unable to update the state to Starting for " + instance + ".  Retry=" + retry);
            }

            State state = instance.getState();
            if (state == State.Running) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("VM is already started: " + vm);
                }
                return null;
            }

            if (state.isTransitional()) {
                if (!checkWorkItems(vm, state)) {
                    throw new ConcurrentOperationException("There are concurrent operations on " + vm);
                } else {

            if (state != State.Stopped) {
                s_logger.debug("VM " + vm + " is not in a state to be started: " + state);
                return null;
            }
        }

        throw new ConcurrentOperationException("Unable to change the state of " + vm);
    }

    protected  boolean changeState(T vm, Event event, Long hostId, ItWorkVO work, Step step) throws NoTransitionException {
        // FIXME: We should do this better.
        Step previousStep = work.getStep();
        _workDao.updateStep(work, step);
        boolean result = false;
        try {
            result = stateTransitTo(vm, event, hostId);
            return result;
        } finally {
            if (!result) {
                _workDao.updateStep(work, previousStep);
            }
        }
    }

    @Override
    public  T advanceStart(T vm, Map params, User caller, Account account) throws InsufficientCapacityException,
    ConcurrentOperationException, ResourceUnavailableException {
        return advanceStart(vm, params, caller, account, null);
    }

    @Override
    public  T advanceStart(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy)
            throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
        long vmId = vm.getId();
        VirtualMachineGuru vmGuru;
        if (vm.getHypervisorType() == HypervisorType.BareMetal) {
            vmGuru = getBareMetalVmGuru(vm);
        } else {
            vmGuru = getVmGuru(vm);
        }

        vm = vmGuru.findById(vm.getId());
        Ternary start = changeToStartState(vmGuru, vm, caller, account);
        if (start == null) {
            return vmGuru.findById(vmId);
        }

        vm = start.first();
        ReservationContext ctx = start.second();
        ItWorkVO work = start.third();

        T startedVm = null;
        ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId());
        VMTemplateVO template = _templateDao.findById(vm.getTemplateId());

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Trying to deploy VM, vm has dcId: " + vm.getDataCenterIdToDeployIn() + " and podId: " + vm.getPodIdToDeployIn());
        }
        DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), null, null, null, null, ctx);
        if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("advanceStart: DeploymentPlan is provided, using dcId:" + planToDeploy.getDataCenterId() + ", podId: " + planToDeploy.getPodId() + ", clusterId: "
                        + planToDeploy.getClusterId() + ", hostId: " + planToDeploy.getHostId() + ", poolId: " + planToDeploy.getPoolId());
            }

            plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId(), ctx);
        }

        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());

        boolean canRetry = true;
        try {
            Journal journal = start.second().getJournal();

            ExcludeList avoids = null;
            if (planToDeploy != null) {
                avoids = planToDeploy.getAvoids();
            }
            if (avoids == null) {
                avoids = new ExcludeList();
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", clusters: " + avoids.getClustersToAvoid() + ", hosts: " + avoids.getHostsToAvoid());
            }



            boolean planChangedByVolume = false;
            boolean reuseVolume = true;
            DataCenterDeployment originalPlan = plan;

            int retry = _retry;
            boolean recreate = false;
            while (retry-- != 0) { // It's != so that it can match -1.

                if(reuseVolume){
                    // edit plan if this vm's ROOT volume is in READY state already
                    List vols = _volsDao.findReadyRootVolumesByInstance(vm.getId());
                    for (VolumeVO vol : vols) {
                        // make sure if the templateId is unchanged. If it is changed,
                        // let planner
                        // reassign pool for the volume even if it ready.
                        Long volTemplateId = vol.getTemplateId();
                        if (volTemplateId != null && volTemplateId.longValue() != template.getId()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug(vol + " of " + vm + " is READY, but template ids don't match, let the planner reassign a new pool");
                            }
                            continue;
                        }
    
                        StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
                        if (!pool.isInMaintenance()) {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Root volume is ready, need to place VM in volume's cluster");
                            }
                            long rootVolDcId = pool.getDataCenterId();
                            Long rootVolPodId = pool.getPodId();
                            Long rootVolClusterId = pool.getClusterId();
                            if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) {
                                Long clusterIdSpecified = planToDeploy.getClusterId();
                                if (clusterIdSpecified != null && rootVolClusterId != null) {
                                    if (rootVolClusterId.longValue() != clusterIdSpecified.longValue()) {
                                        // cannot satisfy the plan passed in to the
                                        // planner
                                        if (s_logger.isDebugEnabled()) {
                                            s_logger.debug("Cannot satisfy the deployment plan passed in since the ready Root volume is in different cluster. volume's cluster: " + rootVolClusterId
                                                    + ", cluster specified: " + clusterIdSpecified);
                                        }
                                        throw new ResourceUnavailableException("Root volume is ready in different cluster, Deployment plan provided cannot be satisfied, unable to create a deployment for "
                                                + vm, Cluster.class, clusterIdSpecified);
                                    }
                                }
                                plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), vol.getPoolId(), null, ctx);
                            }else{
                                plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, ctx);
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug(vol + " is READY, changing deployment plan to use this pool's dcId: " + rootVolDcId + " , podId: " + rootVolPodId + " , and clusterId: " + rootVolClusterId);
                                }
                                planChangedByVolume = true;
                            }
                        }
                    }
                }
                
                VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, account, params);
                DeployDestination dest = null;
                for (DeploymentPlanner planner : _planners) {
                    if (planner.canHandle(vmProfile, plan, avoids)) {
                        dest = planner.plan(vmProfile, plan, avoids);
                    } else {
                        continue;
                    }
                    if (dest != null) {
                        avoids.addHost(dest.getHost().getId());
                        journal.record("Deployment found ", vmProfile, dest);
                        break;
                    }
                }

                if (dest == null) {
                    if (planChangedByVolume) {
                        plan = originalPlan;
                        planChangedByVolume = false;
                        //do not enter volume reuse for next retry, since we want to look for resorces outside the volume's cluster
                        reuseVolume = false;
                        continue;
                    }
                    throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
                }

                long destHostId = dest.getHost().getId();
                vm.setPodId(dest.getPod().getId());

                try {
                    if (!changeState(vm, Event.OperationRetry, destHostId, work, Step.Prepare)) {
                        throw new ConcurrentOperationException("Unable to update the state of the Virtual Machine");
                    }
                } catch (NoTransitionException e1) {
                    throw new ConcurrentOperationException(e1.getMessage());
                }

                try {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("VM is being created in podId: " + vm.getPodIdToDeployIn());
                    }
                    _networkMgr.prepare(vmProfile, dest, ctx); 
                    if (vm.getHypervisorType() != HypervisorType.BareMetal) {
                        _storageMgr.prepare(vmProfile, dest, recreate);
                        recreate = false;
                    }
                    //since StorageMgr succeeded in volume creation, reuse Volume for further tries until current cluster has capacity
                    if(!reuseVolume){
                        reuseVolume = true;
                    }
                    
                    Commands cmds = null;
                    vmGuru.finalizeVirtualMachineProfile(vmProfile, dest, ctx);

                    VirtualMachineTO vmTO = hvGuru.implement(vmProfile);

                    cmds = new Commands(OnError.Stop);
                    cmds.addCommand(new StartCommand(vmTO));

                    vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx);


                    work = _workDao.findById(work.getId());
                    if (work == null || work.getStep() != Step.Prepare) {
                        throw new ConcurrentOperationException("Work steps have been changed: " + work);
                    }
                    _workDao.updateStep(work, Step.Starting);

                    _agentMgr.send(destHostId, cmds);
                    
                    _workDao.updateStep(work, Step.Started);
                    
                    
                    StartAnswer startAnswer = cmds.getAnswer(StartAnswer.class);
                    if (startAnswer != null && startAnswer.getResult()) {
                        String host_guid = startAnswer.getHost_guid();
                        if( host_guid != null ) {
                            HostVO finalHost = _resourceMgr.findHostByGuid(host_guid);
                            if (finalHost == null ) {
        } catch (Exception e) {
                                throw new CloudRuntimeException("Host Guid " + host_guid + " doesn't exist in DB, something wrong here");
                            }
                            destHostId = finalHost.getId();
                        }
                        if (vmGuru.finalizeStart(vmProfile, destHostId, cmds, ctx)) {
                            if (!changeState(vm, Event.OperationSucceeded, destHostId, work, Step.Done)) {
                                throw new ConcurrentOperationException("Unable to transition to a new state.");
                            }
                            startedVm = vm;
                            if (s_logger.isDebugEnabled()) {
                                s_logger.debug("Start completed for VM " + vm);
                            }
                            return startedVm;
                        } else {
                            if (s_logger.isDebugEnabled()) {
                                s_logger.info("The guru did not like the answers so stopping " + vm);
                            }
                           
                            StopCommand cmd = new StopCommand(vm.getInstanceName());
                            StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd);
                            if (answer == null || !answer.getResult()) {
                                s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers")); 
                                _haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop);
                                throw new ExecutionException("Unable to stop " + vm + " so we are unable to retry the start operation");
                            }
                            if (vmGuru.recreateNeeded(vmProfile, destHostId, cmds, ctx)) {
                            	recreate = true;
                            } else {
                            	throw new ExecutionException("Unable to start " + vm + " due to error in finalizeStart, not retrying");
                            }
                        }
                    }
                    s_logger.info("Unable to start VM on " + dest.getHost() + " due to " + (startAnswer == null ? " no start answer" : startAnswer.getDetails()));
                    
                } catch (OperationTimedoutException e) {
                    s_logger.debug("Unable to send the start command to host " + dest.getHost());
                    if (e.isActive()) {
                        _haMgr.scheduleStop(vm, destHostId, WorkType.CheckStop);
                    }
                    canRetry = false;
                    throw new AgentUnavailableException("Unable to start " + vm.getHostName(), destHostId, e);
                } catch (ResourceUnavailableException e) {
                    s_logger.info("Unable to contact resource.", e);
                    if (!avoids.add(e)) {
                        if (e.getScope() == Volume.class || e.getScope() == Nic.class) {
                            throw e;
                        } else {
                            s_logger.warn("unexpected ResourceUnavailableException : " + e.getScope().getName(), e);
                            throw e;
                        }
                    }
                } catch (InsufficientCapacityException e) {
                    s_logger.info("Insufficient capacity ", e);
                    if (!avoids.add(e)) {
                        if (e.getScope() == Volume.class || e.getScope() == Nic.class) {
                            throw e;
                        } else {
                            s_logger.warn("unexpected InsufficientCapacityException : " + e.getScope().getName(), e);
                        }
                    }
                } catch (Exception e) {
                    s_logger.error("Failed to start instance " + vm, e);
                    throw new AgentUnavailableException("Unable to start instance due to " + e.getMessage(), destHostId, e);
                } finally {
                    if (startedVm == null && canRetry) {
                        Step prevStep = work.getStep();
                        _workDao.updateStep(work, Step.Release);
                        if (prevStep == Step.Started || prevStep == Step.Starting) {
                            cleanup(vmGuru, vmProfile, work, Event.OperationFailed, false, caller, account);
                        } else {
                            //if step is not starting/started, send cleanup command with force=true
            s_logger.warn("Unable to release storage resources.", e);
                            cleanup(vmGuru, vmProfile, work, Event.OperationFailed, true, caller, account);
                        }
                    }
                }
            }
        } finally {
            if (startedVm == null) {
                if (canRetry) {
                    try {
                        changeState(vm, Event.OperationFailed, null, work, Step.Done);
                    } catch (NoTransitionException e) {
                        throw new ConcurrentOperationException(e.getMessage());
                    }
                }
            }
        }

        return startedVm;
    }

    @Override
    public  boolean stop(T vm, User user, Account account) throws ResourceUnavailableException {
        try {
            return advanceStop(vm, false, user, account);
        } catch (OperationTimedoutException e) {
            throw new AgentUnavailableException("Unable to stop vm because the operation to stop timed out", vm.getHostId(), e);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to stop vm because of a concurrent operation", e);
        }
    }

    protected  boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) {
        VMInstanceVO vm = profile.getVirtualMachine();
        StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
        try {
            Answer answer = _agentMgr.send(vm.getHostId(), stop);
            if (!answer.getResult()) {
                s_logger.debug("Unable to stop VM due to " + answer.getDetails());
                return false;
            }

            guru.finalizeStop(profile, (StopAnswer) answer);
        } catch (AgentUnavailableException e) {
            if (!force) {
                return false;
            }
        } catch (OperationTimedoutException e) {
            if (!force) {
                return false;
            }
        }

        return true;
    }

    protected  boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile, ItWorkVO work, Event event, boolean force, User user, Account account) {
        T vm = profile.getVirtualMachine();
        State state = vm.getState();
        s_logger.debug("Cleaning up resources for the vm " + vm + " in " + state + " state");
        if (state == State.Starting) {
            Step step = work.getStep();
            if (step == Step.Starting && !force) {
                s_logger.warn("Unable to cleanup vm " + vm + "; work state is incorrect: " + step);
                return false;
            }

            if (step == Step.Started || step == Step.Starting || step == Step.Release) {
                if (vm.getHostId() != null) {
                    if (!sendStop(guru, profile, force)) {
                        s_logger.warn("Failed to stop vm " + vm + " in " + State.Starting + " state as a part of cleanup process");
                        return false;
                    }
                }
            }

            if (step != Step.Release && step != Step.Prepare && step != Step.Started && step != Step.Starting) {
                s_logger.debug("Cleanup is not needed for vm " + vm + "; work state is incorrect: " + step);
                return true;
            }
        } else if (state == State.Stopping) {
            if (vm.getHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Stopping + " state as a part of cleanup process");
                    return false;
                }
            }
        } else if (state == State.Migrating) {
            if (vm.getHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process");
                    return false;
                }
            }
            if (vm.getLastHostId() != null) {
                if (!sendStop(guru, profile, force)) {
                    s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process");
                    return false;
                }
            }
        } else if (state == State.Running) {
            if (!sendStop(guru, profile, force)) {
                s_logger.warn("Failed to stop vm " + vm + " in " + State.Running + " state as a part of cleanup process");
                return false;
            }
        }

        try {
            _networkMgr.release(profile, force);
            s_logger.debug("Successfully released network resources for the vm " + vm);
        } catch (Exception e) {
            s_logger.warn("Unable to release some network resources.", e);
        }
        _storageMgr.release(profile);
        s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state");
        return true;
    }

    @Override
    public  boolean advanceStop(T vm, boolean forced, User user, Account account) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        State state = vm.getState();
        if (state == State.Stopped) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM is already stopped: " + vm);
            }
            return true;
        }

        if (state == State.Destroyed || state == State.Expunging || state == State.Error) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Stopped called on " + vm + " but the state is " + state);
            }
            return true;
        }
        // grab outstanding work item if any
        ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found an outstanding work item for this vm " + vm + " with state:" + vm.getState() + ", work id:" + work.getId());
            }
        }
        Long hostId = vm.getHostId();
        if (hostId == null) {
            if (!forced) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("HostId is null but this is not a forced stop, cannot stop vm " + vm + " with state:" + vm.getState());
                }
                return false;
            }
            try {
                stateTransitTo(vm, Event.AgentReportStopped, null, null);
            } catch (NoTransitionException e) {
                s_logger.warn(e.getMessage());
            }
            // mark outstanding work item if any as done
            if (work != null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Updating work item to Done, id:" + work.getId());
                }
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }
            return true;
        }

        VirtualMachineGuru vmGuru = getVmGuru(vm);
        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);

        try {
            if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
                throw new ConcurrentOperationException("VM is being operated on.");
            }
        } catch (NoTransitionException e1) {
            if (!forced) {
                throw new CloudRuntimeException("We cannot stop " + vm + " when it is in state " + vm.getState());
            }
            boolean doCleanup = false;
            if (s_logger.isDebugEnabled()) {
        }
                s_logger.debug("Unable to transition the state but we're moving on because it's forced stop");
            }
            if (state == State.Starting || state == State.Migrating) {
                if (work != null) {
                    doCleanup = true;
                } else {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Unable to cleanup VM: " + vm + " ,since outstanding work item is not found");
                    }
                    throw new CloudRuntimeException("Work item not found, We cannot stop " + vm + " when it is in state " + vm.getState());
                }
            } else if (state == State.Stopping) {
                doCleanup = true;
            }

            if (doCleanup) {
                if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) {
                    try {
                        if (s_logger.isDebugEnabled()) {
                            s_logger.debug("Updating work item to Done, id:" + work.getId());
                        }
        work.setResourceId(dstHostId);
                        return changeState(vm, Event.AgentReportStopped, null, work, Step.Done);
                    } catch (NoTransitionException e) {
                        s_logger.warn("Unable to cleanup " + vm);
                        return false;
                    }
                } else {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Failed to cleanup VM: " + vm);
                    }
                    throw new CloudRuntimeException("Failed to cleanup " + vm + " , current state " + vm.getState());
                }
            }
        }

        if (vm.getState() != State.Stopping) {
            throw new CloudRuntimeException("We cannot proceed with stop VM " + vm + " since it is not in 'Stopping' state, current state: " + vm.getState());
        }

        vmGuru.prepareStop(profile);
        
        StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
        boolean stopped = false;
        StopAnswer answer = null;
        try {
            answer = (StopAnswer) _agentMgr.send(vm.getHostId(), stop);
            stopped = answer.getResult();
            if (!stopped) {
                throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
            }
            vmGuru.finalizeStop(profile, answer);

        } catch (AgentUnavailableException e) {
        } catch (OperationTimedoutException e) {
        } finally {
            if (!stopped) {
                if (!forced) {
                    s_logger.warn("Unable to stop vm " + vm);
                    try {
                        stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
                    } catch (NoTransitionException e) {
                        s_logger.warn("Unable to transition the state " + vm);
                    }
                    return false;
                } else {
                    s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop");
                    vmGuru.finalizeStop(profile, answer);
                }
            }
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug(vm + " is stopped on the host.  Proceeding to release resource held.");
        }

        try {
            _networkMgr.release(profile, forced);
            s_logger.debug("Successfully released network resources for the vm " + vm);
        } catch (Exception e) {
            s_logger.warn("Unable to release some network resources.", e);
        }

        try {
            if (vm.getHypervisorType() != HypervisorType.BareMetal) {
                _storageMgr.release(profile);
                s_logger.debug("Successfully released storage resources for the vm " + vm);
            }
        try {
            if (work != null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Updating the outstanding work item to Done, id:" + work.getId());
                }
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }

            return stateTransitTo(vm, Event.OperationSucceeded, null, null);
        } catch (NoTransitionException e) {
            s_logger.warn(e.getMessage());
            return false;
        }
    }

    private void setStateMachine() {
        _stateMachine = VirtualMachine.State.getStateMachine();
    }

    protected boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId, String reservationId) throws NoTransitionException {
        vm.setReservationId(reservationId);
        return _stateMachine.transitTo(vm, e, new Pair(vm.getHostId(), hostId), _vmDao);
    }

    @Override
    public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) throws NoTransitionException {
        State oldState = vm.getState();
        if (oldState == State.Starting) {
            if (e == Event.OperationSucceeded) {
                vm.setLastHostId(hostId);
            }
        } else if (oldState == State.Stopping) {
            if (e == Event.OperationSucceeded) {
                vm.setLastHostId(vm.getHostId());
            }
        }
        return _stateMachine.transitTo(vm, e, new Pair(vm.getHostId(), hostId), _vmDao);
    }

    @Override
    public  boolean remove(T vm, User user, Account caller) {
        return _vmDao.remove(vm.getId());
    }

    @Override
    public  boolean destroy(T vm, User user, Account caller) throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Destroying vm " + vm);
        }
        if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging || vm.getRemoved() != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find vm or vm is destroyed: " + vm);
            }
            return true;
        }

        if (!advanceStop(vm, _forceStop, user, caller)) {
            s_logger.debug("Unable to stop " + vm);
            return false;
        }

        try {
            if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) {
                s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm);
                return false;
            }
        } catch (NoTransitionException e) {
            s_logger.debug(e.getMessage());
            return false;
        }

        return true;
    }

    protected boolean checkVmOnHost(VirtualMachine vm, long hostId) throws AgentUnavailableException, OperationTimedoutException {
        CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(hostId, new CheckVirtualMachineCommand(vm.getInstanceName()));
        if (!answer.getResult() || answer.getState() == State.Stopped) {
            return false;
        }

        return true;
    }

    @Override
    public  T storageMigration(T vm, StoragePool destPool) {
        VirtualMachineGuru vmGuru = getVmGuru(vm);

        long vmId = vm.getId();
        vm = vmGuru.findById(vmId);

        try {
            stateTransitTo(vm, VirtualMachine.Event.StorageMigrationRequested, null);
        } catch (NoTransitionException e) {
            s_logger.debug("Unable to migrate vm: " + e.toString());
            throw new CloudRuntimeException("Unable to migrate vm: " + e.toString());
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        boolean migrationResult = false;
        try {
            migrationResult = _storageMgr.StorageMigration(profile, destPool);

            if (migrationResult) {
                //if the vm is migrated to different pod in basic mode, need to reallocate ip

                if (vm.getPodIdToDeployIn() != destPool.getPodId()) {
                    DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterIdToDeployIn(), destPool.getPodId(), null, null, null, null);
                    VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, null, null, null, null);
                    _networkMgr.reallocate(vmProfile, plan);
                }

                //when start the vm next time, don;'t look at last_host_id, only choose the host based on volume/storage pool
                vm.setLastHostId(null);
                vm.setPodId(destPool.getPodId());
            } else {
                s_logger.debug("Storage migration failed");
            }
        } catch (ConcurrentOperationException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientVirtualNetworkCapcityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientAddressCapacityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } catch (InsufficientCapacityException e) {
            s_logger.debug("Failed to migration: " + e.toString());
            throw new CloudRuntimeException("Failed to migration: " + e.toString());
        } finally {
            try {
                stateTransitTo(vm, VirtualMachine.Event.AgentReportStopped, null);
            } catch (NoTransitionException e) {
                s_logger.debug("Failed to change vm state: " + e.toString());
                throw new CloudRuntimeException("Failed to change vm state: " + e.toString());
            }
        }

        return vm;
    }

    @Override
    public  T migrate(T vm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
    VirtualMachineMigrationException {
        s_logger.info("Migrating " + vm + " to " + dest);

        long dstHostId = dest.getHost().getId();
        Host fromHost = _hostDao.findById(srcHostId);
        if (fromHost == null) {
            s_logger.info("Unable to find the host to migrate from: " + srcHostId);
            throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
        }

        if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
            s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
            throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
        }

        VirtualMachineGuru vmGuru = getVmGuru(vm);

        long vmId = vm.getId();
        vm = vmGuru.findById(vmId);
        if (vm == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find the vm " + vm);
            }
            throw new ManagementServerException("Unable to find a virtual machine with id " + vmId);
        }

        if (vm.getState() != State.Running) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
            }
            throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString());
        }

        short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
        if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
            alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE;
        } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
            alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        _networkMgr.prepareNicForMigration(profile, dest);
        _storageMgr.prepareForMigration(profile, dest);

        VirtualMachineTO to = toVmTO(profile);
        PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);

        ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
        work.setStep(Step.Prepare);
        work.setResourceType(ItWorkVO.ResourceType.Host);
        work = _workDao.persist(work);

        PrepareForMigrationAnswer pfma = null;
        try {
            pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
            if (!pfma.getResult()) {
                String msg = "Unable to prepare for migration due to " + pfma.getDetails();
                pfma = null;
                throw new AgentUnavailableException(msg, dstHostId);
            }
        } catch (OperationTimedoutException e1) {
            throw new AgentUnavailableException("Operation timed out", dstHostId);
        } finally {
            if (pfma == null) {
                work.setStep(Step.Done);
                _workDao.update(work.getId(), work);
            }
        }

        vm.setLastHostId(srcHostId);
        try {
            if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
                s_logger.info("Migration cancelled because state has changed: " + vm);
                throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
            }
        } catch (NoTransitionException e1) {
            s_logger.info("Migration cancelled because " + e1.getMessage());
            throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
        }

        boolean migrated = false;
        try {
            boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
            MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
            mc.setHostGuid(dest.getHost().getGuid());

            try {
                MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
                if (!ma.getResult()) {
                    s_logger.error("Unable to migrate due to " + ma.getDetails());
                    return null;
                }
            } catch (OperationTimedoutException e) {
                if (e.isActive()) {
                    s_logger.warn("Active migration command so scheduling a restart for " + vm);
                    _haMgr.scheduleRestart(vm, true);
                }
                throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
            }

            try {
                if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
                    throw new ConcurrentOperationException("Unable to change the state for " + vm);
                }
            } catch (NoTransitionException e1) {
                throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
            }

            try {
                if (!checkVmOnHost(vm, dstHostId)) {
                    s_logger.error("Unable to complete migration for " + vm);
                    try {
                        _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null);
                    } catch (AgentUnavailableException e) {
                        s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
                    }
                    cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                    return null;
                }
            } catch (OperationTimedoutException e) {
            }

            migrated = true;
            return vm;
        } finally {
            if (!migrated) {
                s_logger.info("Migration was unsuccessful.  Cleaning up: " + vm);

                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
                        + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed.  Please check logs.");
                try {
                    _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null);
                } catch (AgentUnavailableException ae) {
                    s_logger.info("Looks like the destination Host is unavailable for cleanup");
                }

                try {
                    stateTransitTo(vm, Event.OperationFailed, srcHostId);
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
            }

            work.setStep(Step.Done);
            _workDao.update(work.getId(), work);
        }
    }

    @Override
    public VirtualMachineTO toVmTO(VirtualMachineProfile profile) {
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getVirtualMachine().getHypervisorType());
        VirtualMachineTO to = hvGuru.implement(profile);
        return to;
    }

    protected void cancelWorkItems(long nodeId) {
        GlobalLock scanLock = GlobalLock.getInternLock("vmmgr.cancel.workitem");

        try {
            if (scanLock.lock(3)) {
                try {
                    List works = _workDao.listWorkInProgressFor(nodeId);
                    for (ItWorkVO work : works) {
                        s_logger.info("Handling unfinished work item: " + work);
                        try {
                            VMInstanceVO vm = _vmDao.findById(work.getInstanceId());
                            if (vm != null) {
                                if (work.getType() == State.Starting) {
                                    _haMgr.scheduleRestart(vm, true);
                                    work.setManagementServerId(_nodeId);
                                    _workDao.update(work.getId(), work);
                                } else if (work.getType() == State.Stopping) {
                                    _haMgr.scheduleStop(vm, vm.getHostId(), WorkType.CheckStop);
                                    work.setManagementServerId(_nodeId);
                                    _workDao.update(work.getId(), work);
                                } else if (work.getType() == State.Migrating) {
                                    _haMgr.scheduleMigration(vm);
                                    work.setStep(Step.Done);
                                    _workDao.update(work.getId(), work);
                                }
                            }
                        } catch (Exception e) {
                            s_logger.error("Error while handling " + work, e);
                        }
                    }
                } finally {
                    scanLock.unlock();
                }
            }
        } finally {
            scanLock.releaseRef();
        }
    }

    @Override
    public boolean migrateAway(VirtualMachine.Type vmType, long vmId, long srcHostId) throws InsufficientServerCapacityException, VirtualMachineMigrationException {
        VirtualMachineGuru vmGuru = _vmGurus.get(vmType);
        VMInstanceVO vm = vmGuru.findById(vmId);
        if (vm == null) {
            s_logger.debug("Unable to find a VM for " + vmId);
            return true;
        }

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);

        Long hostId = vm.getHostId();
        if (hostId == null) {
            s_logger.debug("Unable to migrate because the VM doesn't have a host id: " + vm);
            return true;
        }

        Host host = _hostDao.findById(hostId);

        DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), null, null, null);
        ExcludeList excludes = new ExcludeList();
        excludes.addHost(hostId);

        DeployDestination dest = null;
        while (true) {
            }
            for (DeploymentPlanner planner : _planners) {
                if (planner.canHandle(profile, plan, excludes)) {
                    dest = planner.plan(profile, plan, excludes);
                } else {
                    continue;
                }

                if (dest != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Planner " + planner + " found " + dest + " for migrating to.");
                    }
                    break;
                }
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Planner " + planner + " was unable to find anything.");
                }
            }

            if (dest == null) {
                throw new InsufficientServerCapacityException("Unable to find a server to migrate to.", host.getClusterId());
            }

            excludes.addHost(dest.getHost().getId());
            VMInstanceVO vmInstance = null;
            try {
                vmInstance = migrate(vm, srcHostId, dest);
            } catch (ResourceUnavailableException e) {
                s_logger.debug("Unable to migrate to unavailable " + dest);
            } catch (ConcurrentOperationException e) {
                s_logger.debug("Unable to migrate VM due to: " + e.getMessage());
            } catch (ManagementServerException e) {
                s_logger.debug("Unable to migrate VM: " + e.getMessage());
            } catch (VirtualMachineMigrationException e) {
                s_logger.debug("Got VirtualMachineMigrationException, Unable to migrate: " + e.getMessage());
                if (vm.getState() == State.Starting) {
                    s_logger.debug("VM seems to be still Starting, we should retry migration later");
                    throw e;
                } else {
                    s_logger.debug("Unable to migrate VM, VM is not in Running or even Starting state, current state: " + vm.getState().toString());
                }
            }
            if (vmInstance != null) {
                return true;
            }
            try {
                boolean result = advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                return result;
            } catch (ResourceUnavailableException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            } catch (ConcurrentOperationException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            } catch (OperationTimedoutException e) {
                s_logger.debug("Unable to stop VM due to " + e.getMessage());
            }
            return false;
        }
    }

    protected class CleanupTask implements Runnable {
        @Override
        public void run() {
            s_logger.trace("VM Operation Thread Running");
            try {
                _workDao.cleanup(_cleanupWait);
            } catch (Exception e) {
                s_logger.error("VM Operations failed due to ", e);
        }
    }

    @Override
    public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
        Enumeration en = _hostAllocators.enumeration();
        boolean isMachineUpgradable = true;
        while (isMachineUpgradable && en.hasMoreElements()) {
            final HostAllocator allocator = en.nextElement();
            isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
        }

        return isMachineUpgradable;
    }

    @Override
    public  T reboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException {
        try {
            return advanceReboot(vm, params, caller, account);
        } catch (ConcurrentOperationException e) {
            throw new CloudRuntimeException("Unable to reboot a VM due to concurrent operation", e);
        }
    }

    @Override
    public  T advanceReboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException,
    ConcurrentOperationException, ResourceUnavailableException {
        T rebootedVm = null;

        DataCenter dc = _configMgr.getZone(vm.getDataCenterIdToDeployIn());
        Host host = _hostDao.findById(vm.getHostId());
        Cluster cluster = null;
        if (host != null) {
            cluster = _configMgr.getCluster(host.getClusterId());
        }
        HostPodVO pod = _configMgr.getPod(host.getPodId());
        DeployDestination dest = new DeployDestination(dc, pod, cluster, host);

        try {

            Commands cmds = new Commands(OnError.Stop);
            cmds.addCommand(new RebootCommand(vm.getInstanceName()));
            _agentMgr.send(host.getId(), cmds);

            Answer rebootAnswer = cmds.getAnswer(RebootAnswer.class);
            if (rebootAnswer != null && rebootAnswer.getResult()) {
                rebootedVm = vm;
                return rebootedVm;
            }
            s_logger.info("Unable to reboot VM " + vm + " on " + dest.getHost() + " due to " + (rebootAnswer == null ? " no reboot answer" : rebootAnswer.getDetails()));
        } catch (OperationTimedoutException e) {
            s_logger.warn("Unable to send the reboot command to host " + dest.getHost() + " for the vm " + vm + " due to operation timeout", e);
            throw new CloudRuntimeException("Failed to reboot the vm on host " + dest.getHost());
        }

        return rebootedVm;
    }

    @Override
    public VMInstanceVO findByIdAndType(VirtualMachine.Type type, long vmId) {
        VirtualMachineGuru guru = _vmGurus.get(type);
        return guru.findById(vmId);
    }

    public Command cleanup(String vmName) {
        return new StopCommand(vmName);
    }

    public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) {  
        Commands commands = new Commands(OnError.Continue);

        Map infos = convertToInfos(startup);

        final List vms = _vmDao.listByHostId(hostId);
        s_logger.debug("Found " + vms.size() + " VMs for host " + hostId);
        for (VMInstanceVO vm : vms) {
            AgentVmInfo info = infos.remove(vm.getId());
            VMInstanceVO castedVm = null;
            if (info == null) {
                info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
            } 
            castedVm = info.guru.findById(vm.getId());

            HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
            Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
            if (command != null) {
                commands.addCommand(command);
            }
        }
        
        for (final AgentVmInfo left : infos.values()) {
            boolean found = false;
            for (VirtualMachineGuru vmGuru : _vmGurus.values()) {
                VMInstanceVO vm = vmGuru.findByName(left.name);
                if (vm != null) {
                    found = true;
                    HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                    if(hvGuru.trackVmHostChange()) {
                        Command command = compareState(hostId, vm, left, true, true);
                        if (command != null) {
                            commands.addCommand(command);
                        }
                    } else {
                        s_logger.warn("Stopping a VM, VM " + left.name + " migrate from Host " + vm.getHostId() + " to Host " + hostId );
                        commands.addCommand(cleanup(left.name));
                    }
                    break;
                }
            }
            if ( ! found ) {
                s_logger.warn("Stopping a VM that we have no record of : " + left.name);
                commands.addCommand(cleanup(left.name));
            }
        }

        return commands;
    }

    public Commands deltaHostSync(long hostId, Map newStates) {
        Map states = convertDeltaToInfos(newStates);
        Commands commands = new Commands(OnError.Continue);

        for (Map.Entry entry : states.entrySet()) {
            AgentVmInfo info = entry.getValue();

            VMInstanceVO vm = info.vm;

            Command command = null;
            if (vm != null) {
                HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                command = compareState(hostId, vm, info, false, hvGuru.trackVmHostChange());
            } else {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Cleaning up a VM that is no longer found: " + info.name);
                }
                command = cleanup(info.name);
            }

            if (command != null) {
                commands.addCommand(command);
            }
        }

        return commands;
    }



    public void deltaSync(Map> newStates) {
        Map states = convertToInfos(newStates);

        for (Map.Entry entry : states.entrySet()) {
            AgentVmInfo info = entry.getValue();
            VMInstanceVO vm = info.vm;
            Command command = null;
            if (vm != null) {
                Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
                long hId = host.getId();

                HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
                command = compareState(hId, vm, info, false, hvGuru.trackVmHostChange());
            } else {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Cleaning up a VM that is no longer found : " + info.name);
                }
                command = cleanup(info.name);
            }
            if (command != null){
                try {
                    Host host = _resourceMgr.findHostByGuid(info.getHostUuid());
                    if (host != null){
                        Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
                        if (!answer.getResult()) {
                            s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                        }
                    }
                } catch (Exception e) {
                    s_logger.warn("Unable to stop a VM due to " + e.getMessage());
                }
            }
        }
    }


    public void fullSync(final long clusterId, Map> newStates) {
    	if (newStates==null)return;
        Map infos = convertToInfos(newStates);
        Set set_vms = Collections.synchronizedSet(new HashSet());
        set_vms.addAll(_vmDao.listByClusterId(clusterId));
        set_vms.addAll(_vmDao.listLHByClusterId(clusterId));

        for (VMInstanceVO vm : set_vms) {
            if (vm.isRemoved() || vm.getState() == State.Destroyed  || vm.getState() == State.Expunging) continue;
            AgentVmInfo info =  infos.remove(vm.getId());
            VMInstanceVO castedVm = null;
            if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting))  
            		||  (info != null && (info.state == State.Running && vm.getState() == State.Starting))) 
            {
        }
            	s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " +  (info == null ? "Stopped" : "Running") + " on agent");
                info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
           		
                // Bug 13850- grab outstanding work item if any for this VM state so that we mark it as DONE after we change VM state, else it will remain pending
                ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
                if (work != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Found an outstanding work item for this vm " + vm + " in state:" + vm.getState() + ", work id:" + work.getId());
                    }
                }
                vm.setState(State.Running); // set it as running and let HA take care of it
           		_vmDao.persist(vm);
           		
                if (work != null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Updating outstanding work item to Done, id:" + work.getId());
                    }
                    work.setStep(Step.Done);
                    _workDao.update(work.getId(), work);
                }
           		
                castedVm = info.guru.findById(vm.getId());
                try {
                    Host host = _hostDao.findByGuid(info.getHostUuid());
                    long hostId = host == null ? (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId()) : host.getId();
                    HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
                    Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
                    if (command != null){
                        Answer answer = _agentMgr.send(hostId, command);
                        if (!answer.getResult()) {
                            s_logger.warn("Failed to update state of the VM due to " + answer.getDetails());
                        }
                    }
                } catch (Exception e) {
                    s_logger.warn("Unable to update state of the VM due to exception " + e.getMessage());
                    e.printStackTrace();
                }
            }
            else if (info != null && (vm.getState() == State.Stopped || vm.getState() == State.Stopping)) {
            	 Host host = _hostDao.findByGuid(info.getHostUuid());
                 if (host != null){
                    s_logger.warn("Stopping a VM which is stopped/stopping " + info.name);
                    vm.setState(State.Stopped); // set it as stop and clear it from host
                    vm.setHostId(null);
                    _vmDao.persist(vm);
                     try {
	                     Answer answer = _agentMgr.send(host.getId(), cleanup(info.name));
	                     if (!answer.getResult()) {
	                         s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
	                     }
                     }
                     catch (Exception e) {
                         s_logger.warn("Unable to stop a VM due to " + e.getMessage());
                     }
                 }
            }
            else
            // host id can change
        }
	        if (info != null && vm.getState() == State.Running){
	           // check for host id changes
	           Host host = _hostDao.findByGuid(info.getHostUuid());
	            if (host != null && (vm.getHostId() == null || host.getId() != vm.getHostId())){
    	        	s_logger.info("Found vm " + vm.getInstanceName() + " with inconsistent host in db, new host is " +  host.getId());
        			try {
						stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, host.getId());
					} catch (NoTransitionException e) {
						s_logger.warn(e.getMessage());
					}
        		}
            }
             /* else if(info == null && vm.getState() == State.Stopping) { //Handling CS-13376
                        s_logger.warn("Marking the VM as Stopped as it was still stopping on the CS" +vm.getName());
                        vm.setState(State.Stopped); // Setting the VM as stopped on the DB and clearing it from the host
                        vm.setLastHostId(vm.getHostId());
                        vm.setHostId(null);
                        _vmDao.persist(vm);
                 }*/

        for (final AgentVmInfo left : infos.values()) {
        	if (VirtualMachineName.isValidVmName(left.name)) continue;  // if the vm follows cloudstack naming ignore it for stopping
            try {
                Host host = _hostDao.findByGuid(left.getHostUuid());
                if (host != null){
                    s_logger.warn("Stopping a VM which we do not have any record of " + left.name);
                    Answer answer = _agentMgr.send(host.getId(), cleanup(left.name));
                    if (!answer.getResult()) {
                        s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                    }
                }
            } catch (Exception e) {
                s_logger.warn("Unable to stop a VM due to " + e.getMessage());
            }
        }

    }



    protected Map convertToInfos(final Map> newStates) {
        final HashMap map = new HashMap();
        if (newStates == null) {
            return map;
        }
        Collection> vmGurus = _vmGurus.values();
        boolean is_alien_vm = true;
        long alien_vm_count = -1;
        for (Map.Entry> entry : newStates.entrySet()) {
        	is_alien_vm = true;
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();
                VMInstanceVO vm = vmGuru.findByName(name);
                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().second(), entry.getValue().first()));
                    is_alien_vm = false;
                    break;
                }
                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue().second(), entry.getValue().first()));
                    is_alien_vm = false;
                    break;
                }
            }
            // alien VMs
            if (is_alien_vm){
            	map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, null, entry.getValue().second(), entry.getValue().first()));
            	s_logger.warn("Found an alien VM " + entry.getKey());
            }
        }
        return map;
    }

    protected Map convertToInfos(StartupRoutingCommand cmd) { 
        final Map states = cmd.getVmStates();
        final HashMap map = new HashMap();
        if (states == null) {
            return map;
        }
        Collection> vmGurus = _vmGurus.values();

        for (Map.Entry entry : states.entrySet()) {
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();
                VMInstanceVO vm = vmGuru.findByName(name);
                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().getState(), entry.getValue().getHost() ));
                    break;
                }
                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue().getState(), entry.getValue().getHost() ));
                    break;
                }
            }
        }

        return map;
    }

    protected Map convertDeltaToInfos(final Map states) {
        final HashMap map = new HashMap();

        if (states == null) {
            return map;
        }

        Collection> vmGurus = _vmGurus.values();

        for (Map.Entry entry : states.entrySet()) {
            for (VirtualMachineGuru vmGuru : vmGurus) {
                String name = entry.getKey();

                VMInstanceVO vm = vmGuru.findByName(name);

                if (vm != null) {
                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue()));
                    break;
                }

                Long id = vmGuru.convertToId(name);
                if (id != null) {
                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue()));
                    break;
                }
            }
        }

        return map;
    }



    /**
     * compareState does as its name suggests and compares the states between
     * management server and agent. It returns whether something should be
     * cleaned up
     * 
     */
    protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) {
        State agentState = info.state;
        final String agentName = info.name;
        final State serverState = vm.getState();
        final String serverName = vm.getInstanceName();

        Command command = null;
        s_logger.debug("VM " + serverName + ": cs state = " + serverState + " and realState = " + agentState);
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("VM " + serverName + ": cs state = " + serverState + " and realState = " + agentState);
        }

        if (agentState == State.Error) {
            agentState = State.Stopped;

            short alertType = AlertManager.ALERT_TYPE_USERVM;
            if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER;
            } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY;
            } else if (VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())) {
                alertType = AlertManager.ALERT_TYPE_SSVM;
            }

            HostPodVO podVO = _podDao.findById(vm.getPodIdToDeployIn());
            DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterIdToDeployIn());
            HostVO hostVO = _hostDao.findById(vm.getHostId());

            String hostDesc = "name: " + hostVO.getName() + " (id:" + hostVO.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();
            _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc
                    + " due to storage failure", "Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped due to storage failure.");

        if (trackExternalChange) {
            if (serverState == State.Starting) {
                if (vm.getHostId() != null && vm.getHostId() != hostId) {
                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
                            + vm.getInstanceName());
                    return null;
                }
            }
            if (vm.getHostId() == null || hostId != vm.getHostId()) {
                try {
                    stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
                } catch (NoTransitionException e) {
                }
            }
        }

        // during VM migration time, don't sync state will agent status update
        if (serverState == State.Migrating) {
            s_logger.debug("Skipping vm in migrating state: " + vm);
            return null;
        }

        if (trackExternalChange) {
            if (serverState == State.Starting) {
                if (vm.getHostId() != null && vm.getHostId() != hostId) {
                    s_logger.info("CloudStack is starting VM on host " + vm.getHostId() + ", but status report comes from a different host " + hostId + ", skip status sync for vm: "
                            + vm.getInstanceName());
                    return null;
                }
            }

            if (serverState == State.Running) {
                try {
                    //
                    // we had a bug that sometimes VM may be at Running State
                    // but host_id is null, we will cover it here.
                    // means that when CloudStack DB lost of host information,
                    // we will heal it with the info reported from host
                    //
                    if (vm.getHostId() == null || hostId != vm.getHostId()) {
                        if (s_logger.isDebugEnabled()) {
                            s_logger.debug("detected host change when VM " + vm + " is at running state, VM could be live-migrated externally from host " + vm.getHostId() + " to host " + hostId);
                        }

                        stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId);
                    }
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
            }
        }

        if (agentState == serverState) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Both states are " + agentState + " for " + vm);
            }
            assert (agentState == State.Stopped || agentState == State.Running) : "If the states we send up is changed, this must be changed.";
            if (agentState == State.Running) {
                try {
                    stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, hostId);
                } catch (NoTransitionException e) {
                    s_logger.warn(e.getMessage());
                }
                // FIXME: What if someone comes in and sets it to stopping? Then
                // what?
                return null;
            }

            s_logger.debug("State matches but the agent said stopped so let's send a cleanup command anyways.");
            return cleanup(agentName);
        }

        if (agentState == State.Shutdowned) {
            if (serverState == State.Running || serverState == State.Starting || serverState == State.Stopping) {
                try {
                    advanceStop(vm, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
                } catch (AgentUnavailableException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                } catch (OperationTimedoutException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                } catch (ConcurrentOperationException e) {
                    assert (false) : "How do we hit this with forced on?";
                    return null;
                }
            } else {
                s_logger.debug("Sending cleanup to a shutdowned vm: " + agentName);
                command = cleanup(agentName);
            }
        } else if (agentState == State.Stopped) {
            // This state means the VM on the agent was detected previously
            // and now is gone. This is slightly different than if the VM
            // was never completed but we still send down a Stop Command
            // to ensure there's cleanup.
            if (serverState == State.Running) {
                // Our records showed that it should be running so let's restart
                // it.
                _haMgr.scheduleRestart(vm, false);
            } else if (serverState == State.Stopping) {
                _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop);
                s_logger.debug("Scheduling a check stop for VM in stopping mode: " + vm);
            } else if (serverState == State.Starting) {
                s_logger.debug("Ignoring VM in starting mode: " + vm.getInstanceName());
                _haMgr.scheduleRestart(vm, false);
            }
            command = cleanup(agentName);
        } else if (agentState == State.Running) {
            if (serverState == State.Starting) {
                if (fullSync) {
                    try {
                        ensureVmRunningContext(hostId, vm, Event.AgentReportRunning);
                    } catch (OperationTimedoutException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    } catch (ResourceUnavailableException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    }catch (InsufficientAddressCapacityException e) {
                        s_logger.error("Exception during update for running vm: " + vm, e);
                        return null;
                    }catch (NoTransitionException e) {
                        s_logger.warn(e.getMessage());
                    }
                }
            } else if (serverState == State.Stopping) {
                s_logger.debug("Scheduling a stop command for " + vm);
                _haMgr.scheduleStop(vm, hostId, WorkType.Stop);
            } else {
                s_logger.debug("server VM state " + serverState + " does not meet expectation of a running VM report from agent");

                // just be careful not to stop VM for things we don't handle
                // command = cleanup(agentName);
            }
        }
        return command;
    }

    private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException, InsufficientAddressCapacityException {
        VirtualMachineGuru vmGuru = getVmGuru(vm);

        s_logger.debug("VM state is starting on full sync so updating it to running");
        vm = findByIdAndType(vm.getType(), vm.getId());

        // grab outstanding work item if any
        ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found an outstanding work item for this vm " + vm + " in state:" + vm.getState() + ", work id:" + work.getId());
            }
        }

        try {
            stateTransitTo(vm, cause, hostId);
        } catch (NoTransitionException e1) {
            s_logger.warn(e1.getMessage());
        }

        s_logger.debug("VM's " + vm + " state is starting on full sync so updating it to Running");
        vm = vmGuru.findById(vm.getId()); // this should ensure vm has the most
        // up to date info

        VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
        List nics = _nicsDao.listByVmId(profile.getId());
        for (NicVO nic : nics) {
            Network network = _networkMgr.getNetwork(nic.getNetworkId());
            NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, 
                    _networkMgr.isSecurityGroupSupportedInNetwork(network), _networkMgr.getNetworkTag(profile.getHypervisorType(), network));
            profile.addNic(nicProfile);
        }

        Commands cmds = new Commands(OnError.Stop);
        s_logger.debug("Finalizing commands that need to be send to complete Start process for the vm " + vm);

        if (vmGuru.finalizeCommandsOnStart(cmds, profile)) {
            if (cmds.size() != 0) {
                _agentMgr.send(vm.getHostId(), cmds);
            }

            if (vmGuru.finalizeStart(profile, vm.getHostId(), cmds, null)) {
                stateTransitTo(vm, cause, vm.getHostId());
            } else {
                s_logger.error("Unable to finish finialization for running vm: " + vm);
            }
        } else {
            s_logger.error("Unable to finalize commands on start for vm: " + vm);
        }

        if (work != null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Updating outstanding work item to Done, id:" + work.getId());
            }
            work.setStep(Step.Done);
            _workDao.update(work.getId(), work);
        }
    }

    @Override
    public boolean isRecurring() {
        return true;
    }

    @Override
    public boolean processAnswers(long agentId, long seq, Answer[] answers) {
        for (final Answer answer : answers) {
            if (answer instanceof ClusterSyncAnswer) {
                ClusterSyncAnswer hs = (ClusterSyncAnswer) answer;
                if (!hs.isExceuted()){
                    deltaSync(hs.getNewStates());
                    hs.setExecuted();
                }
            }
        }
        return true;
    }

    @Override
    public boolean processTimeout(long agentId, long seq) {
        return true;
    }

    @Override
    public int getTimeout() {
        return -1;
    }

    @Override
    public boolean processCommands(long agentId, long seq, Command[] cmds) {
        boolean processed = false;
        for (Command cmd : cmds) {
            if (cmd instanceof PingRoutingCommand) {
                PingRoutingCommand ping = (PingRoutingCommand) cmd;
                if (ping.getNewStates() != null && ping.getNewStates().size() > 0) {
                    Commands commands = deltaHostSync(agentId, ping.getNewStates());
                    if (commands.size() > 0) {
                        try {
                            _agentMgr.send(agentId, commands, this);
                        } catch (final AgentUnavailableException e) {
                            s_logger.warn("Agent is now unavailable", e);
                        }
                    }
                }
                processed = true;
            }
        }
        return processed;
    }

    @Override
    public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
        return null;
    }

    @Override
    public boolean processDisconnect(long agentId, Status state) {
        return true;
    }

    @Override
    public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
        if (!(cmd instanceof StartupRoutingCommand)) {
            return;
        }

        } else {
        if (forRebalance) {
            s_logger.debug("Not processing listener " + this + " as connect happens on rebalance process");
            return;
        }

        if (forRebalance) {
            s_logger.debug("Not processing listener " + this + " as connect happens on rebalance process");
            return;
        }

        Long clusterId = agent.getClusterId();
        long agentId = agent.getId();
        if (agent.getHypervisorType() == HypervisorType.XenServer) { // only for Xen
        	StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
        	HashMap> allStates = startup.getClusterVMStateChanges();
        	if (allStates != null){
        		this.fullSync(clusterId, allStates);
        	}
        	
        	// initiate the cron job
            ClusterSyncCommand syncCmd = new ClusterSyncCommand(Integer.parseInt(Config.ClusterDeltaSyncInterval.getDefaultValue()), clusterId);
            try {
        public String getHostUuid() {
                long seq_no = _agentMgr.send(agentId, new Commands(syncCmd), this);
                s_logger.debug("Cluster VM sync started with jobid " + seq_no);
            } catch (AgentUnavailableException e) {
                s_logger.fatal("The Cluster VM sync process failed for cluster id " + clusterId + " with ", e);
            }
        }
        else { // for others KVM and VMWare 
            StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
            Commands commands = fullHostSync(agentId, startup);

            if (commands.size() > 0) {
                s_logger.debug("Sending clean commands to the agent");

                try {
                    boolean error = false;
                    Answer[] answers = _agentMgr.send(agentId, commands);
                    for (Answer answer : answers) {
                        if (!answer.getResult()) {
                            s_logger.warn("Unable to stop a VM due to " + answer.getDetails());
                            error = true;
                        }
                    }
                    if (error) {
                        throw new ConnectionException(true, "Unable to stop VMs");
                    }
                } catch (final AgentUnavailableException e) {
                    s_logger.warn("Agent is unavailable now", e);
                    throw new ConnectionException(true, "Unable to sync", e);
                } catch (final OperationTimedoutException e) {
                    s_logger.warn("Agent is unavailable now", e);
                    throw new ConnectionException(true, "Unable to sync", e);
                }
            }

        }
    }

    protected class TransitionTask implements Runnable {
        @Override
        public void run() {
            GlobalLock lock = GlobalLock.getInternLock("TransitionChecking");
            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 {
                lock.addRef();
                List instances = _vmDao.findVMInTransition(new Date(new Date().getTime() - (_operationTimeout * 1000)), State.Starting, State.Stopping);
                for (VMInstanceVO instance : instances) {
                    State state = instance.getState();
                    if (state == State.Stopping) {
                        _haMgr.scheduleStop(instance, instance.getHostId(), WorkType.CheckStop);
                    } else if (state == State.Starting) {
                        _haMgr.scheduleRestart(instance, true);
                    }
                }
            } catch (Exception e) {
                s_logger.warn("Caught the following exception on transition checking", e);
            } finally {
                StackMaid.current().exitCleanup();
                lock.unlock();
            }
        }
    }

    protected class AgentVmInfo {
        public String name;
        public State state;
        public String hostUuid;
        public VMInstanceVO vm;
        public VirtualMachineGuru guru;

        @SuppressWarnings("unchecked")
        public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state, String host) {
            this.name = name;
            this.state = state;
            this.vm = vm;
            this.guru = (VirtualMachineGuru) guru;
            this.hostUuid = host;
        }

        public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state) {
            this(name, guru, vm, state, null);
        }

            return hostUuid;
        }
    }

    @Override
    public VMInstanceVO findById(long vmId) {
        return _vmDao.findById(vmId);
    }
    
    @Override
    public void checkIfCanUpgrade(VirtualMachine vmInstance, long newServiceOfferingId) {
        ServiceOfferingVO newServiceOffering = _offeringDao.findById(newServiceOfferingId);
        if (newServiceOffering == null) {
            throw new InvalidParameterValueException("Unable to find a service offering with id " + newServiceOfferingId);
        }

        // Check that the VM is stopped
        if (!vmInstance.getState().equals(State.Stopped)) {
            s_logger.warn("Unable to upgrade virtual machine " + vmInstance.toString() + " in state " + vmInstance.getState());
            throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vmInstance.toString() + " " +
            		"in state " + vmInstance.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 (vmInstance.getServiceOfferingId() == newServiceOffering.getId()) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Not upgrading vm " + vmInstance.toString() + " since it already has the requested " +
                		"service offering (" + newServiceOffering.getName() + ")");
            }

            throw new InvalidParameterValueException("Not upgrading vm " + vmInstance.toString() + " since it already " +
            		"has the requested service offering (" + newServiceOffering.getName() + ")");
        }

        ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId());

        // Check that the service offering being upgraded to has the same Guest IP type as the VM's current service offering
        // NOTE: With the new network refactoring in 2.2, we shouldn't need the check for same guest IP type anymore.
        /*
         * 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 " + vmInstance.toString()
                    + ", cannot switch between local storage and shared storage service offerings.  Current offering " +
                    "useLocalStorage=" + currentServiceOffering.getUseLocalStorage()
                    + ", target offering useLocalStorage=" + newServiceOffering.getUseLocalStorage());
        }
        
        // if vm is a system vm, check if it is a system service offering, if yes return with error as it cannot be used for user vms
        if (currentServiceOffering.getSystemUse() != newServiceOffering.getSystemUse()) {
            throw new InvalidParameterValueException("isSystem property is different for current service offering and new service offering");
        }

        // Check that there are enough resources to upgrade the service offering
        if (!isVirtualMachineUpgradable(vmInstance, 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);
        }
    }
    
    @Override
    public boolean upgradeVmDb(long vmId, long serviceOfferingId) {
        VMInstanceVO vmForUpdate = _vmDao.createForUpdate();
        vmForUpdate.setServiceOfferingId(serviceOfferingId);
        ServiceOffering newSvcOff = _configMgr.getServiceOffering(serviceOfferingId);
        vmForUpdate.setHaEnabled(newSvcOff.getOfferHA());
        vmForUpdate.setLimitCpuUse(newSvcOff.getLimitCpuUse());
        vmForUpdate.setServiceOfferingId(newSvcOff.getId());
        return _vmDao.update(vmId, vmForUpdate);
    }
    
    @Override
    public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, 
                                                    ResourceUnavailableException, InsufficientCapacityException {
        
        s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
        VMInstanceVO vmVO = _vmDao.findById(vm.getId());
        ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), 
                _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
        
        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, 
                null, null, null);
        
        DataCenter dc = _configMgr.getZone(network.getDataCenterId());
        Host host = _hostDao.findById(vm.getHostId()); 
        DeployDestination dest = new DeployDestination(dc, null, null, host);
        
        //check vm state
        if (vm.getState() == State.Running) {
            //1) allocate and prepare nic
            NicProfile nic = _networkMgr.createNicForVm(network, requested, context, vmProfile, true);
            
            //2) Convert vmProfile to vmTO
            HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
            VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
            
            //3) Convert nicProfile to NicTO
            NicTO nicTO = toNicTO(nic, vmProfile.getVirtualMachine().getHypervisorType());
            
            //4) plug the nic to the vm
            VirtualMachineGuru vmGuru = getVmGuru(vmVO);
            
            s_logger.debug("Plugging nic for vm " + vm + " in network " + network);
            if (vmGuru.plugNic(network, nicTO, vmTO, context, dest)) {
                s_logger.debug("Nic is plugged successfully for vm " + vm + " in network " + network + ". Vm  is a part of network now");
                return nic;
            } else {
                s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network);
                return null;
            }
        } else if (vm.getState() == State.Stopped) {
            //1) allocate nic
            return _networkMgr.createNicForVm(network, requested, context, vmProfile, false);
            s_logger.warn("Unable to add vm " + vm + " to network  " + network);
            throw new ResourceUnavailableException("Unable to add vm " + vm + " to network, is not in the right state",
                    DataCenter.class, vm.getDataCenterIdToDeployIn());
        }
    }


    @Override
    public NicTO toNicTO(NicProfile nic, HypervisorType hypervisorType) {
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(hypervisorType);
        
        NicTO nicTO = hvGuru.toNicTO(nic);
        return nicTO;
    }
    
    @Override
    public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException {
        VMInstanceVO vmVO = _vmDao.findById(vm.getId());
        ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), 
                _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM));
        
        VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, 
                null, null, null);
        
        DataCenter dc = _configMgr.getZone(network.getDataCenterId());
        Host host = _hostDao.findById(vm.getHostId()); 
        DeployDestination dest = new DeployDestination(dc, null, null, host);
        VirtualMachineGuru vmGuru = getVmGuru(vmVO);
        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType());
        VirtualMachineTO vmTO = hvGuru.implement(vmProfile);
        
        Nic nic = null;
        
        if (broadcastUri != null) {
            nic = _nicsDao.findByInstanceIdNetworkIdAndBroadcastUri(network.getId(), vm.getId(), broadcastUri.toString());
        } else {
            nic = _networkMgr.getNicInNetwork(vm.getId(), network.getId());
        }
        
        NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), 
                _networkMgr.getNetworkRate(network.getId(), vm.getId()), 
                _networkMgr.isSecurityGroupSupportedInNetwork(network), 
                _networkMgr.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network));
        
        //1) Unplug the nic
        NicTO nicTO = toNicTO(nicProfile, vmProfile.getVirtualMachine().getHypervisorType());
        s_logger.debug("Un-plugging nic for vm " + vm + " from network " + network);
        boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest);
        if (result) {
            s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
        } else {
            s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
            return false;
        }
        
        //2) Release the nic
        _networkMgr.releaseNic(vmProfile, nic);
        s_logger.debug("Successfully released nic " + nic +  "for vm " + vm);
        
        //3) Remove the nic
        _networkMgr.removeNic(vmProfile, nic);
        return result;
    }
   
}
File
VirtualMachineManagerImpl.java
Developer's decision
Version 2
Kind of conflict
Annotation
Class declaration
Comment
Import
Package declaration