You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2018/05/11 07:47:02 UTC

[cloudstack] 01/01: Merge branch '4.11': Reduce VR downtime during network restart (#2508)

This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 65511c4335eb5060fb7a3b4577e99d54b72ae6c3
Merge: 1b10c18 a77ed56
Author: Rohit Yadav <ro...@shapeblue.com>
AuthorDate: Fri May 11 13:05:36 2018 +0530

    Merge branch '4.11': Reduce VR downtime during network restart (#2508)
    
    Signed-off-by: Rohit Yadav <ro...@shapeblue.com>

 api/src/main/java/com/cloud/network/Network.java   |   2 +
 .../java/com/cloud/network/NetworkProfile.java     |   5 +
 .../java/com/cloud/network/NetworkService.java     |   2 +-
 api/src/main/java/com/cloud/network/vpc/Vpc.java   |   4 +
 .../org/apache/cloudstack/api/ApiConstants.java    |   3 +-
 .../command/user/network/RestartNetworkCmd.java    |  16 +-
 .../api/command/user/vpc/RestartVPCCmd.java        |  16 +-
 .../cloudstack/api/response/NetworkResponse.java   |  12 ++
 .../service/NetworkOrchestrationService.java       |  24 +++
 .../engine/orchestration/NetworkOrchestrator.java  | 204 ++++++++++++++-------
 .../java/com/cloud/network/dao/NetworkDaoImpl.java |   3 +-
 .../main/java/com/cloud/network/dao/NetworkVO.java |  25 ++-
 .../src/main/java/com/cloud/network/vpc/VpcVO.java |  13 ++
 .../main/java/com/cloud/api/ApiResponseHelper.java |   1 +
 .../api/query/dao/DomainRouterJoinDaoImpl.java     |   4 +-
 .../java/com/cloud/network/NetworkServiceImpl.java |  10 +-
 .../network/element/VirtualRouterElement.java      |   8 +-
 .../java/com/cloud/network/vpc/VpcManagerImpl.java |  92 ++++++++--
 .../deployment/RouterDeploymentDefinition.java     |   8 +-
 .../deployment/VpcRouterDeploymentDefinition.java  |   5 +
 .../java/com/cloud/vpc/MockNetworkManagerImpl.java |  12 +-
 systemvm/debian/opt/cloud/bin/cs/CsAddress.py      |   4 +-
 systemvm/debian/opt/cloud/bin/setup/common.sh      |   6 +-
 systemvm/debian/opt/cloud/bin/setup/postinit.sh    |   6 +-
 .../opt/cloud/templates/keepalived.conf.templ      |   3 -
 ui/scripts/network.js                              |  31 +++-
 26 files changed, 391 insertions(+), 128 deletions(-)

diff --cc api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 8886320,0000000..504b214
mode 100644,000000..100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@@ -1,732 -1,0 +1,733 @@@
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with 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.
 +package org.apache.cloudstack.api;
 +
 +public class ApiConstants {
 +    public static final String ACCOUNT = "account";
 +    public static final String ACCOUNTS = "accounts";
 +    public static final String ACCOUNT_TYPE = "accounttype";
 +    public static final String ACCOUNT_ID = "accountid";
 +    public static final String ACTIVITY = "activity";
 +    public static final String ADDRESS = "address";
 +    public static final String ALGORITHM = "algorithm";
 +    public static final String ALLOCATED_ONLY = "allocatedonly";
 +    public static final String ANNOTATION = "annotation";
 +    public static final String API_KEY = "apikey";
 +    public static final String ASYNC_BACKUP = "asyncbackup";
 +    public static final String USER_API_KEY = "userapikey";
 +    public static final String APPLIED = "applied";
 +    public static final String LIST_LB_VMIPS = "lbvmips";
 +    public static final String AVAILABLE = "available";
 +    public static final String BITS = "bits";
 +    public static final String BOOTABLE = "bootable";
 +    public static final String BIND_DN = "binddn";
 +    public static final String BIND_PASSWORD = "bindpass";
 +    public static final String BYTES_READ_RATE = "bytesreadrate";
 +    public static final String BYTES_WRITE_RATE = "byteswriterate";
 +    public static final String BYPASS_VLAN_OVERLAP_CHECK = "bypassvlanoverlapcheck";
 +    public static final String CATEGORY = "category";
 +    public static final String CAN_REVERT = "canrevert";
 +    public static final String CA_CERTIFICATES = "cacertificates";
 +    public static final String CERTIFICATE = "certificate";
 +    public static final String CERTIFICATE_CHAIN = "certchain";
 +    public static final String CERTIFICATE_FINGERPRINT = "fingerprint";
 +    public static final String CERTIFICATE_ID = "certid";
 +    public static final String CSR = "csr";
 +    public static final String PRIVATE_KEY = "privatekey";
 +    public static final String DOMAIN_SUFFIX = "domainsuffix";
 +    public static final String DNS_SEARCH_ORDER = "dnssearchorder";
 +    public static final String CHAIN_INFO = "chaininfo";
 +    public static final String CIDR = "cidr";
 +    public static final String IP6_CIDR = "ip6cidr";
 +    public static final String CIDR_LIST = "cidrlist";
 +    public static final String DEST_CIDR_LIST = "destcidrlist";
 +    public static final String CLEANUP = "cleanup";
-     public static final String MAKEREDUNDANTE = "makeredundant";
++    public static final String MAKEREDUNDANT = "makeredundant";
 +    public static final String CLUSTER_ID = "clusterid";
 +    public static final String CLUSTER_NAME = "clustername";
 +    public static final String CLUSTER_TYPE = "clustertype";
 +    public static final String CN = "cn";
 +    public static final String COMMAND = "command";
 +    public static final String CMD_EVENT_TYPE = "cmdeventtype";
 +    public static final String COMPONENT = "component";
 +    public static final String CPU_NUMBER = "cpunumber";
 +    public static final String CPU_SPEED = "cpuspeed";
 +    public static final String CREATED = "created";
 +    public static final String CTX_ACCOUNT_ID = "ctxaccountid";
 +    public static final String CTX_DETAILS = "ctxDetails";
 +    public static final String CTX_USER_ID = "ctxuserid";
 +    public static final String CTXSTARTEVENTID = "ctxstarteventid";
 +    public static final String CTX_START_EVENT_ID = "ctxStartEventId";
 +    public static final String CUSTOMIZED = "customized";
 +    public static final String CUSTOMIZED_IOPS = "customizediops";
 +    public static final String CUSTOM_ID = "customid";
 +    public static final String CUSTOM_JOB_ID = "customjobid";
 +    public static final String MIN_IOPS = "miniops";
 +    public static final String MAX_IOPS = "maxiops";
 +    public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";
 +    public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist";
 +    public static final String DESCRIPTION = "description";
 +    public static final String DESTINATION_ZONE_ID = "destzoneid";
 +    public static final String DETAILS = "details";
 +    public static final String DEVICE_ID = "deviceid";
 +    public static final String DIRECT_DOWNLOAD = "directdownload";
 +    public static final String DISK_OFFERING_ID = "diskofferingid";
 +    public static final String NEW_DISK_OFFERING_ID = "newdiskofferingid";
 +    public static final String DISK_SIZE = "disksize";
 +    public static final String UTILIZATION = "utilization";
 +    public static final String DRIVER = "driver";
 +    public static final String ROOT_DISK_SIZE = "rootdisksize";
 +    public static final String DHCP_OPTIONS_NETWORK_LIST = "dhcpoptionsnetworklist";
 +    public static final String DHCP_OPTIONS = "dhcpoptions";
 +    public static final String DHCP_PREFIX = "dhcp:";
 +    public static final String DISPLAY_NAME = "displayname";
 +    public static final String DISPLAY_NETWORK = "displaynetwork";
 +    public static final String DISPLAY_NIC = "displaynic";
 +    public static final String DISPLAY_TEXT = "displaytext";
 +    public static final String DISPLAY_VM = "displayvm";
 +    public static final String DISPLAY_OFFERING = "displayoffering";
 +    public static final String DISPLAY_VOLUME = "displayvolume";
 +    public static final String DNS1 = "dns1";
 +    public static final String DNS2 = "dns2";
 +    public static final String IP6_DNS1 = "ip6dns1";
 +    public static final String IP6_DNS2 = "ip6dns2";
 +    public static final String DOMAIN = "domain";
 +    public static final String DOMAIN_ID = "domainid";
 +    public static final String DOMAIN__ID = "domainId";
 +    public static final String DURATION = "duration";
 +    public static final String ELIGIBLE = "eligible";
 +    public static final String EMAIL = "email";
 +    public static final String END_DATE = "enddate";
 +    public static final String END_IP = "endip";
 +    public static final String END_IPV6 = "endipv6";
 +    public static final String END_PORT = "endport";
 +    public static final String ENTRY_TIME = "entrytime";
 +    public static final String EXPIRES = "expires";
 +    public static final String EXTRA_DHCP_OPTION = "extradhcpoption";
 +    public static final String EXTRA_DHCP_OPTION_NAME = "extradhcpoptionname";
 +    public static final String EXTRA_DHCP_OPTION_CODE = "extradhcpoptioncode";
 +    public static final String EXTRA_DHCP_OPTION_VALUE = "extradhcpvalue";
 +    public static final String FENCE = "fence";
 +    public static final String FETCH_LATEST = "fetchlatest";
 +    public static final String FIRSTNAME = "firstname";
 +    public static final String FORCED = "forced";
 +    public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage";
 +    public static final String FORMAT = "format";
 +    public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork";
 +    public static final String FOR_SYSTEM_VMS = "forsystemvms";
 +    public static final String GATEWAY = "gateway";
 +    public static final String IP6_GATEWAY = "ip6gateway";
 +    public static final String GROUP = "group";
 +    public static final String GROUP_ID = "groupid";
 +    public static final String GSLB_LB_METHOD = "gslblbmethod";
 +    public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname";
 +    public static final String GSLB_SERVICE_TYPE = "gslbservicetype";
 +    public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname";
 +    public static final String GSLB_LBRULE_WEIGHT_MAP = "gslblbruleweightsmap";
 +    public static final String GUEST_CIDR_ADDRESS = "guestcidraddress";
 +    public static final String GUEST_VLAN_RANGE = "guestvlanrange";
 +    public static final String HA_ENABLE = "haenable";
 +    public static final String HA_PROVIDER = "haprovider";
 +    public static final String HA_STATE = "hastate";
 +    public static final String HEALTH = "health";
 +    public static final String HOST_ID = "hostid";
 +    public static final String HOST_NAME = "hostname";
 +    public static final String HYPERVISOR = "hypervisor";
 +    public static final String INLINE = "inline";
 +    public static final String INSTANCE = "instance";
 +    public static final String ICMP_CODE = "icmpcode";
 +    public static final String ICMP_TYPE = "icmptype";
 +    public static final String ID = "id";
 +    public static final String IDS = "ids";
 +    public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid";
 +    public static final String NEXT_ACL_RULE_ID = "nextaclruleid";
 +    public static final String INTERNAL_DNS1 = "internaldns1";
 +    public static final String INTERNAL_DNS2 = "internaldns2";
 +    public static final String INTERVAL_TYPE = "intervaltype";
 +    public static final String LOCATION_TYPE = "locationtype";
 +    public static final String IOPS_READ_RATE = "iopsreadrate";
 +    public static final String IOPS_WRITE_RATE = "iopswriterate";
 +    public static final String IP_ADDRESS = "ipaddress";
 +    public static final String IP6_ADDRESS = "ip6address";
 +    public static final String IP_ADDRESS_ID = "ipaddressid";
 +    public static final String IS_ASYNC = "isasync";
 +    public static final String IP_AVAILABLE = "ipavailable";
 +    public static final String IP_LIMIT = "iplimit";
 +    public static final String IP_TOTAL = "iptotal";
 +    public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired";
 +    public static final String IS_EXTRACTABLE = "isextractable";
 +    public static final String IS_FEATURED = "isfeatured";
 +    public static final String IS_PORTABLE = "isportable";
 +    public static final String IS_PUBLIC = "ispublic";
 +    public static final String IS_PERSISTENT = "ispersistent";
 +    public static final String EGRESS_DEFAULT_POLICY = "egressdefaultpolicy";
 +    public static final String IS_READY = "isready";
 +    public static final String IS_RECURSIVE = "isrecursive";
 +    public static final String ISO_FILTER = "isofilter";
 +    public static final String ISO_GUEST_OS_NONE = "None";
 +    public static final String JOB_ID = "jobid";
 +    public static final String JOB_STATUS = "jobstatus";
 +    public static final String LASTNAME = "lastname";
 +    public static final String LEVEL = "level";
 +    public static final String LENGTH = "length";
 +    public static final String LIMIT_CPU_USE = "limitcpuuse";
 +    public static final String LOCK = "lock";
 +    public static final String LUN = "lun";
 +    public static final String LBID = "lbruleid";
 +    public static final String MAX = "max";
 +    public static final String MAC_ADDRESS = "macaddress";
 +    public static final String MAX_SNAPS = "maxsnaps";
 +    public static final String MEMORY = "memory";
 +    public static final String MODE = "mode";
 +    public static final String KEEPALIVE_ENABLED = "keepaliveenabled";
 +    public static final String NAME = "name";
 +    public static final String METHOD_NAME = "methodname";
 +    public static final String NETWORK_DOMAIN = "networkdomain";
 +    public static final String NETMASK = "netmask";
 +    public static final String NEW_NAME = "newname";
 +    public static final String NUM_RETRIES = "numretries";
 +    public static final String OFFER_HA = "offerha";
 +    public static final String IS_SYSTEM_OFFERING = "issystem";
 +    public static final String IS_DEFAULT_USE = "defaultuse";
 +    public static final String OP = "op";
 +    public static final String OS_CATEGORY_ID = "oscategoryid";
 +    public static final String OS_TYPE_ID = "ostypeid";
 +    public static final String OS_DISPLAY_NAME = "osdisplayname";
 +    public static final String OS_NAME_FOR_HYPERVISOR = "osnameforhypervisor";
 +    public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate";
 +    public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled";
 +    public static final String PARAMS = "params";
 +    public static final String PARENT_ID = "parentid";
 +    public static final String PARENT_DOMAIN_ID = "parentdomainid";
 +    public static final String PARENT_TEMPLATE_ID = "parenttemplateid";
 +    public static final String PASSWORD = "password";
 +    public static final String CURRENT_PASSWORD = "currentpassword";
 +    public static final String SHOULD_UPDATE_PASSWORD = "update_passwd_on_host";
 +    public static final String PASSWORD_ENABLED = "passwordenabled";
 +    public static final String SSHKEY_ENABLED = "sshkeyenabled";
 +    public static final String PATH = "path";
 +    public static final String POD_ID = "podid";
 +    public static final String POD_NAME = "podname";
 +    public static final String POD_IDS = "podids";
 +    public static final String POLICY_ID = "policyid";
 +    public static final String PORT = "port";
 +    public static final String PORTAL = "portal";
 +    public static final String PORTABLE_IP_ADDRESS = "portableipaddress";
 +    public static final String PORT_FORWARDING_SERVICE_ID = "portforwardingserviceid";
 +    public static final String POST_URL = "postURL";
 +    public static final String POWER_STATE = "powerstate";
 +    public static final String PRIVATE_INTERFACE = "privateinterface";
 +    public static final String PRIVATE_IP = "privateip";
 +    public static final String PRIVATE_PORT = "privateport";
 +    public static final String PRIVATE_START_PORT = "privateport";
 +    public static final String PRIVATE_END_PORT = "privateendport";
 +    public static final String PRIVATE_ZONE = "privatezone";
 +    public static final String PROTOCOL = "protocol";
 +    public static final String PROVISIONINGTYPE = "provisioningtype";
 +    public static final String PUBLIC_INTERFACE = "publicinterface";
 +    public static final String PUBLIC_IP_ID = "publicipid";
 +    public static final String PUBLIC_IP = "publicip";
 +    public static final String PUBLIC_PORT = "publicport";
 +    public static final String PUBLIC_START_PORT = "publicport";
 +    public static final String PUBLIC_END_PORT = "publicendport";
 +    public static final String PUBLIC_ZONE = "publiczone";
 +    public static final String RECEIVED_BYTES = "receivedbytes";
 +    public static final String RECONNECT = "reconnect";
 +    public static final String RECOVER = "recover";
 +    public static final String REQUIRES_HVM = "requireshvm";
 +    public static final String RESOURCE_TYPE = "resourcetype";
 +    public static final String RESOURCE_TYPE_NAME = "resourcetypename";
 +    public static final String RESPONSE = "response";
 +    public static final String REVERTABLE = "revertable";
 +    public static final String REGISTERED = "registered";
 +    public static final String QUERY_FILTER = "queryfilter";
 +    public static final String SCHEDULE = "schedule";
 +    public static final String SCOPE = "scope";
 +    public static final String SECRET_KEY = "usersecretkey";
 +    public static final String SECONDARY_IP = "secondaryip";
 +    public static final String SINCE = "since";
 +    public static final String KEY = "key";
 +    public static final String SEARCH_BASE = "searchbase";
 +    public static final String SECURITY_GROUP_IDS = "securitygroupids";
 +    public static final String SECURITY_GROUP_NAMES = "securitygroupnames";
 +    public static final String SECURITY_GROUP_NAME = "securitygroupname";
 +    public static final String SECURITY_GROUP_ID = "securitygroupid";
 +    public static final String SENT = "sent";
 +    public static final String SENT_BYTES = "sentbytes";
 +    public static final String SERIAL = "serial";
 +    public static final String SERVICE_OFFERING_ID = "serviceofferingid";
 +    public static final String SESSIONKEY = "sessionkey";
 +    public static final String SHOW_CAPACITIES = "showcapacities";
 +    public static final String SHOW_REMOVED = "showremoved";
 +    public static final String SIGNATURE = "signature";
 +    public static final String SIGNATURE_VERSION = "signatureversion";
 +    public static final String SIZE = "size";
 +    public static final String SNAPSHOT = "snapshot";
 +    public static final String SNAPSHOT_ID = "snapshotid";
 +    public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
 +    public static final String SNAPSHOT_TYPE = "snapshottype";
 +    public static final String SNAPSHOT_QUIESCEVM = "quiescevm";
 +    public static final String SOURCE_ZONE_ID = "sourcezoneid";
 +    public static final String START_DATE = "startdate";
 +    public static final String START_ID = "startid";
 +    public static final String START_IP = "startip";
 +    public static final String START_IPV6 = "startipv6";
 +    public static final String START_PORT = "startport";
 +    public static final String STATE = "state";
 +    public static final String STATUS = "status";
 +    public static final String STORAGE_TYPE = "storagetype";
 +    public static final String STORAGE_POLICY = "storagepolicy";
 +    public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
 +    public static final String STORAGE_CAPABILITIES = "storagecapabilities";
 +    public static final String SYSTEM_VM_TYPE = "systemvmtype";
 +    public static final String TAGS = "tags";
 +    public static final String TARGET_IQN = "targetiqn";
 +    public static final String TEMPLATE_FILTER = "templatefilter";
 +    public static final String TEMPLATE_ID = "templateid";
 +    public static final String ISO_ID = "isoid";
 +    public static final String TIMEOUT = "timeout";
 +    public static final String TIMEZONE = "timezone";
 +    public static final String TIMEZONEOFFSET = "timezoneoffset";
 +    public static final String TYPE = "type";
 +    public static final String TRUST_STORE = "truststore";
 +    public static final String TRUST_STORE_PASSWORD = "truststorepass";
 +    public static final String URL = "url";
 +    public static final String USAGE_INTERFACE = "usageinterface";
 +    public static final String USER_DATA = "userdata";
 +    public static final String USER_ID = "userid";
 +    public static final String USE_SSL = "ssl";
 +    public static final String USERNAME = "username";
 +    public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist";
 +    public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork";
 +    public static final String Update_IN_SEQUENCE = "updateinsequence";
 +    public static final String VALUE = "value";
 +    public static final String VIRTUAL_MACHINE_ID = "virtualmachineid";
 +    public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids";
 +    public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
 +    public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount";
 +    public static final String USAGE_ID = "usageid";
 +    public static final String USAGE_TYPE = "usagetype";
 +    public static final String INCLUDE_TAGS = "includetags";
 +
 +    public static final String VLAN = "vlan";
 +    public static final String VLAN_RANGE = "vlanrange";
 +    public static final String REMOVE_VLAN = "removevlan";
 +    public static final String VLAN_ID = "vlanid";
 +    public static final String ISOLATED_PVLAN = "isolatedpvlan";
 +    public static final String ISOLATION_URI = "isolationuri";
 +    public static final String VM_AVAILABLE = "vmavailable";
 +    public static final String VM_LIMIT = "vmlimit";
 +    public static final String VM_TOTAL = "vmtotal";
 +    public static final String VNET = "vnet";
 +    public static final String IS_VOLATILE = "isvolatile";
 +    public static final String VOLUME_ID = "volumeid";
 +    public static final String ZONE_ID = "zoneid";
 +    public static final String ZONE_NAME = "zonename";
 +    public static final String NETWORK_TYPE = "networktype";
 +    public static final String PAGE = "page";
 +    public static final String PAGE_SIZE = "pagesize";
 +    public static final String COUNT = "count";
 +    public static final String TRAFFIC_TYPE = "traffictype";
 +    public static final String NETWORK_OFFERING_ID = "networkofferingid";
 +    public static final String TIER_NETWORK_OFFERINGS = "tiernetworkofferings";
 +    public static final String NETWORK_IDS = "networkids";
 +    public static final String NETWORK_ID = "networkid";
 +    public static final String NIC_ID = "nicid";
 +    public static final String SPECIFY_VLAN = "specifyvlan";
 +    public static final String IS_DEFAULT = "isdefault";
 +    public static final String IS_SYSTEM = "issystem";
 +    public static final String IS_USER_DEFINED = "isuserdefined";
 +    public static final String AVAILABILITY = "availability";
 +    public static final String NETWORKRATE = "networkrate";
 +    public static final String HOST_TAGS = "hosttags";
 +    public static final String SSH_KEYPAIR = "keypair";
 +    public static final String HTTPMETHOD = "httpmethod";
 +    public static final String HOST_CPU_CAPACITY = "hostcpucapacity";
 +    public static final String HOST_CPU_NUM = "hostcpunum";
 +    public static final String HOST_MEM_CAPACITY = "hostmemcapacity";
 +    public static final String HOST_MAC = "hostmac";
 +    public static final String HOST_TAG = "hosttag";
 +    public static final String PXE_SERVER_TYPE = "pxeservertype";
 +    public static final String LINMIN_USERNAME = "linminusername";
 +    public static final String LINMIN_PASSWORD = "linminpassword";
 +    public static final String LINMIN_APID = "linminapid";
 +    public static final String DHCP_SERVER_TYPE = "dhcpservertype";
 +    public static final String LINK_LOCAL_IP = "linklocalip";
 +    public static final String LINK_LOCAL_MAC_ADDRESS = "linklocalmacaddress";
 +    public static final String LINK_LOCAL_MAC_NETMASK = "linklocalnetmask";
 +    public static final String LINK_LOCAL_NETWORK_ID = "linklocalnetworkid";
 +    public static final String PRIVATE_MAC_ADDRESS = "privatemacaddress";
 +    public static final String PRIVATE_NETMASK = "privatenetmask";
 +    public static final String PRIVATE_NETWORK_ID = "privatenetworkid";
 +    public static final String ALLOCATION_STATE = "allocationstate";
 +    public static final String MANAGED_STATE = "managedstate";
 +    public static final String STORAGE_ID = "storageid";
 +    public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip";
 +    public static final String PING_DIR = "pingdir";
 +    public static final String TFTP_DIR = "tftpdir";
 +    public static final String PING_CIFS_USERNAME = "pingcifsusername";
 +    public static final String PING_CIFS_PASSWORD = "pingcifspassword";
 +    public static final String CHECKSUM = "checksum";
 +    public static final String NETWORK_DEVICE_TYPE = "networkdevicetype";
 +    public static final String NETWORK_DEVICE_PARAMETER_LIST = "networkdeviceparameterlist";
 +    public static final String ZONE_TOKEN = "zonetoken";
 +    public static final String DHCP_PROVIDER = "dhcpprovider";
 +    public static final String RESULT = "success";
 +    public static final String RESUME = "resume";
 +    public static final String LUN_ID = "lunId";
 +    public static final String IQN = "iqn";
 +    public static final String AGGREGATE_NAME = "aggregatename";
 +    public static final String POOL_NAME = "poolname";
 +    public static final String VOLUME_NAME = "volumename";
 +    public static final String SNAPSHOT_POLICY = "snapshotpolicy";
 +    public static final String SNAPSHOT_RESERVATION = "snapshotreservation";
 +    public static final String IP_NETWORK_LIST = "iptonetworklist";
 +    public static final String PARAM_LIST = "param";
 +    public static final String FOR_LOAD_BALANCING = "forloadbalancing";
 +    public static final String KEYBOARD = "keyboard";
 +    public static final String OPEN_FIREWALL = "openfirewall";
 +    public static final String TEMPLATE_TAG = "templatetag";
 +    public static final String HYPERVISOR_VERSION = "hypervisorversion";
 +    public static final String MAX_GUESTS_LIMIT = "maxguestslimit";
 +    public static final String MAX_DATA_VOLUMES_LIMIT = "maxdatavolumeslimit";
 +    public static final String MAX_HOSTS_PER_CLUSTER = "maxhostspercluster";
 +    public static final String PROJECT_ID = "projectid";
 +    public static final String PROJECT_IDS = "projectids";
 +    public static final String PROJECT = "project";
 +    public static final String ROLE = "role";
 +    public static final String ROLE_ID = "roleid";
 +    public static final String ROLE_TYPE = "roletype";
 +    public static final String ROLE_NAME = "rolename";
 +    public static final String PERMISSION = "permission";
 +    public static final String RULE = "rule";
 +    public static final String RULE_ID = "ruleid";
 +    public static final String RULE_ORDER = "ruleorder";
 +    public static final String USER = "user";
 +    public static final String ACTIVE_ONLY = "activeonly";
 +    public static final String TOKEN = "token";
 +    public static final String ACCEPT = "accept";
 +    public static final String SORT_KEY = "sortkey";
 +    public static final String ACCOUNT_DETAILS = "accountdetails";
 +    public static final String SERVICE_OFFERING_DETAILS = "serviceofferingdetails";
 +    public static final String SERVICE_PROVIDER_LIST = "serviceproviderlist";
 +    public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist";
 +    public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability";
 +    public static final String PROVIDER = "provider";
 +    public static final String MANAGED = "managed";
 +    public static final String CAPACITY_BYTES = "capacitybytes";
 +    public static final String CAPACITY_IOPS = "capacityiops";
 +    public static final String NETWORK_SPEED = "networkspeed";
 +    public static final String BROADCAST_DOMAIN_RANGE = "broadcastdomainrange";
 +    public static final String BROADCAST_URI = "broadcasturi";
 +    public static final String ISOLATION_METHOD = "isolationmethod";
 +    public static final String ISOLATION_METHODS = "isolationmethods";
 +    public static final String PHYSICAL_NETWORK_ID = "physicalnetworkid";
 +    public static final String DEST_PHYSICAL_NETWORK_ID = "destinationphysicalnetworkid";
 +    public static final String ENABLE = "enable";
 +    public static final String ENABLED = "enabled";
 +    public static final String SERVICE_NAME = "servicename";
 +    public static final String DHCP_RANGE = "dhcprange";
 +    public static final String UUID = "uuid";
 +    public static final String SECURITY_GROUP_EANBLED = "securitygroupenabled";
 +    public static final String LOCAL_STORAGE_ENABLED = "localstorageenabled";
 +    public static final String GUEST_IP_TYPE = "guestiptype";
 +    public static final String XENSERVER_NETWORK_LABEL = "xennetworklabel";
 +    public static final String KVM_NETWORK_LABEL = "kvmnetworklabel";
 +    public static final String VMWARE_NETWORK_LABEL = "vmwarenetworklabel";
 +    public static final String HYPERV_NETWORK_LABEL = "hypervnetworklabel";
 +    public static final String OVM3_NETWORK_LABEL = "ovm3networklabel";
 +    public static final String NETWORK_SERVICE_PROVIDER_ID = "nspid";
 +    public static final String SERVICE_LIST = "servicelist";
 +    public static final String CAN_ENABLE_INDIVIDUAL_SERVICE = "canenableindividualservice";
 +    public static final String SUPPORTED_SERVICES = "supportedservices";
 +    public static final String NSP_ID = "nspid";
 +    public static final String ACL_TYPE = "acltype";
 +    public static final String ACL_REASON = "reason";
 +    public static final String ACL_RULE_PARTIAL_UPGRADE = "partialupgrade";
 +    public static final String SUBDOMAIN_ACCESS = "subdomainaccess";
 +    public static final String LOAD_BALANCER_DEVICE_ID = "lbdeviceid";
 +    public static final String LOAD_BALANCER_DEVICE_NAME = "lbdevicename";
 +    public static final String LOAD_BALANCER_DEVICE_STATE = "lbdevicestate";
 +    public static final String LOAD_BALANCER_DEVICE_CAPACITY = "lbdevicecapacity";
 +    public static final String LOAD_BALANCER_DEVICE_DEDICATED = "lbdevicededicated";
 +    public static final String LOAD_BALANCER_RULE = "loadbalancerrule";
 +    public static final String LOAD_BALANCER_RULE_LIST = "loadbalancerrulelist";
 +    public static final String FIREWALL_DEVICE_ID = "fwdeviceid";
 +    public static final String FIREWALL_DEVICE_NAME = "fwdevicename";
 +    public static final String FIREWALL_DEVICE_STATE = "fwdevicestate";
 +    public static final String FIREWALL_DEVICE_CAPACITY = "fwdevicecapacity";
 +    public static final String FIREWALL_DEVICE_DEDICATED = "fwdevicededicated";
 +    public static final String SERVICE = "service";
 +    public static final String ASSOCIATED_NETWORK_ID = "associatednetworkid";
 +    public static final String ASSOCIATED_NETWORK_NAME = "associatednetworkname";
 +    public static final String SOURCE_NAT_SUPPORTED = "sourcenatsupported";
 +    public static final String RESOURCE_STATE = "resourcestate";
 +    public static final String PROJECT_INVITE_REQUIRED = "projectinviterequired";
 +    public static final String REQUIRED = "required";
 +    public static final String RESTART_REQUIRED = "restartrequired";
 +    public static final String ALLOW_USER_CREATE_PROJECTS = "allowusercreateprojects";
 +    public static final String CONSERVE_MODE = "conservemode";
 +    public static final String TRAFFIC_TYPE_IMPLEMENTOR = "traffictypeimplementor";
 +    public static final String KEYWORD = "keyword";
 +    public static final String LIST_ALL = "listall";
 +    public static final String SPECIFY_IP_RANGES = "specifyipranges";
 +    public static final String IS_SOURCE_NAT = "issourcenat";
 +    public static final String IS_STATIC_NAT = "isstaticnat";
 +    public static final String SORT_BY = "sortby";
 +    public static final String CHANGE_CIDR = "changecidr";
 +    public static final String PURPOSE = "purpose";
 +    public static final String IS_TAGGED = "istagged";
 +    public static final String INSTANCE_NAME = "instancename";
 +    public static final String START_VM = "startvm";
 +    public static final String HA_HOST = "hahost";
 +    public static final String CUSTOM_DISK_OFF_MIN_SIZE = "customdiskofferingminsize";
 +    public static final String CUSTOM_DISK_OFF_MAX_SIZE = "customdiskofferingmaxsize";
 +    public static final String DEFAULT_ZONE_ID = "defaultzoneid";
 +    public static final String LIVE_MIGRATE = "livemigrate";
 +    public static final String MIGRATE_TO = "migrateto";
 +    public static final String GUID = "guid";
 +    public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype";
 +    public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype";
 +    public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname";
 +    public static final String VSWITCH_NAME_PUBLIC_TRAFFIC = "publicvswitchname";
 +    // Ovs controller
 +    public static final String OVS_DEVICE_ID = "ovsdeviceid";
 +    public static final String OVS_DEVICE_NAME = "ovsdevicename";
 +    // OpenDaylight controller
 +    public static final String ODL_DEVICE_ID = "odldeviceid";
 +    public static final String ODL_DEVICE_NAME = "odldevicename";
 +    public static final String ODL_TRANSPORT_ZONE_UUID = "transportzoneuuid";
 +    public static final String ODL_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid";
 +
 +    public static final String EXTERNAL_SWITCH_MGMT_DEVICE_ID = "vsmdeviceid";
 +    public static final String EXTERNAL_SWITCH_MGMT_DEVICE_NAME = "vsmdevicename";
 +    public static final String EXTERNAL_SWITCH_MGMT_DEVICE_STATE = "vsmdevicestate";
 +    // Would we need to have a capacity field for Cisco N1KV VSM? Max hosts managed by it perhaps? May remove this
 +    // later.
 +    public static final String EXTERNAL_SWITCH_MGMT_DEVICE_CAPACITY = "vsmdevicecapacity";
 +    public static final String CISCO_NEXUS_VSM_NAME = "vsmname";
 +    public static final String VSM_USERNAME = "vsmusername";
 +    public static final String VSM_PASSWORD = "vsmpassword";
 +    public static final String VSM_IPADDRESS = "vsmipaddress";
 +    public static final String VSM_MGMT_VLAN_ID = "vsmmgmtvlanid";
 +    public static final String VSM_PKT_VLAN_ID = "vsmpktvlanid";
 +    public static final String VSM_CTRL_VLAN_ID = "vsmctrlvlanid";
 +    public static final String VSM_STORAGE_VLAN_ID = "vsmstoragevlanid";
 +    public static final String VSM_DOMAIN_ID = "vsmdomainid";
 +    public static final String VSM_CONFIG_MODE = "vsmconfigmode";
 +    public static final String VSM_CONFIG_STATE = "vsmconfigstate";
 +    public static final String VSM_DEVICE_STATE = "vsmdevicestate";
 +    public static final String VCENTER = "vcenter";
 +    public static final String ADD_VSM_FLAG = "addvsmflag";
 +    public static final String END_POINT = "endpoint";
 +    public static final String REGION_ID = "regionid";
 +    public static final String VPC_OFF_ID = "vpcofferingid";
 +    public static final String NETWORK = "network";
 +    public static final String VPC_ID = "vpcid";
 +    public static final String GATEWAY_ID = "gatewayid";
 +    public static final String CAN_USE_FOR_DEPLOY = "canusefordeploy";
 +    public static final String RESOURCE_IDS = "resourceids";
 +    public static final String RESOURCE_ID = "resourceid";
 +    public static final String CUSTOMER = "customer";
 +    public static final String S2S_VPN_GATEWAY_ID = "s2svpngatewayid";
 +    public static final String S2S_CUSTOMER_GATEWAY_ID = "s2scustomergatewayid";
 +    public static final String IPSEC_PSK = "ipsecpsk";
 +    public static final String GUEST_IP = "guestip";
 +    public static final String REMOVED = "removed";
 +    public static final String IKE_POLICY = "ikepolicy";
 +    public static final String ESP_POLICY = "esppolicy";
 +    public static final String IKE_LIFETIME = "ikelifetime";
 +    public static final String ESP_LIFETIME = "esplifetime";
 +    public static final String DPD = "dpd";
 +    public static final String FORCE_ENCAP = "forceencap";
 +    public static final String FOR_VPC = "forvpc";
 +    public static final String SHRINK_OK = "shrinkok";
 +    public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid";
 +    public static final String NICIRA_NVP_TRANSPORT_ZONE_UUID = "transportzoneuuid";
 +    public static final String NICIRA_NVP_DEVICE_NAME = "niciradevicename";
 +    public static final String NICIRA_NVP_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid";
 +    public static final String NICIRA_NVP_L2_GATEWAYSERVICE_UUID = "l2gatewayserviceuuid";
 +    public static final String NSX_LOGICAL_SWITCH = "nsxlogicalswitch";
 +    public static final String NSX_LOGICAL_SWITCH_PORT = "nsxlogicalswitchport";
 +    public static final String S3_ACCESS_KEY = "accesskey";
 +    public static final String S3_SECRET_KEY = "secretkey";
 +    public static final String S3_END_POINT = "endpoint";
 +    public static final String S3_BUCKET_NAME = "bucket";
 +    public static final String S3_SIGNER = "s3signer";
 +    public static final String S3_V3_SIGNER = "S3SignerType";
 +    public static final String S3_V4_SIGNER = "AWSS3V4SignerType";
 +    public static final String S3_HTTPS_FLAG = "usehttps";
 +    public static final String S3_CONNECTION_TIMEOUT = "connectiontimeout";
 +    public static final String S3_CONNECTION_TTL = "connectionttl";
 +    public static final String S3_MAX_ERROR_RETRY = "maxerrorretry";
 +    public static final String S3_SOCKET_TIMEOUT = "sockettimeout";
 +    public static final String S3_USE_TCP_KEEPALIVE = "usetcpkeepalive";
 +    public static final String INCL_ZONES = "includezones";
 +    public static final String EXCL_ZONES = "excludezones";
 +    public static final String SOURCE = "source";
 +    public static final String COUNTER_ID = "counterid";
 +    public static final String AGGR_OPERATOR = "aggroperator";
 +    public static final String AGGR_FUNCTION = "aggrfunction";
 +    public static final String AGGR_VALUE = "aggrvalue";
 +    public static final String THRESHOLD = "threshold";
 +    public static final String RELATIONAL_OPERATOR = "relationaloperator";
 +    public static final String OTHER_DEPLOY_PARAMS = "otherdeployparams";
 +    public static final String MIN_MEMBERS = "minmembers";
 +    public static final String MAX_MEMBERS = "maxmembers";
 +    public static final String AUTOSCALE_VM_DESTROY_TIME = "destroyvmgraceperiod";
 +    public static final String VMPROFILE_ID = "vmprofileid";
 +    public static final String VMGROUP_ID = "vmgroupid";
 +    public static final String CS_URL = "csurl";
 +    public static final String IDP_ID = "idpid";
 +    public static final String SCALEUP_POLICY_IDS = "scaleuppolicyids";
 +    public static final String SCALEDOWN_POLICY_IDS = "scaledownpolicyids";
 +    public static final String SCALEUP_POLICIES = "scaleuppolicies";
 +    public static final String SCALEDOWN_POLICIES = "scaledownpolicies";
 +    public static final String INTERVAL = "interval";
 +    public static final String QUIETTIME = "quiettime";
 +    public static final String ACTION = "action";
 +    public static final String CONDITION_ID = "conditionid";
 +    public static final String CONDITION_IDS = "conditionids";
 +    public static final String COUNTERPARAM_LIST = "counterparam";
 +    public static final String AUTOSCALE_USER_ID = "autoscaleuserid";
 +    public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername";
 +    public static final String BAREMETAL_RCT_URL = "baremetalrcturl";
 +    public static final String UCS_DN = "ucsdn";
 +    public static final String GSLB_PROVIDER = "gslbprovider";
 +    public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider";
 +    public static final String GSLB_PROVIDER_PUBLIC_IP = "gslbproviderpublicip";
 +    public static final String GSLB_PROVIDER_PRIVATE_IP = "gslbproviderprivateip";
 +    public static final String VM_SNAPSHOT_DESCRIPTION = "description";
 +    public static final String VM_SNAPSHOT_DISPLAYNAME = "name";
 +    public static final String VM_SNAPSHOT_ID = "vmsnapshotid";
 +    public static final String VM_SNAPSHOT_IDS = "vmsnapshotids";
 +    public static final String VM_SNAPSHOT_DISK_IDS = "vmsnapshotdiskids";
 +    public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory";
 +    public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm";
 +    public static final String IMAGE_STORE_UUID = "imagestoreuuid";
 +    public static final String GUEST_VM_CIDR = "guestvmcidr";
 +    public static final String NETWORK_CIDR = "networkcidr";
 +    public static final String RESERVED_IP_RANGE = "reservediprange";
 +    public static final String UCS_MANAGER_ID = "ucsmanagerid";
 +    public static final String UCS_PROFILE_DN = "profiledn";
 +    public static final String UCS_BLADE_DN = "bladedn";
 +    public static final String UCS_BLADE_ID = "bladeid";
 +    public static final String VM_GUEST_IP = "vmguestip";
 +    public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout";
 +    public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime";
 +    public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold";
 +    public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold";
 +    public static final String HEALTHCHECK_PINGPATH = "pingpath";
 +    public static final String SOURCE_PORT = "sourceport";
 +    public static final String INSTANCE_PORT = "instanceport";
 +    public static final String SOURCE_IP = "sourceipaddress";
 +    public static final String SOURCE_IP_NETWORK_ID = "sourceipaddressnetworkid";
 +    public static final String SCHEME = "scheme";
 +    public static final String PROVIDER_TYPE = "providertype";
 +    public static final String AFFINITY_GROUP_IDS = "affinitygroupids";
 +    public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames";
 +    public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile";
 +    public static final String AFFINITY_GROUP_ID = "affinitygroupid";
 +    public static final String DEPLOYMENT_PLANNER = "deploymentplanner";
 +    public static final String ACL_ID = "aclid";
 +    public static final String NUMBER = "number";
 +    public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable";
 +    public static final String ROUTING = "isrouting";
 +    public static final String MAX_CONNECTIONS = "maxconnections";
 +    public static final String SERVICE_STATE = "servicestate";
 +
 +    public static final String IAM_ACCOUNT_IDS = "accountids";
 +    public static final String IAM_MEMBER_ACCOUNTS = "memberaccounts";
 +    public static final String IAM_PARENT_POLICY_ID = "parentpolicyid";
 +    public static final String IAM_PARENT_POLICY_NAME = "parentpolicyname";
 +    public static final String IAM_POLICY_IDS = "policyids";
 +    public static final String IAM_POLICIES = "policies";
 +    public static final String IAM_APIS = "apis";
 +    public static final String IAM_GROUPS = "groups";
 +    public static final String IAM_PERMISSIONS = "permission";
 +    public static final String IAM_ACTION = "action";
 +    public static final String IAM_SCOPE = "scope";
 +    public static final String IAM_SCOPE_ID = "scopeid";
 +    public static final String IAM_ALLOW_DENY = "permission";
 +    public static final String ENTITY_TYPE = "entitytype";
 +    public static final String ENTITY_ID = "entityid";
 +    public static final String EXTERNAL_ID = "externalid";
 +    public static final String ACCESS_TYPE = "accesstype";
 +
 +    public static final String RESOURCE_DETAILS = "resourcedetails";
 +    public static final String EXPUNGE = "expunge";
 +    public static final String FOR_DISPLAY = "fordisplay";
 +    public static final String PASSIVE = "passive";
 +    public static final String VERSION = "version";
 +    public static final String START = "start";
 +    public static final String GPUGROUP = "gpugroup";
 +    public static final String GPUGROUPNAME = "gpugroupname";
 +    public static final String VGPU = "vgpu";
 +    public static final String VGPUTYPE = "vgputype";
 +    public static final String VIDEORAM = "videoram";
 +    public static final String MAXHEADS = "maxheads";
 +    public static final String MAXRESOLUTIONX = "maxresolutionx";
 +    public static final String MAXRESOLUTIONY = "maxresolutiony";
 +    public static final String MAXVGPUPERPGPU = "maxvgpuperpgpu";
 +    public static final String REMAININGCAPACITY = "remainingcapacity";
 +    public static final String MAXCAPACITY = "maxcapacity";
 +    public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter";
++    public static final String REDUNDANT_ROUTER = "redundantrouter";
 +    public static final String REDUNDANT_VPC_ROUTER = "redundantvpcrouter";
 +    public static final String READ_ONLY = "readonly";
 +    public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc";
 +    public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet";
 +    public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess";
 +    public static final String REGION_LEVEL_VPC = "regionlevelvpc";
 +    public static final String STRECHED_L2_SUBNET = "strechedl2subnet";
 +    public static final String NETWORK_NAME = "networkname";
 +    public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans";
 +    public static final String METADATA = "metadata";
 +    public static final String PHYSICAL_SIZE = "physicalsize";
 +    public static final String OVM3_POOL = "ovm3pool";
 +    public static final String OVM3_CLUSTER = "ovm3cluster";
 +    public static final String OVM3_VIP = "ovm3vip";
 +    public static final String CLEAN_UP_DETAILS = "cleanupdetails";
 +    public static final String VIRTUAL_SIZE = "virtualsize";
 +    public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid";
 +    public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid";
 +
 +    public static final String ZONE_ID_LIST = "zoneids";
 +    public static final String DESTINATION_ZONE_ID_LIST = "destzoneids";
 +    public static final String ADMIN = "admin";
 +    public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n"
 +            + " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n"
 +            + " use another algorithm the hexadecimal string is to be prefixed with a string of the form,\n"
 +            + " \"{<algorithm>}\", not including the double quotes. In this <algorithm> is the exact string\n"
 +            + " representing the java supported algorithm, i.e. MD5 or SHA-256. Note that java does not\n" + " contain an algorithm called SHA256 or one called sha-256, only SHA-256.";
 +
 +    public static final String HAS_ANNOTATION = "hasannotation";
 +    public static final String LAST_ANNOTATED = "lastannotated";
 +    public static final String LDAP_DOMAIN = "ldapdomain";
 +
 +    public enum HostDetails {
 +        all, capacity, events, stats, min;
 +    }
 +
 +    public enum VMDetails {
 +        all, group, nics, stats, secgrp, tmpl, servoff, diskoff, iso, volume, min, affgrp;
 +    }
 +
 +    public enum DomainDetails {
 +        all, resource, min;
 +    }
 +}
diff --cc server/src/main/java/com/cloud/api/ApiResponseHelper.java
index 0cab30e,0000000..4d7de2a
mode 100644,000000..100644
--- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
@@@ -1,3966 -1,0 +1,3967 @@@
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with 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.
 +package com.cloud.api;
 +
 +import com.cloud.utils.crypt.DBEncryptionUtil;
 +import com.cloud.tags.dao.ResourceTagDao;
 +import com.cloud.agent.api.VgpuTypesInfo;
 +import com.cloud.api.query.ViewResponseHelper;
 +import com.cloud.api.query.vo.AccountJoinVO;
 +import com.cloud.api.query.vo.AsyncJobJoinVO;
 +import com.cloud.api.query.vo.ControlledViewEntity;
 +import com.cloud.api.query.vo.DataCenterJoinVO;
 +import com.cloud.api.query.vo.DiskOfferingJoinVO;
 +import com.cloud.api.query.vo.DomainRouterJoinVO;
 +import com.cloud.api.query.vo.EventJoinVO;
 +import com.cloud.api.query.vo.HostJoinVO;
 +import com.cloud.api.query.vo.ImageStoreJoinVO;
 +import com.cloud.api.query.vo.InstanceGroupJoinVO;
 +import com.cloud.api.query.vo.ProjectAccountJoinVO;
 +import com.cloud.api.query.vo.ProjectInvitationJoinVO;
 +import com.cloud.api.query.vo.ProjectJoinVO;
 +import com.cloud.api.query.vo.ResourceTagJoinVO;
 +import com.cloud.api.query.vo.SecurityGroupJoinVO;
 +import com.cloud.api.query.vo.ServiceOfferingJoinVO;
 +import com.cloud.api.query.vo.StoragePoolJoinVO;
 +import com.cloud.api.query.vo.TemplateJoinVO;
 +import com.cloud.api.query.vo.UserAccountJoinVO;
 +import com.cloud.api.query.vo.UserVmJoinVO;
 +import com.cloud.api.query.vo.VolumeJoinVO;
 +import com.cloud.api.response.ApiResponseSerializer;
 +import com.cloud.capacity.Capacity;
 +import com.cloud.capacity.CapacityVO;
 +import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
 +import com.cloud.configuration.ConfigurationManager;
 +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.ClusterDetailsDao;
 +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.domain.DomainVO;
 +import com.cloud.event.Event;
 +import com.cloud.exception.InvalidParameterValueException;
 +import com.cloud.exception.PermissionDeniedException;
 +import com.cloud.gpu.GPU;
 +import com.cloud.host.Host;
 +import com.cloud.host.HostVO;
 +import com.cloud.hypervisor.HypervisorCapabilities;
 +import com.cloud.network.GuestVlan;
 +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.NetworkModel;
 +import com.cloud.network.NetworkProfile;
 +import com.cloud.network.Networks.BroadcastDomainType;
 +import com.cloud.network.Networks.IsolationType;
 +import com.cloud.network.Networks.TrafficType;
 +import com.cloud.network.OvsProvider;
 +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.Site2SiteVpnConnection;
 +import com.cloud.network.Site2SiteVpnGateway;
 +import com.cloud.network.VirtualRouterProvider;
 +import com.cloud.network.VpnUser;
 +import com.cloud.network.VpnUserVO;
 +import com.cloud.network.as.AutoScalePolicy;
 +import com.cloud.network.as.AutoScaleVmGroup;
 +import com.cloud.network.as.AutoScaleVmProfile;
 +import com.cloud.network.as.AutoScaleVmProfileVO;
 +import com.cloud.network.as.Condition;
 +import com.cloud.network.as.ConditionVO;
 +import com.cloud.network.as.Counter;
 +import com.cloud.network.dao.IPAddressDao;
 +import com.cloud.network.dao.IPAddressVO;
 +import com.cloud.network.dao.LoadBalancerVO;
 +import com.cloud.network.dao.NetworkVO;
 +import com.cloud.network.dao.PhysicalNetworkVO;
 +import com.cloud.network.router.VirtualRouter;
 +import com.cloud.network.rules.FirewallRule;
 +import com.cloud.network.rules.FirewallRuleVO;
 +import com.cloud.network.rules.HealthCheckPolicy;
 +import com.cloud.network.rules.LoadBalancer;
 +import com.cloud.network.rules.LoadBalancerContainer.Scheme;
 +import com.cloud.network.rules.PortForwardingRule;
 +import com.cloud.network.rules.PortForwardingRuleVO;
 +import com.cloud.network.rules.StaticNatRule;
 +import com.cloud.network.rules.StickinessPolicy;
 +import com.cloud.network.security.SecurityGroup;
 +import com.cloud.network.security.SecurityGroupVO;
 +import com.cloud.network.security.SecurityRule;
 +import com.cloud.network.security.SecurityRule.SecurityRuleType;
 +import com.cloud.network.vpc.NetworkACL;
 +import com.cloud.network.vpc.NetworkACLItem;
 +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.NetworkOffering.Detail;
 +import com.cloud.offering.ServiceOffering;
 +import com.cloud.offerings.NetworkOfferingVO;
 +import com.cloud.org.Cluster;
 +import com.cloud.projects.Project;
 +import com.cloud.projects.ProjectAccount;
 +import com.cloud.projects.ProjectInvitation;
 +import com.cloud.region.ha.GlobalLoadBalancerRule;
 +import com.cloud.server.ResourceTag;
 +import com.cloud.server.ResourceTag.ResourceObjectType;
 +import com.cloud.service.ServiceOfferingVO;
 +import com.cloud.storage.DataStoreRole;
 +import com.cloud.storage.DiskOfferingVO;
 +import com.cloud.storage.GuestOS;
 +import com.cloud.storage.GuestOSCategoryVO;
 +import com.cloud.storage.GuestOSHypervisor;
 +import com.cloud.storage.ImageStore;
 +import com.cloud.storage.Snapshot;
 +import com.cloud.storage.SnapshotVO;
 +import com.cloud.storage.StoragePool;
 +import com.cloud.storage.Upload;
 +import com.cloud.storage.UploadVO;
 +import com.cloud.storage.VMTemplateVO;
 +import com.cloud.storage.Volume;
 +import com.cloud.storage.VolumeVO;
 +import com.cloud.storage.dao.VolumeDao;
 +import com.cloud.storage.snapshot.SnapshotPolicy;
 +import com.cloud.storage.snapshot.SnapshotSchedule;
 +import com.cloud.template.VirtualMachineTemplate;
 +import com.cloud.user.Account;
 +import com.cloud.user.AccountManager;
 +import com.cloud.user.SSHKeyPair;
 +import com.cloud.user.User;
 +import com.cloud.user.UserAccount;
 +import com.cloud.uservm.UserVm;
 +import com.cloud.utils.Pair;
 +import com.cloud.utils.StringUtils;
 +import com.cloud.utils.db.EntityManager;
 +import com.cloud.utils.net.Dhcp;
 +import com.cloud.utils.db.SearchBuilder;
 +import com.cloud.utils.db.SearchCriteria;
 +import com.cloud.utils.exception.CloudRuntimeException;
 +import com.cloud.utils.net.Ip;
 +import com.cloud.utils.net.NetUtils;
 +import com.cloud.vm.ConsoleProxyVO;
 +import com.cloud.vm.InstanceGroup;
 +import com.cloud.vm.Nic;
 +import com.cloud.vm.NicExtraDhcpOptionVO;
 +import com.cloud.vm.NicProfile;
 +import com.cloud.vm.NicSecondaryIp;
 +import com.cloud.vm.NicVO;
 +import com.cloud.vm.VMInstanceVO;
 +import com.cloud.vm.VirtualMachine;
 +import com.cloud.vm.VirtualMachine.Type;
 +import com.cloud.vm.dao.NicExtraDhcpOptionDao;
 +import com.cloud.vm.dao.NicSecondaryIpVO;
 +import com.cloud.vm.snapshot.VMSnapshot;
 +import org.apache.cloudstack.acl.ControlledEntity;
 +import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 +import org.apache.cloudstack.affinity.AffinityGroup;
 +import org.apache.cloudstack.affinity.AffinityGroupResponse;
 +import org.apache.cloudstack.api.ApiConstants.HostDetails;
 +import org.apache.cloudstack.api.ApiConstants.VMDetails;
 +import org.apache.cloudstack.api.ResponseGenerator;
 +import org.apache.cloudstack.api.ResponseObject.ResponseView;
 +import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
 +import org.apache.cloudstack.api.response.AccountResponse;
 +import org.apache.cloudstack.api.response.ApplicationLoadBalancerInstanceResponse;
 +import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
 +import org.apache.cloudstack.api.response.ApplicationLoadBalancerRuleResponse;
 +import org.apache.cloudstack.api.response.AsyncJobResponse;
 +import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
 +import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
 +import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse;
 +import org.apache.cloudstack.api.response.CapabilityResponse;
 +import org.apache.cloudstack.api.response.CapacityResponse;
 +import org.apache.cloudstack.api.response.ClusterResponse;
 +import org.apache.cloudstack.api.response.ConditionResponse;
 +import org.apache.cloudstack.api.response.ConfigurationResponse;
 +import org.apache.cloudstack.api.response.ControlledEntityResponse;
 +import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
 +import org.apache.cloudstack.api.response.CounterResponse;
 +import org.apache.cloudstack.api.response.CreateCmdResponse;
 +import org.apache.cloudstack.api.response.CreateSSHKeyPairResponse;
 +import org.apache.cloudstack.api.response.DiskOfferingResponse;
 +import org.apache.cloudstack.api.response.DomainResponse;
 +import org.apache.cloudstack.api.response.DomainRouterResponse;
 +import org.apache.cloudstack.api.response.EventResponse;
 +import org.apache.cloudstack.api.response.ExtractResponse;
 +import org.apache.cloudstack.api.response.FirewallResponse;
 +import org.apache.cloudstack.api.response.FirewallRuleResponse;
 +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
 +import org.apache.cloudstack.api.response.GuestOSResponse;
 +import org.apache.cloudstack.api.response.GuestOsMappingResponse;
 +import org.apache.cloudstack.api.response.GuestVlanRangeResponse;
 +import org.apache.cloudstack.api.response.HostForMigrationResponse;
 +import org.apache.cloudstack.api.response.HostResponse;
 +import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse;
 +import org.apache.cloudstack.api.response.IPAddressResponse;
 +import org.apache.cloudstack.api.response.ImageStoreResponse;
 +import org.apache.cloudstack.api.response.InstanceGroupResponse;
 +import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse;
 +import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
 +import org.apache.cloudstack.api.response.IsolationMethodResponse;
 +import org.apache.cloudstack.api.response.LBHealthCheckPolicyResponse;
 +import org.apache.cloudstack.api.response.LBHealthCheckResponse;
 +import org.apache.cloudstack.api.response.LBStickinessPolicyResponse;
 +import org.apache.cloudstack.api.response.LBStickinessResponse;
 +import org.apache.cloudstack.api.response.ListResponse;
 +import org.apache.cloudstack.api.response.LoadBalancerResponse;
 +import org.apache.cloudstack.api.response.NetworkACLItemResponse;
 +import org.apache.cloudstack.api.response.NetworkACLResponse;
 +import org.apache.cloudstack.api.response.NetworkOfferingResponse;
 +import org.apache.cloudstack.api.response.NetworkResponse;
 +import org.apache.cloudstack.api.response.NicExtraDhcpOptionResponse;
 +import org.apache.cloudstack.api.response.NicResponse;
 +import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
 +import org.apache.cloudstack.api.response.OvsProviderResponse;
 +import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
 +import org.apache.cloudstack.api.response.PodResponse;
 +import org.apache.cloudstack.api.response.PortableIpRangeResponse;
 +import org.apache.cloudstack.api.response.PortableIpResponse;
 +import org.apache.cloudstack.api.response.PrivateGatewayResponse;
 +import org.apache.cloudstack.api.response.ProjectAccountResponse;
 +import org.apache.cloudstack.api.response.ProjectInvitationResponse;
 +import org.apache.cloudstack.api.response.ProjectResponse;
 +import org.apache.cloudstack.api.response.ProviderResponse;
 +import org.apache.cloudstack.api.response.RegionResponse;
 +import org.apache.cloudstack.api.response.RemoteAccessVpnResponse;
 +import org.apache.cloudstack.api.response.ResourceCountResponse;
 +import org.apache.cloudstack.api.response.ResourceLimitResponse;
 +import org.apache.cloudstack.api.response.ResourceTagResponse;
 +import org.apache.cloudstack.api.response.SSHKeyPairResponse;
 +import org.apache.cloudstack.api.response.SecurityGroupResponse;
 +import org.apache.cloudstack.api.response.SecurityGroupRuleResponse;
 +import org.apache.cloudstack.api.response.ServiceOfferingResponse;
 +import org.apache.cloudstack.api.response.ServiceResponse;
 +import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse;
 +import org.apache.cloudstack.api.response.Site2SiteVpnConnectionResponse;
 +import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse;
 +import org.apache.cloudstack.api.response.SnapshotPolicyResponse;
 +import org.apache.cloudstack.api.response.SnapshotResponse;
 +import org.apache.cloudstack.api.response.SnapshotScheduleResponse;
 +import org.apache.cloudstack.api.response.StaticRouteResponse;
 +import org.apache.cloudstack.api.response.StorageNetworkIpRangeResponse;
 +import org.apache.cloudstack.api.response.StoragePoolResponse;
 +import org.apache.cloudstack.api.response.SystemVmInstanceResponse;
 +import org.apache.cloudstack.api.response.SystemVmResponse;
 +import org.apache.cloudstack.api.response.TemplatePermissionsResponse;
 +import org.apache.cloudstack.api.response.TemplateResponse;
 +import org.apache.cloudstack.api.response.TrafficMonitorResponse;
 +import org.apache.cloudstack.api.response.TrafficTypeResponse;
 +import org.apache.cloudstack.api.response.UpgradeRouterTemplateResponse;
 +import org.apache.cloudstack.api.response.UsageRecordResponse;
 +import org.apache.cloudstack.api.response.UserResponse;
 +import org.apache.cloudstack.api.response.UserVmResponse;
 +import org.apache.cloudstack.api.response.VMSnapshotResponse;
 +import org.apache.cloudstack.api.response.VirtualRouterProviderResponse;
 +import org.apache.cloudstack.api.response.VlanIpRangeResponse;
 +import org.apache.cloudstack.api.response.VolumeResponse;
 +import org.apache.cloudstack.api.response.VpcOfferingResponse;
 +import org.apache.cloudstack.api.response.VpcResponse;
 +import org.apache.cloudstack.api.response.VpnUsersResponse;
 +import org.apache.cloudstack.api.response.ZoneResponse;
 +import org.apache.cloudstack.config.Configuration;
 +import org.apache.cloudstack.context.CallContext;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
 +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 +import org.apache.cloudstack.framework.jobs.AsyncJob;
 +import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 +import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule;
 +import org.apache.cloudstack.region.PortableIp;
 +import org.apache.cloudstack.region.PortableIpRange;
 +import org.apache.cloudstack.region.Region;
 +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
 +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 +import org.apache.cloudstack.usage.Usage;
 +import org.apache.cloudstack.usage.UsageService;
 +import org.apache.cloudstack.usage.UsageTypes;
 +import org.apache.commons.collections.CollectionUtils;
 +import org.apache.log4j.Logger;
 +
 +import javax.inject.Inject;
 +import java.text.DecimalFormat;
 +import java.util.ArrayList;
 +import java.util.Calendar;
 +import java.util.Date;
 +import java.util.EnumSet;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +import java.util.TimeZone;
 +import java.util.stream.Collectors;
 +
 +public class ApiResponseHelper implements ResponseGenerator {
 +
 +    private static final Logger s_logger = Logger.getLogger(ApiResponseHelper.class);
 +    private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##");
 +
 +    @Inject
 +    private EntityManager _entityMgr;
 +    @Inject
 +    private UsageService _usageSvc;
 +    @Inject
 +    NetworkModel _ntwkModel;
 +    @Inject
 +    protected AccountManager _accountMgr;
 +    @Inject
 +    protected AsyncJobManager _jobMgr;
 +    @Inject
 +    ConfigurationManager _configMgr;
 +    @Inject
 +    SnapshotDataFactory snapshotfactory;
 +    @Inject
 +    private VolumeDao _volumeDao;
 +    @Inject
 +    private DataStoreManager _dataStoreMgr;
 +    @Inject
 +    private SnapshotDataStoreDao _snapshotStoreDao;
 +    @Inject
 +    private PrimaryDataStoreDao _storagePoolDao;
 +    @Inject
 +    private ClusterDetailsDao _clusterDetailsDao;
 +    @Inject
 +    private ResourceTagDao _resourceTagDao;
 +    @Inject
 +    private NicExtraDhcpOptionDao _nicExtraDhcpOptionDao;
 +    @Inject
 +    private IPAddressDao userIpAddressDao;
 +
 +    @Override
 +    public UserResponse createUserResponse(User user) {
 +        UserAccountJoinVO vUser = ApiDBUtils.newUserView(user);
 +        return ApiDBUtils.newUserResponse(vUser);
 +    }
 +
 +    // this method is used for response generation via createAccount (which
 +    // creates an account + user)
 +    @Override
 +    public AccountResponse createUserAccountResponse(ResponseView view, UserAccount user) {
 +        return ApiDBUtils.newAccountResponse(view, ApiDBUtils.findAccountViewById(user.getAccountId()));
 +    }
 +
 +    @Override
 +    public AccountResponse createAccountResponse(ResponseView view, Account account) {
 +        AccountJoinVO vUser = ApiDBUtils.newAccountView(account);
 +        return ApiDBUtils.newAccountResponse(view, vUser);
 +    }
 +
 +    @Override
 +    public UserResponse createUserResponse(UserAccount user) {
 +        UserAccountJoinVO vUser = ApiDBUtils.newUserView(user);
 +        return ApiDBUtils.newUserResponse(vUser);
 +    }
 +
 +    @Override
 +    public DomainResponse createDomainResponse(Domain domain) {
 +        DomainResponse domainResponse = new DomainResponse();
 +        domainResponse.setDomainName(domain.getName());
 +        domainResponse.setId(domain.getUuid());
 +        domainResponse.setLevel(domain.getLevel());
 +        domainResponse.setNetworkDomain(domain.getNetworkDomain());
 +        Domain parentDomain = ApiDBUtils.findDomainById(domain.getParent());
 +        if (parentDomain != null) {
 +            domainResponse.setParentDomainId(parentDomain.getUuid());
 +        }
 +        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) {
 +        DiskOfferingJoinVO vOffering = ApiDBUtils.newDiskOfferingView(offering);
 +        return ApiDBUtils.newDiskOfferingResponse(vOffering);
 +    }
 +
 +    @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(limit.getType());
 +
 +        if ((limit.getType() == ResourceType.primary_storage || limit.getType() == ResourceType.secondary_storage) && limit.getMax() >= 0) {
 +            resourceLimitResponse.setMax((long)Math.ceil((double)limit.getMax() / ResourceType.bytesToGiB));
 +        } else {
 +            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(resourceCount.getType());
 +        resourceCountResponse.setResourceCount(resourceCount.getCount());
 +        resourceCountResponse.setObjectName("resourcecount");
 +        return resourceCountResponse;
 +    }
 +
 +    @Override
 +    public ServiceOfferingResponse createServiceOfferingResponse(ServiceOffering offering) {
 +        ServiceOfferingJoinVO vOffering = ApiDBUtils.newServiceOfferingView(offering);
 +        return ApiDBUtils.newServiceOfferingResponse(vOffering);
 +    }
 +
 +    @Override
 +    public ConfigurationResponse createConfigurationResponse(Configuration cfg) {
 +        ConfigurationResponse cfgResponse = new ConfigurationResponse();
 +        cfgResponse.setCategory(cfg.getCategory());
 +        cfgResponse.setDescription(cfg.getDescription());
 +        cfgResponse.setName(cfg.getName());
 +        if(cfg.isEncrypted()) {
 +            cfgResponse.setValue(DBEncryptionUtil.encrypt(cfg.getValue()));
 +        } else {
 +            cfgResponse.setValue(cfg.getValue());
 +        }
 +        cfgResponse.setObjectName("configuration");
 +
 +        return cfgResponse;
 +    }
 +
 +    @Override
 +    public SnapshotResponse createSnapshotResponse(Snapshot snapshot) {
 +        SnapshotResponse snapshotResponse = new SnapshotResponse();
 +        snapshotResponse.setId(snapshot.getUuid());
 +
 +        populateOwner(snapshotResponse, snapshot);
 +
 +        VolumeVO volume = findVolumeById(snapshot.getVolumeId());
 +        String snapshotTypeStr = snapshot.getRecurringType().name();
 +        snapshotResponse.setSnapshotType(snapshotTypeStr);
 +        if (volume != null) {
 +            snapshotResponse.setVolumeId(volume.getUuid());
 +            snapshotResponse.setVolumeName(volume.getName());
 +            snapshotResponse.setVolumeType(volume.getVolumeType().name());
 +            snapshotResponse.setVirtualSize(volume.getSize());
 +            DataCenter zone = ApiDBUtils.findZoneById(volume.getDataCenterId());
 +            if (zone != null) {
 +                snapshotResponse.setZoneId(zone.getUuid());
 +            }
 +
 +            if (volume.getVolumeType() == Volume.Type.ROOT) {
 +                //TODO combine lines and 489 into a join in the volume dao
 +                VMInstanceVO instance = ApiDBUtils.findVMInstanceById(volume.getInstanceId());
 +                if (instance != null) {
 +                    GuestOS guestOs = ApiDBUtils.findGuestOSById(instance.getGuestOSId());
 +                    if (guestOs != null) {
 +                        snapshotResponse.setOsTypeId(guestOs.getUuid());
 +                        snapshotResponse.setOsDisplayName(guestOs.getDisplayName());
 +                    }
 +                }
 +            }
 +        }
 +        snapshotResponse.setCreated(snapshot.getCreated());
 +        snapshotResponse.setName(snapshot.getName());
 +        snapshotResponse.setIntervalType(ApiDBUtils.getSnapshotIntervalTypes(snapshot.getId()));
 +        snapshotResponse.setState(snapshot.getState());
 +        snapshotResponse.setLocationType(ApiDBUtils.getSnapshotLocationType(snapshot.getId()));
 +
 +        SnapshotInfo snapshotInfo = null;
 +
 +        if (snapshot instanceof SnapshotInfo) {
 +            snapshotInfo = (SnapshotInfo)snapshot;
 +        } else {
 +            DataStoreRole dataStoreRole = getDataStoreRole(snapshot, _snapshotStoreDao, _dataStoreMgr);
 +
 +            snapshotInfo = snapshotfactory.getSnapshot(snapshot.getId(), dataStoreRole);
 +        }
 +
 +        if (snapshotInfo == null) {
 +            s_logger.debug("Unable to find info for image store snapshot with uuid " + snapshot.getUuid());
 +            snapshotResponse.setRevertable(false);
 +        } else {
 +        snapshotResponse.setRevertable(snapshotInfo.isRevertable());
 +        snapshotResponse.setPhysicaSize(snapshotInfo.getPhysicalSize());
 +        }
 +
 +        // set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.Snapshot, snapshot.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        snapshotResponse.setTags(tagResponses);
 +
 +        snapshotResponse.setObjectName("snapshot");
 +        return snapshotResponse;
 +    }
 +
 +    public static DataStoreRole getDataStoreRole(Snapshot snapshot, SnapshotDataStoreDao snapshotStoreDao, DataStoreManager dataStoreMgr) {
 +        SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Primary);
 +
 +        if (snapshotStore == null) {
 +            return DataStoreRole.Image;
 +        }
 +
 +        long storagePoolId = snapshotStore.getDataStoreId();
 +        DataStore dataStore = dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary);
 +        if (dataStore == null) {
 +            return DataStoreRole.Image;
 +        }
 +
 +        Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
 +
 +        if (mapCapabilities != null) {
 +            String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString());
 +            Boolean supportsStorageSystemSnapshots = new Boolean(value);
 +
 +            if (supportsStorageSystemSnapshots) {
 +                return DataStoreRole.Primary;
 +            }
 +        }
 +
 +        return DataStoreRole.Image;
 +    }
 +
 +    @Override
 +    public VMSnapshotResponse createVMSnapshotResponse(VMSnapshot vmSnapshot) {
 +        VMSnapshotResponse vmSnapshotResponse = new VMSnapshotResponse();
 +        vmSnapshotResponse.setId(vmSnapshot.getUuid());
 +        vmSnapshotResponse.setName(vmSnapshot.getName());
 +        vmSnapshotResponse.setState(vmSnapshot.getState());
 +        vmSnapshotResponse.setCreated(vmSnapshot.getCreated());
 +        vmSnapshotResponse.setDescription(vmSnapshot.getDescription());
 +        vmSnapshotResponse.setDisplayName(vmSnapshot.getDisplayName());
 +        UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId());
 +        if (vm != null) {
 +            vmSnapshotResponse.setVirtualMachineid(vm.getUuid());
 +            DataCenterVO datacenter = ApiDBUtils.findZoneById(vm.getDataCenterId());
 +            if (datacenter != null) {
 +                vmSnapshotResponse.setZoneId(datacenter.getUuid());
 +            }
 +        }
 +        if (vmSnapshot.getParent() != null) {
 +            VMSnapshot vmSnapshotParent = ApiDBUtils.getVMSnapshotById(vmSnapshot.getParent());
 +            if (vmSnapshotParent != null) {
 +                vmSnapshotResponse.setParent(vmSnapshotParent.getUuid());
 +                vmSnapshotResponse.setParentName(vmSnapshotParent.getDisplayName());
 +            }
 +        }
 +        populateOwner(vmSnapshotResponse, vmSnapshot);
 +        Project project = ApiDBUtils.findProjectByProjectAccountId(vmSnapshot.getAccountId());
 +        if (project != null) {
 +            vmSnapshotResponse.setProjectId(project.getUuid());
 +            vmSnapshotResponse.setProjectName(project.getName());
 +        }
 +        Account account = ApiDBUtils.findAccountById(vmSnapshot.getAccountId());
 +        if (account != null) {
 +            vmSnapshotResponse.setAccountName(account.getAccountName());
 +        }
 +        DomainVO domain = ApiDBUtils.findDomainById(vmSnapshot.getDomainId());
 +        if (domain != null) {
 +            vmSnapshotResponse.setDomainId(domain.getUuid());
 +            vmSnapshotResponse.setDomainName(domain.getName());
 +        }
 +
 +        vmSnapshotResponse.setCurrent(vmSnapshot.getCurrent());
 +        vmSnapshotResponse.setType(vmSnapshot.getType().toString());
 +        vmSnapshotResponse.setObjectName("vmsnapshot");
 +        return vmSnapshotResponse;
 +    }
 +
 +    @Override
 +    public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) {
 +        SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse();
 +        policyResponse.setId(policy.getUuid());
 +        Volume vol = ApiDBUtils.findVolumeById(policy.getVolumeId());
 +        if (vol != null) {
 +            policyResponse.setVolumeId(vol.getUuid());
 +        }
 +        policyResponse.setSchedule(policy.getSchedule());
 +        policyResponse.setIntervalType(policy.getInterval());
 +        policyResponse.setMaxSnaps(policy.getMaxSnaps());
 +        policyResponse.setTimezone(policy.getTimezone());
 +        policyResponse.setForDisplay(policy.isDisplay());
 +        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<HostDetails> details) {
 +        List<HostJoinVO> viewHosts = ApiDBUtils.newHostView(host);
 +        List<HostResponse> listHosts = ViewResponseHelper.createHostResponse(details, viewHosts.toArray(new HostJoinVO[viewHosts.size()]));
 +        assert listHosts != null && listHosts.size() == 1 : "There should be one host returned";
 +        return listHosts.get(0);
 +    }
 +
 +    @Override
 +    public HostForMigrationResponse createHostForMigrationResponse(Host host) {
 +        return createHostForMigrationResponse(host, EnumSet.of(HostDetails.all));
 +    }
 +
 +    @Override
 +    public HostForMigrationResponse createHostForMigrationResponse(Host host, EnumSet<HostDetails> details) {
 +        List<HostJoinVO> viewHosts = ApiDBUtils.newHostView(host);
 +        List<HostForMigrationResponse> listHosts = ViewResponseHelper.createHostForMigrationResponse(details, viewHosts.toArray(new HostJoinVO[viewHosts.size()]));
 +        assert listHosts != null && listHosts.size() == 1 : "There should be one host returned";
 +        return listHosts.get(0);
 +    }
 +
 +    @Override
 +    public VlanIpRangeResponse createVlanIpRangeResponse(Vlan vlan) {
 +        return createVlanIpRangeResponse(VlanIpRangeResponse.class, vlan);
 +    }
 +
 +    @Override
 +    public VlanIpRangeResponse createVlanIpRangeResponse(Class<? extends VlanIpRangeResponse> subClass, Vlan vlan) {
 +        try {
 +            Long podId = ApiDBUtils.getPodIdForVlan(vlan.getId());
 +
 +            VlanIpRangeResponse vlanResponse = subClass.newInstance();
 +            vlanResponse.setId(vlan.getUuid());
 +            if (vlan.getVlanType() != null) {
 +                vlanResponse.setForVirtualNetwork(vlan.getVlanType().equals(VlanType.VirtualNetwork));
 +            }
 +            vlanResponse.setVlan(vlan.getVlanTag());
 +            DataCenter zone = ApiDBUtils.findZoneById(vlan.getDataCenterId());
 +            if (zone != null) {
 +                vlanResponse.setZoneId(zone.getUuid());
 +            }
 +
 +            if (podId != null) {
 +                HostPodVO pod = ApiDBUtils.findPodById(podId);
 +                if (pod != null) {
 +                    vlanResponse.setPodId(pod.getUuid());
 +                    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();
 +            if (ipRange != null) {
 +                String[] range = ipRange.split("-");
 +                vlanResponse.setStartIp(range[0]);
 +                vlanResponse.setEndIp(range[1]);
 +            }
 +
 +            vlanResponse.setIp6Gateway(vlan.getIp6Gateway());
 +            vlanResponse.setIp6Cidr(vlan.getIp6Cidr());
 +
 +            String ip6Range = vlan.getIp6Range();
 +            if (ip6Range != null) {
 +                String[] range = ip6Range.split("-");
 +                vlanResponse.setStartIpv6(range[0]);
 +                vlanResponse.setEndIpv6(range[1]);
 +            }
 +
 +            if (vlan.getNetworkId() != null) {
 +                Network nw = ApiDBUtils.findNetworkById(vlan.getNetworkId());
 +                if (nw != null) {
 +                    vlanResponse.setNetworkId(nw.getUuid());
 +                }
 +            }
 +            Account owner = ApiDBUtils.getVlanAccount(vlan.getId());
 +            if (owner != null) {
 +                populateAccount(vlanResponse, owner.getId());
 +                populateDomain(vlanResponse, owner.getDomainId());
 +            } else {
 +                Domain domain = ApiDBUtils.getVlanDomain(vlan.getId());
 +                if (domain != null) {
 +                    populateDomain(vlanResponse, domain.getId());
 +                } else {
 +                    Long networkId = vlan.getNetworkId();
 +                    if (networkId != null) {
 +                        Network network = _ntwkModel.getNetwork(networkId);
 +                        if (network != null) {
 +                            Long accountId = network.getAccountId();
 +                            populateAccount(vlanResponse, accountId);
 +                            populateDomain(vlanResponse, ApiDBUtils.findAccountById(accountId).getDomainId());
 +                        }
 +                    }
 +                }
 +            }
 +
 +            if (vlan.getPhysicalNetworkId() != null) {
 +                PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(vlan.getPhysicalNetworkId());
 +                if (pnw != null) {
 +                    vlanResponse.setPhysicalNetworkId(pnw.getUuid());
 +                }
 +            }
 +            vlanResponse.setForSystemVms(isForSystemVms(vlan.getId()));
 +            vlanResponse.setObjectName("vlan");
 +            return vlanResponse;
 +        } catch (InstantiationException | IllegalAccessException e) {
 +            throw new CloudRuntimeException("Failed to create Vlan IP Range response", e);
 +        }
 +    }
 +
 +    /**
 +     * Return true if vlan IP range is dedicated for system vms (SSVM and CPVM), false if not
 +     * @param vlanId vlan id
 +     * @return true if VLAN IP range is dedicated to system vms
 +     */
 +    private boolean isForSystemVms(long vlanId){
 +        SearchBuilder<IPAddressVO> sb = userIpAddressDao.createSearchBuilder();
 +        sb.and("vlanId", sb.entity().getVlanId(), SearchCriteria.Op.EQ);
 +        SearchCriteria<IPAddressVO> sc = sb.create();
 +        sc.setParameters("vlanId", vlanId);
 +        IPAddressVO userIpAddresVO = userIpAddressDao.findOneBy(sc);
 +        return userIpAddresVO.isForSystemVms();
 +    }
 +
 +    @Override
 +    public IPAddressResponse createIPAddressResponse(ResponseView view, 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.getUuid());
 +        ipResponse.setIpAddress(ipAddr.getAddress().toString());
 +        if (ipAddr.getAllocatedTime() != null) {
 +            ipResponse.setAllocated(ipAddr.getAllocatedTime());
 +        }
 +        DataCenter zone = ApiDBUtils.findZoneById(ipAddr.getDataCenterId());
 +        if (zone != null) {
 +            ipResponse.setZoneId(zone.getUuid());
 +            ipResponse.setZoneName(zone.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());
 +            if (vm != null) {
 +                ipResponse.setVirtualMachineId(vm.getUuid());
 +                ipResponse.setVirtualMachineName(vm.getHostName());
 +                if (vm.getDisplayName() != null) {
 +                    ipResponse.setVirtualMachineDisplayName(vm.getDisplayName());
 +                } else {
 +                    ipResponse.setVirtualMachineDisplayName(vm.getHostName());
 +                }
 +            }
 +        }
 +        if (ipAddr.getVmIp() != null) {
 +            ipResponse.setVirtualMachineIp(ipAddr.getVmIp());
 +        }
 +
 +        if (ipAddr.getAssociatedWithNetworkId() != null) {
 +            Network ntwk = ApiDBUtils.findNetworkById(ipAddr.getAssociatedWithNetworkId());
 +            if (ntwk != null) {
 +                ipResponse.setAssociatedNetworkId(ntwk.getUuid());
 +                ipResponse.setAssociatedNetworkName(ntwk.getName());
 +            }
 +        }
 +
 +        if (ipAddr.getVpcId() != null) {
 +            Vpc vpc = ApiDBUtils.findVpcById(ipAddr.getVpcId());
 +            if (vpc != null) {
 +                ipResponse.setVpcId(vpc.getUuid());
 +            }
 +        }
 +
 +        // 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);
 +        }
 +
 +        if (networkId != null) {
 +            NetworkVO nw = ApiDBUtils.findNetworkById(networkId);
 +            if (nw != null) {
 +                ipResponse.setNetworkId(nw.getUuid());
 +            }
 +        }
 +        ipResponse.setState(ipAddr.getState().toString());
 +
 +        if (ipAddr.getPhysicalNetworkId() != null) {
 +            PhysicalNetworkVO pnw = ApiDBUtils.findPhysicalNetworkById(ipAddr.getPhysicalNetworkId());
 +            if (pnw != null) {
 +                ipResponse.setPhysicalNetworkId(pnw.getUuid());
 +            }
 +        }
 +
 +        // show this info to full view only
 +        if (view == ResponseView.Full) {
 +            VlanVO vl = ApiDBUtils.findVlanById(ipAddr.getVlanId());
 +            if (vl != null) {
 +                ipResponse.setVlanId(vl.getUuid());
 +                ipResponse.setVlanName(vl.getVlanTag());
 +            }
 +        }
 +
 +        if (ipAddr.getSystem()) {
 +            if (ipAddr.isOneToOneNat()) {
 +                ipResponse.setPurpose(IpAddress.Purpose.StaticNat.toString());
 +            } else {
 +                ipResponse.setPurpose(IpAddress.Purpose.Lb.toString());
 +            }
 +        }
 +
 +        ipResponse.setForDisplay(ipAddr.isDisplay());
 +
 +        ipResponse.setPortable(ipAddr.isPortable());
 +
 +        //set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.PublicIpAddress, ipAddr.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        ipResponse.setTags(tagResponses);
 +
 +        ipResponse.setObjectName("ipaddress");
 +        return ipResponse;
 +    }
 +
 +    @Override
 +    public LoadBalancerResponse createLoadBalancerResponse(LoadBalancer loadBalancer) {
 +        LoadBalancerResponse lbResponse = new LoadBalancerResponse();
 +        lbResponse.setId(loadBalancer.getUuid());
 +        lbResponse.setName(loadBalancer.getName());
 +        lbResponse.setDescription(loadBalancer.getDescription());
 +        List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(loadBalancer.getId());
 +        lbResponse.setCidrList(StringUtils.join(cidrs, ","));
 +
 +        IPAddressVO publicIp = ApiDBUtils.findIpAddressById(loadBalancer.getSourceIpAddressId());
 +        lbResponse.setPublicIpId(publicIp.getUuid());
 +        lbResponse.setPublicIp(publicIp.getAddress().addr());
 +        lbResponse.setPublicPort(Integer.toString(loadBalancer.getSourcePortStart()));
 +        lbResponse.setPrivatePort(Integer.toString(loadBalancer.getDefaultPortStart()));
 +        lbResponse.setAlgorithm(loadBalancer.getAlgorithm());
 +        lbResponse.setLbProtocol(loadBalancer.getLbProtocol());
 +        lbResponse.setForDisplay(loadBalancer.isDisplay());
 +        FirewallRule.State state = loadBalancer.getState();
 +        String stateToSet = state.toString();
 +        if (state.equals(FirewallRule.State.Revoke)) {
 +            stateToSet = "Deleting";
 +        }
 +        lbResponse.setState(stateToSet);
 +        populateOwner(lbResponse, loadBalancer);
 +        DataCenter zone = ApiDBUtils.findZoneById(publicIp.getDataCenterId());
 +        if (zone != null) {
 +            lbResponse.setZoneId(zone.getUuid());
 +            lbResponse.setZoneName(zone.getName());
 +        }
 +
 +        //set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.LoadBalancer, loadBalancer.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        lbResponse.setTags(tagResponses);
 +
 +        Network ntwk = ApiDBUtils.findNetworkById(loadBalancer.getNetworkId());
 +        lbResponse.setNetworkId(ntwk.getUuid());
 +
 +        lbResponse.setObjectName("loadbalancer");
 +        return lbResponse;
 +    }
 +
 +    @Override
 +    public GlobalLoadBalancerResponse createGlobalLoadBalancerResponse(GlobalLoadBalancerRule globalLoadBalancerRule) {
 +        GlobalLoadBalancerResponse response = new GlobalLoadBalancerResponse();
 +        response.setAlgorithm(globalLoadBalancerRule.getAlgorithm());
 +        response.setStickyMethod(globalLoadBalancerRule.getPersistence());
 +        response.setServiceType(globalLoadBalancerRule.getServiceType());
 +        response.setServiceDomainName(globalLoadBalancerRule.getGslbDomain() + "." + ApiDBUtils.getDnsNameConfiguredForGslb());
 +        response.setName(globalLoadBalancerRule.getName());
 +        response.setDescription(globalLoadBalancerRule.getDescription());
 +        response.setRegionIdId(globalLoadBalancerRule.getRegion());
 +        response.setId(globalLoadBalancerRule.getUuid());
 +        populateOwner(response, globalLoadBalancerRule);
 +        response.setObjectName("globalloadbalancer");
 +
 +        List<LoadBalancerResponse> siteLbResponses = new ArrayList<LoadBalancerResponse>();
 +        List<? extends LoadBalancer> siteLoadBalaners = ApiDBUtils.listSiteLoadBalancers(globalLoadBalancerRule.getId());
 +        for (LoadBalancer siteLb : siteLoadBalaners) {
 +            LoadBalancerResponse siteLbResponse = createLoadBalancerResponse(siteLb);
 +            siteLbResponses.add(siteLbResponse);
 +        }
 +        response.setSiteLoadBalancers(siteLbResponses);
 +        return response;
 +    }
 +
 +    @Override
 +    public PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
 +        String[] ipRange = new String[2];
 +        List<String> startIp = new ArrayList<String>();
 +        List<String> endIp = new ArrayList<String>();
 +        List<String> forSystemVms = new ArrayList<String>();
 +        List<String> vlanIds = new ArrayList<String>();
 +
 +        if (pod.getDescription() != null && pod.getDescription().length() > 0) {
 +            final String[] existingPodIpRanges = pod.getDescription().split(",");
 +
 +            for(String podIpRange: existingPodIpRanges) {
 +                final String[] existingPodIpRange = podIpRange.split("-");
 +
 +                startIp.add(((existingPodIpRange.length > 0) && (existingPodIpRange[0] != null)) ? existingPodIpRange[0] : "");
 +                endIp.add(((existingPodIpRange.length > 1) && (existingPodIpRange[1] != null)) ? existingPodIpRange[1] : "");
 +                forSystemVms.add((existingPodIpRange.length > 2) && (existingPodIpRange[2] != null) ? existingPodIpRange[2] : "0");
 +                vlanIds.add((existingPodIpRange.length > 3) &&
 +                        (existingPodIpRange[3] != null && !existingPodIpRange.equals("untagged")) ?
 +                        BroadcastDomainType.Vlan.toUri(existingPodIpRange[3]).toString() :
 +                        BroadcastDomainType.Vlan.toUri(Vlan.UNTAGGED).toString());
 +            }
 +        }
 +
 +        PodResponse podResponse = new PodResponse();
 +        podResponse.setId(pod.getUuid());
 +        podResponse.setName(pod.getName());
 +        DataCenter zone = ApiDBUtils.findZoneById(pod.getDataCenterId());
 +        if (zone != null) {
 +            podResponse.setZoneId(zone.getUuid());
 +            podResponse.setZoneName(zone.getName());
 +        }
 +        podResponse.setNetmask(NetUtils.getCidrNetmask(pod.getCidrSize()));
 +        podResponse.setStartIp(startIp);
 +        podResponse.setEndIp(endIp);
 +        podResponse.setForSystemVms(forSystemVms);
 +        podResponse.setVlanId(vlanIds);
 +        podResponse.setGateway(pod.getGateway());
 +        podResponse.setAllocationState(pod.getAllocationState().toString());
 +        if (showCapacities != null && showCapacities) {
 +            List<SummedCapacity> capacities = ApiDBUtils.getCapacityByClusterPodZone(null, pod.getId(), null);
 +            Set<CapacityResponse> capacityResponses = new HashSet<CapacityResponse>();
 +            for (SummedCapacity capacity : capacities) {
 +                CapacityResponse capacityResponse = new CapacityResponse();
 +                capacityResponse.setCapacityType(capacity.getCapacityType());
 +                capacityResponse.setCapacityName(CapacityVO.getCapacityName(capacity.getCapacityType()));
 +                capacityResponse.setCapacityUsed(capacity.getUsedCapacity() + capacity.getReservedCapacity());
 +                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
 +                    List<SummedCapacity> 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<CapacityResponse>(capacityResponses));
 +        }
 +        podResponse.setObjectName("pod");
 +        return podResponse;
 +    }
 +
 +    @Override
 +    public ZoneResponse createZoneResponse(ResponseView view, DataCenter dataCenter, Boolean showCapacities) {
 +        DataCenterJoinVO vOffering = ApiDBUtils.newDataCenterView(dataCenter);
 +        return ApiDBUtils.newDataCenterResponse(view, vOffering, showCapacities);
 +    }
 +
 +    public static List<CapacityResponse> getDataCenterCapacityResponse(Long zoneId) {
 +        List<SummedCapacity> capacities = ApiDBUtils.getCapacityByClusterPodZone(zoneId, null, null);
 +        Set<CapacityResponse> capacityResponses = new HashSet<CapacityResponse>();
 +
 +        for (SummedCapacity capacity : capacities) {
 +            CapacityResponse capacityResponse = new CapacityResponse();
 +            capacityResponse.setCapacityType(capacity.getCapacityType());
 +            capacityResponse.setCapacityName(CapacityVO.getCapacityName(capacity.getCapacityType()));
 +            capacityResponse.setCapacityUsed(capacity.getUsedCapacity() + capacity.getReservedCapacity());
 +            if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
 +                List<SummedCapacity> c = ApiDBUtils.findNonSharedStorageForClusterPodZone(zoneId, 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, zoneId));
 +
 +        return new ArrayList<CapacityResponse>(capacityResponses);
 +    }
 +
 +    private static List<CapacityResponse> getStatsCapacityresponse(Long poolId, Long clusterId, Long podId, Long zoneId) {
 +        List<CapacityVO> capacities = new ArrayList<CapacityVO>();
 +        capacities.add(ApiDBUtils.getStoragePoolUsedStats(poolId, clusterId, podId, zoneId));
 +        if (clusterId == null && podId == null) {
 +            capacities.add(ApiDBUtils.getSecondaryStorageUsedStats(poolId, zoneId));
 +        }
 +
 +        List<CapacityResponse> capacityResponses = new ArrayList<CapacityResponse>();
 +        for (CapacityVO capacity : capacities) {
 +            CapacityResponse capacityResponse = new CapacityResponse();
 +            capacityResponse.setCapacityType(capacity.getCapacityType());
 +            capacityResponse.setCapacityName(CapacityVO.getCapacityName(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(ResponseView view, Volume volume) {
 +        List<VolumeJoinVO> viewVrs = ApiDBUtils.newVolumeView(volume);
 +        List<VolumeResponse> listVrs = ViewResponseHelper.createVolumeResponse(view, viewVrs.toArray(new VolumeJoinVO[viewVrs.size()]));
 +        assert listVrs != null && listVrs.size() == 1 : "There should be one volume returned";
 +        return listVrs.get(0);
 +    }
 +
 +    @Override
 +    public InstanceGroupResponse createInstanceGroupResponse(InstanceGroup group) {
 +        InstanceGroupJoinVO vgroup = ApiDBUtils.newInstanceGroupView(group);
 +        return ApiDBUtils.newInstanceGroupResponse(vgroup);
 +
 +    }
 +
 +    @Override
 +    public StoragePoolResponse createStoragePoolResponse(StoragePool pool) {
 +        List<StoragePoolJoinVO> viewPools = ApiDBUtils.newStoragePoolView(pool);
 +        List<StoragePoolResponse> listPools = ViewResponseHelper.createStoragePoolResponse(viewPools.toArray(new StoragePoolJoinVO[viewPools.size()]));
 +        assert listPools != null && listPools.size() == 1 : "There should be one storage pool returned";
 +        return listPools.get(0);
 +    }
 +
 +    @Override
 +    public ImageStoreResponse createImageStoreResponse(ImageStore os) {
 +        List<ImageStoreJoinVO> viewStores = ApiDBUtils.newImageStoreView(os);
 +        List<ImageStoreResponse> listStores = ViewResponseHelper.createImageStoreResponse(viewStores.toArray(new ImageStoreJoinVO[viewStores.size()]));
 +        assert listStores != null && listStores.size() == 1 : "There should be one image data store returned";
 +        return listStores.get(0);
 +    }
 +
 +    @Override
 +    public StoragePoolResponse createStoragePoolForMigrationResponse(StoragePool pool) {
 +        List<StoragePoolJoinVO> viewPools = ApiDBUtils.newStoragePoolView(pool);
 +        List<StoragePoolResponse> listPools = ViewResponseHelper.createStoragePoolForMigrationResponse(viewPools.toArray(new StoragePoolJoinVO[viewPools.size()]));
 +        assert listPools != null && listPools.size() == 1 : "There should be one storage pool returned";
 +        return listPools.get(0);
 +    }
 +
 +    @Override
 +    public ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities) {
 +        ClusterResponse clusterResponse = new ClusterResponse();
 +        clusterResponse.setId(cluster.getUuid());
 +        clusterResponse.setName(cluster.getName());
 +        HostPodVO pod = ApiDBUtils.findPodById(cluster.getPodId());
 +        if (pod != null) {
 +            clusterResponse.setPodId(pod.getUuid());
 +            clusterResponse.setPodName(pod.getName());
 +        }
 +        DataCenter dc = ApiDBUtils.findZoneById(cluster.getDataCenterId());
 +        if (dc != null) {
 +            clusterResponse.setZoneId(dc.getUuid());
 +            clusterResponse.setZoneName(dc.getName());
 +        }
 +        clusterResponse.setHypervisorType(cluster.getHypervisorType().toString());
 +        clusterResponse.setClusterType(cluster.getClusterType().toString());
 +        clusterResponse.setAllocationState(cluster.getAllocationState().toString());
 +        clusterResponse.setManagedState(cluster.getManagedState().toString());
 +        String cpuOvercommitRatio = ApiDBUtils.findClusterDetails(cluster.getId(), "cpuOvercommitRatio");
 +        String memoryOvercommitRatio = ApiDBUtils.findClusterDetails(cluster.getId(), "memoryOvercommitRatio");
 +        clusterResponse.setCpuOvercommitRatio(cpuOvercommitRatio);
 +        clusterResponse.setMemoryOvercommitRatio(memoryOvercommitRatio);
 +        clusterResponse.setResourceDetails(_clusterDetailsDao.findDetails(cluster.getId()));
 +
 +        if (showCapacities != null && showCapacities) {
 +            List<SummedCapacity> capacities = ApiDBUtils.getCapacityByClusterPodZone(null, null, cluster.getId());
 +            Set<CapacityResponse> capacityResponses = new HashSet<CapacityResponse>();
 +
 +            for (SummedCapacity capacity : capacities) {
 +                CapacityResponse capacityResponse = new CapacityResponse();
 +                capacityResponse.setCapacityType(capacity.getCapacityType());
 +                capacityResponse.setCapacityName(CapacityVO.getCapacityName(capacity.getCapacityType()));
 +                capacityResponse.setCapacityUsed(capacity.getUsedCapacity() + capacity.getReservedCapacity());
 +
 +                if (capacity.getCapacityType() == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED) {
 +                    List<SummedCapacity> 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<CapacityResponse>(capacityResponses));
 +        }
 +        clusterResponse.setObjectName("cluster");
 +        return clusterResponse;
 +    }
 +
 +    @Override
 +    public FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRule fwRule) {
 +        FirewallRuleResponse response = new FirewallRuleResponse();
 +        response.setId(fwRule.getUuid());
 +        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<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
 +        response.setCidrList(StringUtils.join(cidrs, ","));
 +
 +        Network guestNtwk = ApiDBUtils.findNetworkById(fwRule.getNetworkId());
 +        response.setNetworkId(guestNtwk.getUuid());
 +
 +
 +        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
 +
 +        if (ip != null)
 +        {
 +            response.setPublicIpAddressId(ip.getUuid());
 +            response.setPublicIpAddress(ip.getAddress().addr());
 +            if (fwRule.getDestinationIpAddress() != null)
 +            {
 +                response.setDestNatVmIp(fwRule.getDestinationIpAddress().toString());
 +                UserVm vm = ApiDBUtils.findUserVmById(fwRule.getVirtualMachineId());
 +                if (vm != null) {
 +                    response.setVirtualMachineId(vm.getUuid());
 +                    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<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.PortForwardingRule, fwRule.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        response.setTags(tagResponses);
 +
 +        response.setState(stateToSet);
 +        response.setForDisplay(fwRule.isDisplay());
 +        response.setObjectName("portforwardingrule");
 +        return response;
 +    }
 +
 +    @Override
 +    public IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule) {
 +        IpForwardingRuleResponse response = new IpForwardingRuleResponse();
 +        response.setId(fwRule.getUuid());
 +        response.setProtocol(fwRule.getProtocol());
 +
 +        IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
 +
 +        if (ip != null) {
 +            response.setPublicIpAddressId(ip.getId());
 +            response.setPublicIpAddress(ip.getAddress().addr());
 +            if (fwRule.getDestIpAddress() != null) {
 +                UserVm vm = ApiDBUtils.findUserVmById(ip.getAssociatedWithVmId());
 +                if (vm != null) {// vm might be destroyed
 +                    response.setVirtualMachineId(vm.getUuid());
 +                    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<UserVmResponse> createUserVmResponse(String objectName, UserVm... userVms) {
 +        return createUserVmResponse(null, objectName, userVms);
 +    }
 +
 +    @Override
 +    public List<UserVmResponse> createUserVmResponse(String objectName, EnumSet<VMDetails> details, UserVm... userVms) {
 +        return createUserVmResponse(null, objectName, userVms);
 +    }
 +    */
 +
 +    @Override
 +    public List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, EnumSet<VMDetails> details, UserVm... userVms) {
 +        List<UserVmJoinVO> viewVms = ApiDBUtils.newUserVmView(userVms);
 +        return ViewResponseHelper.createUserVmResponse(view, objectName, details, viewVms.toArray(new UserVmJoinVO[viewVms.size()]));
 +
 +    }
 +
 +    @Override
 +    public List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, UserVm... userVms) {
 +        List<UserVmJoinVO> viewVms = ApiDBUtils.newUserVmView(userVms);
 +        return ViewResponseHelper.createUserVmResponse(view, objectName, viewVms.toArray(new UserVmJoinVO[viewVms.size()]));
 +    }
 +
 +    @Override
 +    public DomainRouterResponse createDomainRouterResponse(VirtualRouter router) {
 +        List<DomainRouterJoinVO> viewVrs = ApiDBUtils.newDomainRouterView(router);
 +        List<DomainRouterResponse> listVrs = ViewResponseHelper.createDomainRouterResponse(viewVrs.toArray(new DomainRouterJoinVO[viewVrs.size()]));
 +        assert listVrs != null && listVrs.size() == 1 : "There should be one virtual router returned";
 +        return listVrs.get(0);
 +    }
 +
 +    @Override
 +    public SystemVmResponse createSystemVmResponse(VirtualMachine vm) {
 +        SystemVmResponse vmResponse = new SystemVmResponse();
 +        if (vm.getType() == Type.SecondaryStorageVm || vm.getType() == Type.ConsoleProxy || vm.getType() == Type.DomainRouter || vm.getType() == Type.NetScalerVm) {
 +            vmResponse.setId(vm.getUuid());
 +            vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
 +            vmResponse.setName(vm.getHostName());
 +
 +            if (vm.getPodIdToDeployIn() != null) {
 +                HostPodVO pod = ApiDBUtils.findPodById(vm.getPodIdToDeployIn());
 +                if (pod != null) {
 +                    vmResponse.setPodId(pod.getUuid());
 +                }
 +            }
 +            VMTemplateVO template = ApiDBUtils.findTemplateById(vm.getTemplateId());
 +            if (template != null) {
 +                vmResponse.setTemplateId(template.getUuid());
 +            }
 +            vmResponse.setCreated(vm.getCreated());
 +
 +            if (vm.getHostId() != null) {
 +                Host host = ApiDBUtils.findHostById(vm.getHostId());
 +                if (host != null) {
 +                    vmResponse.setHostId(host.getUuid());
 +                    vmResponse.setHostName(host.getName());
 +                    vmResponse.setHypervisor(host.getHypervisorType().toString());
 +                }
 +            }
 +
 +            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.getDataCenterId());
 +            if (zone != null) {
 +                vmResponse.setZoneId(zone.getUuid());
 +                vmResponse.setZoneName(zone.getName());
 +                vmResponse.setDns1(zone.getDns1());
 +                vmResponse.setDns2(zone.getDns2());
 +            }
 +
 +            List<NicProfile> 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.getIPv4Address());
 +                        vmResponse.setPrivateMacAddress(singleNicProfile.getMacAddress());
 +                        vmResponse.setPrivateNetmask(singleNicProfile.getIPv4Netmask());
 +                    } else if (network.getTrafficType() == TrafficType.Control) {
 +                        vmResponse.setLinkLocalIp(singleNicProfile.getIPv4Address());
 +                        vmResponse.setLinkLocalMacAddress(singleNicProfile.getMacAddress());
 +                        vmResponse.setLinkLocalNetmask(singleNicProfile.getIPv4Netmask());
 +                    } else if (network.getTrafficType() == TrafficType.Public) {
 +                        vmResponse.setPublicIp(singleNicProfile.getIPv4Address());
 +                        vmResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
 +                        vmResponse.setPublicNetmask(singleNicProfile.getIPv4Netmask());
 +                        vmResponse.setGateway(singleNicProfile.getIPv4Gateway());
 +                    } else if (network.getTrafficType() == TrafficType.Guest) {
 +                        /*
 +                          * In basic zone, public ip has TrafficType.Guest in case EIP service is not enabled.
 +                          * When EIP service is enabled in the basic zone, system VM by default get the public
 +                          * IP allocated for EIP. So return the guest/public IP accordingly.
 +                          * */
 +                        NetworkOffering networkOffering = ApiDBUtils.findNetworkOfferingById(network.getNetworkOfferingId());
 +                        if (networkOffering.getElasticIp()) {
 +                            IpAddress ip = ApiDBUtils.findIpByAssociatedVmId(vm.getId());
 +                            if (ip != null) {
 +                                Vlan vlan = ApiDBUtils.findVlanById(ip.getVlanId());
 +                                vmResponse.setPublicIp(ip.getAddress().addr());
 +                                vmResponse.setPublicNetmask(vlan.getVlanNetmask());
 +                                vmResponse.setGateway(vlan.getVlanGateway());
 +                            }
 +                        } else {
 +                            vmResponse.setPublicIp(singleNicProfile.getIPv4Address());
 +                            vmResponse.setPublicMacAddress(singleNicProfile.getMacAddress());
 +                            vmResponse.setPublicNetmask(singleNicProfile.getIPv4Netmask());
 +                            vmResponse.setGateway(singleNicProfile.getIPv4Gateway());
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +        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 DiskOfferingVO findDiskOfferingById(Long diskOfferingId) {
 +        return ApiDBUtils.findDiskOfferingById(diskOfferingId);
 +    }
 +
 +    @Override
 +    public VpnUsersResponse createVpnUserResponse(VpnUser vpnUser) {
 +        VpnUsersResponse vpnResponse = new VpnUsersResponse();
 +        vpnResponse.setId(vpnUser.getUuid());
 +        vpnResponse.setUserName(vpnUser.getUsername());
 +        vpnResponse.setState(vpnUser.getState().toString());
 +
 +        populateOwner(vpnResponse, vpnUser);
 +
 +        vpnResponse.setObjectName("vpnuser");
 +        return vpnResponse;
 +    }
 +
 +    @Override
 +    public RemoteAccessVpnResponse createRemoteAccessVpnResponse(RemoteAccessVpn vpn) {
 +        RemoteAccessVpnResponse vpnResponse = new RemoteAccessVpnResponse();
 +        IpAddress ip = ApiDBUtils.findIpAddressById(vpn.getServerAddressId());
 +        if (ip != null) {
 +            vpnResponse.setPublicIpId(ip.getUuid());
 +            vpnResponse.setPublicIp(ip.getAddress().addr());
 +        }
 +        vpnResponse.setIpRange(vpn.getIpRange());
 +        vpnResponse.setPresharedKey(vpn.getIpsecPresharedKey());
 +        populateOwner(vpnResponse, vpn);
 +        vpnResponse.setState(vpn.getState().toString());
 +        vpnResponse.setId(vpn.getUuid());
 +        vpnResponse.setForDisplay(vpn.isDisplay());
 +        vpnResponse.setObjectName("remoteaccessvpn");
 +
 +        return vpnResponse;
 +    }
 +
 +    @Override
 +    public TemplateResponse createTemplateUpdateResponse(ResponseView view, VirtualMachineTemplate result) {
 +        List<TemplateJoinVO> tvo = ApiDBUtils.newTemplateView(result);
 +        List<TemplateResponse> listVrs = ViewResponseHelper.createTemplateUpdateResponse(view, tvo.toArray(new TemplateJoinVO[tvo.size()]));
 +        assert listVrs != null && listVrs.size() == 1 : "There should be one template returned";
 +        return listVrs.get(0);
 +    }
 +
 +    @Override
 +    public List<TemplateResponse> createTemplateResponses(ResponseView view, VirtualMachineTemplate result, Long zoneId, boolean readyOnly) {
 +        List<TemplateJoinVO> tvo = null;
 +        if (zoneId == null || zoneId == -1 || result.isCrossZones()) {
 +            tvo = ApiDBUtils.newTemplateView(result);
 +        } else {
 +            tvo = ApiDBUtils.newTemplateView(result, zoneId, readyOnly);
 +
 +        }
 +        return ViewResponseHelper.createTemplateResponse(view, tvo.toArray(new TemplateJoinVO[tvo.size()]));
 +    }
 +
 +    @Override
 +    public List<TemplateResponse> createTemplateResponses(ResponseView view, VirtualMachineTemplate result,
 +                                                          List<Long> zoneIds, boolean readyOnly) {
 +        List<TemplateJoinVO> tvo = null;
 +        if (zoneIds == null) {
 +            return createTemplateResponses(view, result, (Long)null, readyOnly);
 +        } else {
 +            for (Long zoneId: zoneIds){
 +                if (tvo == null)
 +                    tvo = ApiDBUtils.newTemplateView(result, zoneId, readyOnly);
 +                else
 +                    tvo.addAll(ApiDBUtils.newTemplateView(result, zoneId, readyOnly));
 +            }
 +        }
 +        return ViewResponseHelper.createTemplateResponse(view, tvo.toArray(new TemplateJoinVO[tvo.size()]));
 +    }
 +
 +    @Override
 +    public List<TemplateResponse> createTemplateResponses(ResponseView view, long templateId, Long zoneId, boolean readyOnly) {
 +        VirtualMachineTemplate template = findTemplateById(templateId);
 +        return createTemplateResponses(view, template, zoneId, readyOnly);
 +    }
 +
 +    @Override
 +    public List<TemplateResponse> createIsoResponses(ResponseView view, VirtualMachineTemplate result, Long zoneId, boolean readyOnly) {
 +        List<TemplateJoinVO> tvo = null;
 +        if (zoneId == null || zoneId == -1) {
 +            tvo = ApiDBUtils.newTemplateView(result);
 +        } else {
 +            tvo = ApiDBUtils.newTemplateView(result, zoneId, readyOnly);
 +        }
 +
 +        return ViewResponseHelper.createIsoResponse(view, tvo.toArray(new TemplateJoinVO[tvo.size()]));
 +    }
 +
 +    @Override
 +    public SecurityGroupResponse createSecurityGroupResponse(SecurityGroup group) {
 +        List<SecurityGroupJoinVO> viewSgs = ApiDBUtils.newSecurityGroupView(group);
 +        List<SecurityGroupResponse> listSgs = ViewResponseHelper.createSecurityGroupResponses(viewSgs);
 +        assert listSgs != null && listSgs.size() == 1 : "There should be one security group returned";
 +        return listSgs.get(0);
 +    }
 +
 +    //TODO: we need to deprecate uploadVO, since extract is done in a synchronous fashion
 +    @Override
 +    public ExtractResponse createExtractResponse(Long id, Long zoneId, Long accountId, String mode, String url) {
 +
 +        ExtractResponse response = new ExtractResponse();
 +        response.setObjectName("template");
 +        VMTemplateVO template = ApiDBUtils.findTemplateById(id);
 +        response.setId(template.getUuid());
 +        response.setName(template.getName());
 +        if (zoneId != null) {
 +            DataCenter zone = ApiDBUtils.findZoneById(zoneId);
 +            response.setZoneId(zone.getUuid());
 +            response.setZoneName(zone.getName());
 +        }
 +        response.setMode(mode);
 +        response.setUrl(url);
 +        response.setState(Upload.Status.DOWNLOAD_URL_CREATED.toString());
 +        Account account = ApiDBUtils.findAccountById(accountId);
 +        response.setAccountId(account.getUuid());
 +
 +        return response;
 +    }
 +
 +    @Override
 +    public ExtractResponse createExtractResponse(Long uploadId, Long id, Long zoneId, Long accountId, String mode, String url) {
 +
 +        ExtractResponse response = new ExtractResponse();
 +        response.setObjectName("template");
 +        VMTemplateVO template = ApiDBUtils.findTemplateById(id);
 +        response.setId(template.getUuid());
 +        response.setName(template.getName());
 +        if (zoneId != null) {
 +            DataCenter zone = ApiDBUtils.findZoneById(zoneId);
 +            response.setZoneId(zone.getUuid());
 +            response.setZoneName(zone.getName());
 +        }
 +        response.setMode(mode);
 +        if (uploadId == null) {
 +            // region-wide image store
 +            response.setUrl(url);
 +            response.setState(Upload.Status.DOWNLOAD_URL_CREATED.toString());
 +        } else {
 +            UploadVO uploadInfo = ApiDBUtils.findUploadById(uploadId);
 +            response.setUploadId(uploadInfo.getUuid());
 +            response.setState(uploadInfo.getUploadState().toString());
 +            response.setUrl(uploadInfo.getUploadUrl());
 +        }
 +        Account account = ApiDBUtils.findAccountById(accountId);
 +        response.setAccountId(account.getUuid());
 +
 +        return response;
 +
 +    }
 +
 +    @Override
 +    public String toSerializedString(CreateCmdResponse response, String responseType) {
 +        return ApiResponseSerializer.toSerializedString(response, responseType);
 +    }
 +
 +    @Override
 +    public List<TemplateResponse> createTemplateResponses(ResponseView view, long templateId, Long snapshotId, Long volumeId, boolean readyOnly) {
 +        Long zoneId = null;
 +
 +        if (snapshotId != null) {
 +            Snapshot snapshot = ApiDBUtils.findSnapshotById(snapshotId);
 +            VolumeVO volume = findVolumeById(snapshot.getVolumeId());
 +
 +            // it seems that the volume can actually be removed from the DB at some point if it's deleted
 +            // if volume comes back null, use another technique to try to discover the zone
 +            if (volume == null) {
 +                SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Primary);
 +
 +                if (snapshotStore != null) {
 +                    long storagePoolId = snapshotStore.getDataStoreId();
 +
 +                    StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);
 +
 +                    if (storagePool != null) {
 +                        zoneId = storagePool.getDataCenterId();
 +                    }
 +                }
 +            }
 +            else {
 +                zoneId = volume.getDataCenterId();
 +            }
 +        } else {
 +            VolumeVO volume = findVolumeById(volumeId);
 +
 +            zoneId = volume.getDataCenterId();
 +        }
 +
 +        if (zoneId == null) {
 +            throw new CloudRuntimeException("Unable to determine the zone ID");
 +        }
 +
 +        return createTemplateResponses(view, templateId, zoneId, readyOnly);
 +    }
 +
 +    @Override
 +    public List<TemplateResponse> createTemplateResponses(ResponseView view, long templateId, Long vmId) {
 +        UserVm vm = findUserVmById(vmId);
 +        Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
 +        Host host = findHostById(hostId);
 +        return createTemplateResponses(view, templateId, host.getDataCenterId(), true);
 +    }
 +
 +    @Override
 +    public EventResponse createEventResponse(Event event) {
 +        EventJoinVO vEvent = ApiDBUtils.newEventView(event);
 +        return ApiDBUtils.newEventResponse(vEvent);
 +    }
 +
 +    @Override
 +    public List<CapacityResponse> createCapacityResponse(List<? extends Capacity> result, DecimalFormat format) {
 +        List<CapacityResponse> capacityResponses = new ArrayList<CapacityResponse>();
 +
 +        for (Capacity summedCapacity : result) {
 +            CapacityResponse capacityResponse = new CapacityResponse();
 +            capacityResponse.setCapacityTotal(summedCapacity.getTotalCapacity());
 +            if (summedCapacity.getAllocatedCapacity() != null) {
 +                capacityResponse.setCapacityAllocated(summedCapacity.getAllocatedCapacity());
 +            }
 +            capacityResponse.setCapacityType(summedCapacity.getCapacityType());
 +            capacityResponse.setCapacityName(CapacityVO.getCapacityName(summedCapacity.getCapacityType()));
 +            capacityResponse.setCapacityUsed(summedCapacity.getUsedCapacity());
 +            if (summedCapacity.getPodId() != null) {
 +                capacityResponse.setPodId(ApiDBUtils.findPodById(summedCapacity.getPodId()).getUuid());
 +                HostPodVO pod = ApiDBUtils.findPodById(summedCapacity.getPodId());
 +                if (pod != null) {
 +                    capacityResponse.setPodId(pod.getUuid());
 +                    capacityResponse.setPodName(pod.getName());
 +                }
 +            }
 +            if (summedCapacity.getClusterId() != null) {
 +                ClusterVO cluster = ApiDBUtils.findClusterById(summedCapacity.getClusterId());
 +                if (cluster != null) {
 +                    capacityResponse.setClusterId(cluster.getUuid());
 +                    capacityResponse.setClusterName(cluster.getName());
 +                    if (summedCapacity.getPodId() == null) {
 +                        HostPodVO pod = ApiDBUtils.findPodById(cluster.getPodId());
 +                        capacityResponse.setPodId(pod.getUuid());
 +                        capacityResponse.setPodName(pod.getName());
 +                    }
 +                }
 +            }
 +            DataCenter zone = ApiDBUtils.findZoneById(summedCapacity.getDataCenterId());
 +            if (zone != null) {
 +                capacityResponse.setZoneId(zone.getUuid());
 +                capacityResponse.setZoneName(zone.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);
 +        }
 +
 +        List<VgpuTypesInfo> gpuCapacities;
 +        if (result.size() > 1 && (gpuCapacities = ApiDBUtils.getGpuCapacites(result.get(0).getDataCenterId(), result.get(0).getPodId(), result.get(0).getClusterId())) != null) {
 +            HashMap<String, Long> vgpuVMs = ApiDBUtils.getVgpuVmsCount(result.get(0).getDataCenterId(), result.get(0).getPodId(), result.get(0).getClusterId());
 +
 +            float capacityUsed = 0;
 +            long capacityMax = 0;
 +            for (VgpuTypesInfo capacity : gpuCapacities) {
 +                if (vgpuVMs.containsKey(capacity.getGroupName().concat(capacity.getModelName()))) {
 +                    capacityUsed += (float)vgpuVMs.get(capacity.getGroupName().concat(capacity.getModelName())) / capacity.getMaxVpuPerGpu();
 +                }
 +                if (capacity.getModelName().equals(GPU.GPUType.passthrough.toString())) {
 +                    capacityMax += capacity.getMaxCapacity();
 +                }
 +            }
 +
 +            DataCenter zone = ApiDBUtils.findZoneById(result.get(0).getDataCenterId());
 +            CapacityResponse capacityResponse = new CapacityResponse();
 +            if (zone != null) {
 +                capacityResponse.setZoneId(zone.getUuid());
 +                capacityResponse.setZoneName(zone.getName());
 +            }
 +            if (result.get(0).getPodId() != null) {
 +                HostPodVO pod = ApiDBUtils.findPodById(result.get(0).getPodId());
 +                capacityResponse.setPodId(pod.getUuid());
 +                capacityResponse.setPodName(pod.getName());
 +            }
 +            if (result.get(0).getClusterId() != null) {
 +                ClusterVO cluster = ApiDBUtils.findClusterById(result.get(0).getClusterId());
 +                capacityResponse.setClusterId(cluster.getUuid());
 +                capacityResponse.setClusterName(cluster.getName());
 +            }
 +            capacityResponse.setCapacityType(Capacity.CAPACITY_TYPE_GPU);
 +            capacityResponse.setCapacityName(CapacityVO.getCapacityName(Capacity.CAPACITY_TYPE_GPU));
 +            capacityResponse.setCapacityUsed((long)Math.ceil(capacityUsed));
 +            capacityResponse.setCapacityTotal(capacityMax);
 +            if (capacityMax > 0) {
 +                capacityResponse.setPercentUsed(format.format(capacityUsed / capacityMax * 100f));
 +            } else {
 +                capacityResponse.setPercentUsed(format.format(0));
 +            }
 +            capacityResponse.setObjectName("capacity");
 +            capacityResponses.add(capacityResponse);
 +        }
 +        return capacityResponses;
 +    }
 +
 +    @Override
 +    public TemplatePermissionsResponse createTemplatePermissionsResponse(ResponseView view, List<String> accountNames, Long id) {
 +        Long templateOwnerDomain = null;
 +        VirtualMachineTemplate template = ApiDBUtils.findTemplateById(id);
 +        Account templateOwner = ApiDBUtils.findAccountById(template.getAccountId());
 +        if (view == ResponseView.Full) {
 +            // 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.getUuid());
 +        response.setPublicTemplate(template.isPublicTemplate());
 +        if ((view == ResponseView.Full) && (templateOwnerDomain != null)) {
 +            Domain domain = ApiDBUtils.findDomainById(templateOwnerDomain);
 +            if (domain != null) {
 +                response.setDomainId(domain.getUuid());
 +            }
 +        }
 +
 +        // Set accounts
 +        List<String> projectIds = new ArrayList<String>();
 +        List<String> regularAccounts = new ArrayList<String>();
 +        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) {
 +        Account caller = CallContext.current().getCallingAccount();
 +
 +        AsyncJob job = _entityMgr.findById(AsyncJob.class, cmd.getId());
 +        if (job == null) {
 +            throw new InvalidParameterValueException("Unable to find a job by id " + cmd.getId());
 +        }
 +
 +        User userJobOwner = _accountMgr.getUserIncludingRemoved(job.getUserId());
 +        Account jobOwner = _accountMgr.getAccount(userJobOwner.getAccountId());
 +
 +        //check permissions
 +        if (_accountMgr.isNormalUser(caller.getId())) {
 +            //regular user can see only jobs he owns
 +            if (caller.getId() != jobOwner.getId()) {
 +                throw new PermissionDeniedException("Account " + caller + " is not authorized to see job id=" + job.getId());
 +            }
 +        } else if (_accountMgr.isDomainAdmin(caller.getId())) {
 +            _accountMgr.checkAccess(caller, null, true, jobOwner);
 +        }
 +
 +        return createAsyncJobResponse(_jobMgr.queryJob(cmd.getId(), true));
 +    }
 +
 +    public AsyncJobResponse createAsyncJobResponse(AsyncJob job) {
 +        AsyncJobJoinVO vJob = ApiDBUtils.newAsyncJobView(job);
 +        return ApiDBUtils.newAsyncJobResponse(vJob);
 +    }
 +
 +    @Override
 +    public SecurityGroupResponse createSecurityGroupResponseFromSecurityGroupRule(List<? extends SecurityRule> securityRules) {
 +        SecurityGroupResponse response = new SecurityGroupResponse();
 +        Map<Long, Account> securiytGroupAccounts = new HashMap<Long, Account>();
 +
 +        if ((securityRules != null) && !securityRules.isEmpty()) {
 +            SecurityGroupJoinVO securityGroup = ApiDBUtils.findSecurityGroupViewById(securityRules.get(0).getSecurityGroupId()).get(0);
 +            response.setId(securityGroup.getUuid());
 +            response.setName(securityGroup.getName());
 +            response.setDescription(securityGroup.getDescription());
 +
 +            Account account = securiytGroupAccounts.get(securityGroup.getAccountId());
 +
 +            if (securityGroup.getAccountType() == Account.ACCOUNT_TYPE_PROJECT) {
 +                response.setProjectId(securityGroup.getProjectUuid());
 +                response.setProjectName(securityGroup.getProjectName());
 +            } else {
 +                response.setAccountName(securityGroup.getAccountName());
 +            }
 +
 +            response.setDomainId(securityGroup.getDomainUuid());
 +            response.setDomainName(securityGroup.getDomainName());
 +
 +            for (SecurityRule securityRule : securityRules) {
 +                SecurityGroupRuleResponse securityGroupData = new SecurityGroupRuleResponse();
 +
 +                securityGroupData.setRuleId(securityRule.getUuid());
 +                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) {
 +                    List<SecurityGroupJoinVO> sgs = ApiDBUtils.findSecurityGroupViewById(allowedSecurityGroupId);
 +                    if (sgs != null && sgs.size() > 0) {
 +                        SecurityGroupJoinVO sg = sgs.get(0);
 +                        securityGroupData.setSecurityGroupName(sg.getName());
 +                        securityGroupData.setAccountName(sg.getAccountName());
 +                    }
 +                } else {
 +                    securityGroupData.setCidr(securityRule.getAllowedSourceIpCidr());
 +                }
 +                if (securityRule.getRuleType() == SecurityRuleType.IngressRule) {
 +                    securityGroupData.setObjectName("ingressrule");
 +                    response.addSecurityGroupIngressRule(securityGroupData);
 +                } else {
 +                    securityGroupData.setObjectName("egressrule");
 +                    response.addSecurityGroupEgressRule(securityGroupData);
 +                }
 +
 +            }
 +            response.setObjectName("securitygroup");
 +
 +        }
 +        return response;
 +    }
 +
 +    @Override
 +    public NetworkOfferingResponse createNetworkOfferingResponse(NetworkOffering offering) {
 +        NetworkOfferingResponse response = new NetworkOfferingResponse();
 +        response.setId(offering.getUuid());
 +        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.setIsPersistent(offering.getIsPersistent());
 +        response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId()));
 +        response.setEgressDefaultPolicy(offering.getEgressDefaultPolicy());
 +        response.setConcurrentConnections(offering.getConcurrentConnections());
 +        response.setSupportsStrechedL2Subnet(offering.getSupportsStrechedL2());
 +        response.setSupportsPublicAccess(offering.getSupportsPublicAccess());
 +        Long so = null;
 +        if (offering.getServiceOfferingId() != null) {
 +            so = offering.getServiceOfferingId();
 +        } else {
 +            so = ApiDBUtils.findDefaultRouterServiceOffering();
 +        }
 +        if (so != null) {
 +            ServiceOffering soffering = ApiDBUtils.findServiceOfferingById(so);
 +            if (soffering != null) {
 +                response.setServiceOfferingId(soffering.getUuid());
 +            }
 +        }
 +
 +        if (offering.getGuestType() != null) {
 +            response.setGuestIpType(offering.getGuestType().toString());
 +        }
 +
 +        response.setState(offering.getState().name());
 +
 +        Map<Service, Set<Provider>> serviceProviderMap = ApiDBUtils.listNetworkOfferingServices(offering.getId());
 +        List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();
 +        for (Map.Entry<Service,Set<Provider>> entry : serviceProviderMap.entrySet()) {
 +            Service service = entry.getKey();
 +            Set<Provider> srvc_providers = entry.getValue();
 +            ServiceResponse svcRsp = new ServiceResponse();
 +            // skip gateway service
 +            if (service == Service.Gateway) {
 +                continue;
 +            }
 +            svcRsp.setName(service.getName());
 +            List<ProviderResponse> providers = new ArrayList<ProviderResponse>();
 +            for (Provider provider : srvc_providers) {
 +                if (provider != null) {
 +                    ProviderResponse providerRsp = new ProviderResponse();
 +                    providerRsp.setName(provider.getName());
 +                    providers.add(providerRsp);
 +                }
 +            }
 +            svcRsp.setProviders(providers);
 +
 +            if (Service.Lb == service) {
 +                List<CapabilityResponse> lbCapResponse = new ArrayList<CapabilityResponse>();
 +
 +                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);
 +
 +                CapabilityResponse inline = new CapabilityResponse();
 +                inline.setName(Capability.InlineMode.getName());
 +                inline.setValue(offering.isInline() ? "true" : "false");
 +                lbCapResponse.add(inline);
 +
 +                svcRsp.setCapabilities(lbCapResponse);
 +            } else if (Service.SourceNat == service) {
 +                List<CapabilityResponse> capabilities = new ArrayList<CapabilityResponse>();
 +                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<CapabilityResponse> staticNatCapResponse = new ArrayList<CapabilityResponse>();
 +
 +                CapabilityResponse eIp = new CapabilityResponse();
 +                eIp.setName(Capability.ElasticIp.getName());
 +                eIp.setValue(offering.getElasticIp() ? "true" : "false");
 +                staticNatCapResponse.add(eIp);
 +
 +                CapabilityResponse associatePublicIp = new CapabilityResponse();
 +                associatePublicIp.setName(Capability.AssociatePublicIP.getName());
 +                associatePublicIp.setValue(offering.getAssociatePublicIP() ? "true" : "false");
 +                staticNatCapResponse.add(associatePublicIp);
 +
 +                svcRsp.setCapabilities(staticNatCapResponse);
 +            }
 +
 +            serviceResponses.add(svcRsp);
 +        }
 +        response.setForVpc(_configMgr.isOfferingForVpc(offering));
 +
 +        response.setServices(serviceResponses);
 +
 +        //set network offering details
 +        Map<Detail, String> details = _ntwkModel.getNtwkOffDetails(offering.getId());
 +        if (details != null && !details.isEmpty()) {
 +            response.setDetails(details);
 +        }
 +
 +        response.setObjectName("networkoffering");
 +        return response;
 +    }
 +
 +    @Override
 +    public NetworkResponse createNetworkResponse(ResponseView view, 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.getUuid());
 +        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.getNetworkCidr() != null) {
 +            response.setNetworkCidr((network.getNetworkCidr()));
 +        }
 +        // If network has reservation its entire network cidr is defined by
 +        // getNetworkCidr()
 +        // if no reservation is present then getCidr() will define the entire
 +        // network cidr
 +        if (network.getNetworkCidr() != null) {
 +            response.setNetmask(NetUtils.cidr2Netmask(network.getNetworkCidr()));
 +        }
 +        if (((network.getCidr()) != null) && (network.getNetworkCidr() == null)) {
 +            response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
 +        }
 +
 +        response.setIp6Gateway(network.getIp6Gateway());
 +        response.setIp6Cidr(network.getIp6Cidr());
 +
 +        // create response for reserved IP ranges that can be used for
 +        // non-cloudstack purposes
 +        String reservation = null;
 +        if ((network.getCidr() != null) && (NetUtils.isNetworkAWithinNetworkB(network.getCidr(), network.getNetworkCidr()))) {
 +            String[] guestVmCidrPair = network.getCidr().split("\\/");
 +            String[] guestCidrPair = network.getNetworkCidr().split("\\/");
 +
 +            Long guestVmCidrSize = Long.valueOf(guestVmCidrPair[1]);
 +            Long guestCidrSize = Long.valueOf(guestCidrPair[1]);
 +
 +            String[] guestVmIpRange = NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], guestVmCidrSize);
 +            String[] guestIpRange = NetUtils.getIpRangeFromCidr(guestCidrPair[0], guestCidrSize);
 +            long startGuestIp = NetUtils.ip2Long(guestIpRange[0]);
 +            long endGuestIp = NetUtils.ip2Long(guestIpRange[1]);
 +            long startVmIp = NetUtils.ip2Long(guestVmIpRange[0]);
 +            long endVmIp = NetUtils.ip2Long(guestVmIpRange[1]);
 +
 +            if (startVmIp == startGuestIp && endVmIp < endGuestIp - 1) {
 +                reservation = (NetUtils.long2Ip(endVmIp + 1) + "-" + NetUtils.long2Ip(endGuestIp));
 +            }
 +            if (endVmIp == endGuestIp && startVmIp > startGuestIp + 1) {
 +                reservation = (NetUtils.long2Ip(startGuestIp) + "-" + NetUtils.long2Ip(startVmIp - 1));
 +            }
 +            if (startVmIp > startGuestIp + 1 && endVmIp < endGuestIp - 1) {
 +                reservation = (NetUtils.long2Ip(startGuestIp) + "-" + NetUtils.long2Ip(startVmIp - 1) + " ,  " + NetUtils.long2Ip(endVmIp + 1) + "-" + NetUtils.long2Ip(endGuestIp));
 +            }
 +        }
 +        response.setReservedIpRange(reservation);
 +
 +        // return vlan information only to Root admin
 +        if (network.getBroadcastUri() != null && view == ResponseView.Full) {
 +            String broadcastUri = network.getBroadcastUri().toString();
 +            response.setBroadcastUri(broadcastUri);
 +            String vlan = "N/A";
 +            switch (BroadcastDomainType.getSchemeValue(network.getBroadcastUri())) {
 +            case Vlan:
 +            case Vxlan:
 +                vlan = BroadcastDomainType.getValue(network.getBroadcastUri());
 +                break;
 +            }
 +            // return vlan information only to Root admin
 +            response.setVlan(vlan);
 +        }
 +
 +        DataCenter zone = ApiDBUtils.findZoneById(network.getDataCenterId());
 +        if (zone != null) {
 +            response.setZoneId(zone.getUuid());
 +            response.setZoneName(zone.getName());
 +        }
 +        if (network.getPhysicalNetworkId() != null) {
 +            PhysicalNetworkVO pnet = ApiDBUtils.findPhysicalNetworkById(network.getPhysicalNetworkId());
 +            response.setPhysicalNetworkId(pnet.getUuid());
 +        }
 +
 +        // populate network offering information
 +        NetworkOffering networkOffering = ApiDBUtils.findNetworkOfferingById(network.getNetworkOfferingId());
 +        if (networkOffering != null) {
 +            response.setNetworkOfferingId(networkOffering.getUuid());
 +            response.setNetworkOfferingName(networkOffering.getName());
 +            response.setNetworkOfferingDisplayText(networkOffering.getDisplayText());
 +            response.setNetworkOfferingConserveMode(networkOffering.isConserveMode());
 +            response.setIsSystem(networkOffering.isSystemOnly());
 +            response.setNetworkOfferingAvailability(networkOffering.getAvailability().toString());
 +            response.setIsPersistent(networkOffering.getIsPersistent());
 +        }
 +
 +        if (network.getAclType() != null) {
 +            response.setAclType(network.getAclType().toString());
 +        }
 +        response.setDisplayNetwork(network.getDisplayNetwork());
 +        response.setState(network.getState().toString());
 +        response.setRestartRequired(network.isRestartRequired());
 +        NetworkVO nw = ApiDBUtils.findNetworkById(network.getRelated());
 +        if (nw != null) {
 +            response.setRelated(nw.getUuid());
 +        }
 +        response.setNetworkDomain(network.getNetworkDomain());
 +
 +        response.setDns1(profile.getDns1());
 +        response.setDns2(profile.getDns2());
 +        // populate capability
 +        Map<Service, Map<Capability, String>> serviceCapabilitiesMap = ApiDBUtils.getNetworkCapabilities(network.getId(), network.getDataCenterId());
 +        List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();
 +        if (serviceCapabilitiesMap != null) {
 +            for (Map.Entry<Service, Map<Capability, String>>entry : serviceCapabilitiesMap.entrySet()) {
 +                Service service = entry.getKey();
 +                ServiceResponse serviceResponse = new ServiceResponse();
 +                // skip gateway service
 +                if (service == Service.Gateway) {
 +                    continue;
 +                }
 +                serviceResponse.setName(service.getName());
 +
 +                // set list of capabilities for the service
 +                List<CapabilityResponse> capabilityResponses = new ArrayList<CapabilityResponse>();
 +                Map<Capability, String> serviceCapabilities = entry.getValue();
 +                if (serviceCapabilities != null) {
 +                    for (Map.Entry<Capability,String> ser_cap_entries : serviceCapabilities.entrySet()) {
 +                        Capability capability = ser_cap_entries.getKey();
 +                        CapabilityResponse capabilityResponse = new CapabilityResponse();
 +                        String capabilityValue = ser_cap_entries.getValue();
 +                        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<Long, Boolean> domainNetworkDetails = ApiDBUtils.getDomainNetworkDetails(network.getId());
 +            if (domainNetworkDetails.first() != null) {
 +                Domain domain = ApiDBUtils.findDomainById(domainNetworkDetails.first());
 +                if (domain != null) {
 +                    response.setDomainId(domain.getUuid());
 +                }
 +            }
 +            response.setSubdomainAccess(domainNetworkDetails.second());
 +        }
 +
 +        Long dedicatedDomainId = ApiDBUtils.getDedicatedNetworkDomain(network.getId());
 +        if (dedicatedDomainId != null) {
 +            Domain domain = ApiDBUtils.findDomainById(dedicatedDomainId);
 +            if (domain != null) {
 +                response.setDomainId(domain.getUuid());
 +                response.setDomainName(domain.getName());
 +            }
 +
 +        }
 +
 +        response.setSpecifyIpRanges(network.getSpecifyIpRanges());
 +        if (network.getVpcId() != null) {
 +            Vpc vpc = ApiDBUtils.findVpcById(network.getVpcId());
 +            if (vpc != null) {
 +                response.setVpcId(vpc.getUuid());
 +            }
 +        }
 +        response.setCanUseForDeploy(ApiDBUtils.canUseForDeploy(network));
 +
 +        // set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.Network, network.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        response.setTags(tagResponses);
 +
 +        if (network.getNetworkACLId() != null) {
 +            NetworkACL acl = ApiDBUtils.findByNetworkACLId(network.getNetworkACLId());
 +            if (acl != null) {
 +                response.setAclId(acl.getUuid());
 +            }
 +        }
 +
 +        response.setStrechedL2Subnet(network.isStrechedL2Network());
 +        if (network.isStrechedL2Network()) {
 +            Set<String> networkSpannedZones = new  HashSet<String>();
 +            List<VMInstanceVO> vmInstances = new ArrayList<VMInstanceVO>();
 +            vmInstances.addAll(ApiDBUtils.listUserVMsByNetworkId(network.getId()));
 +            vmInstances.addAll(ApiDBUtils.listDomainRoutersByNetworkId(network.getId()));
 +            for (VirtualMachine vm : vmInstances) {
 +                DataCenter vmZone = ApiDBUtils.findZoneById(vm.getDataCenterId());
 +                networkSpannedZones.add(vmZone.getUuid());
 +            }
 +            response.setNetworkSpannedZones(networkSpannedZones);
 +        }
 +        response.setExternalId(network.getExternalId());
++        response.setRedundantRouter(network.isRedundant());
 +        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) {
 +        List<ProjectJoinVO> viewPrjs = ApiDBUtils.newProjectView(project);
 +        List<ProjectResponse> listPrjs = ViewResponseHelper.createProjectResponse(viewPrjs.toArray(new ProjectJoinVO[viewPrjs.size()]));
 +        assert listPrjs != null && listPrjs.size() == 1 : "There should be one project  returned";
 +        return listPrjs.get(0);
 +    }
 +
 +    @Override
 +    public FirewallResponse createFirewallResponse(FirewallRule fwRule) {
 +        FirewallResponse response = new FirewallResponse();
 +
 +        response.setId(fwRule.getUuid());
 +        response.setProtocol(fwRule.getProtocol());
 +        if (fwRule.getSourcePortStart() != null) {
 +            response.setStartPort(fwRule.getSourcePortStart());
 +        }
 +
 +        if (fwRule.getSourcePortEnd() != null) {
 +            response.setEndPort(fwRule.getSourcePortEnd());
 +        }
 +
 +        List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
 +        response.setCidrList(StringUtils.join(cidrs, ","));
 +
 +        if(fwRule.getTrafficType() == FirewallRule.TrafficType.Egress){
 +            List<String> destCidrs = ApiDBUtils.findFirewallDestCidrs(fwRule.getId());
 +            response.setDestCidr(StringUtils.join(destCidrs,","));
 +        }
 +
 +        if (fwRule.getTrafficType() == FirewallRule.TrafficType.Ingress) {
 +            IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
 +            response.setPublicIpAddressId(ip.getUuid());
 +            response.setPublicIpAddress(ip.getAddress().addr());
 +        }
 +
 +            Network network = ApiDBUtils.findNetworkById(fwRule.getNetworkId());
 +            response.setNetworkId(network.getUuid());
 +
 +        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());
 +        response.setForDisplay(fwRule.isDisplay());
 +
 +        // set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.FirewallRule, fwRule.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        response.setTags(tagResponses);
 +
 +        response.setState(stateToSet);
 +        response.setObjectName("firewallrule");
 +        return response;
 +    }
 +
 +    @Override
 +    public NetworkACLItemResponse createNetworkACLItemResponse(NetworkACLItem aclItem) {
 +        NetworkACLItemResponse response = new NetworkACLItemResponse();
 +
 +        response.setId(aclItem.getUuid());
 +        response.setProtocol(aclItem.getProtocol());
 +        if (aclItem.getSourcePortStart() != null) {
 +            response.setStartPort(Integer.toString(aclItem.getSourcePortStart()));
 +        }
 +
 +        if (aclItem.getSourcePortEnd() != null) {
 +            response.setEndPort(Integer.toString(aclItem.getSourcePortEnd()));
 +        }
 +
 +        response.setCidrList(StringUtils.join(aclItem.getSourceCidrList(), ","));
 +
 +        response.setTrafficType(aclItem.getTrafficType().toString());
 +
 +        NetworkACLItem.State state = aclItem.getState();
 +        String stateToSet = state.toString();
 +        if (state.equals(NetworkACLItem.State.Revoke)) {
 +            stateToSet = "Deleting";
 +        }
 +
 +        response.setIcmpCode(aclItem.getIcmpCode());
 +        response.setIcmpType(aclItem.getIcmpType());
 +
 +        response.setState(stateToSet);
 +        response.setNumber(aclItem.getNumber());
 +        response.setAction(aclItem.getAction().toString());
 +        response.setForDisplay(aclItem.isDisplay());
 +
 +        NetworkACL acl = ApiDBUtils.findByNetworkACLId(aclItem.getAclId());
 +        if (acl != null) {
 +            response.setAclId(acl.getUuid());
 +        }
 +
 +        //set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.NetworkACL, aclItem.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        response.setTags(tagResponses);
 +        response.setReason(aclItem.getReason());
 +        response.setObjectName("networkacl");
 +        return response;
 +    }
 +
 +    @Override
 +    public HypervisorCapabilitiesResponse createHypervisorCapabilitiesResponse(HypervisorCapabilities hpvCapabilities) {
 +        HypervisorCapabilitiesResponse hpvCapabilitiesResponse = new HypervisorCapabilitiesResponse();
 +        hpvCapabilitiesResponse.setId(hpvCapabilities.getUuid());
 +        hpvCapabilitiesResponse.setHypervisor(hpvCapabilities.getHypervisorType());
 +        hpvCapabilitiesResponse.setHypervisorVersion(hpvCapabilities.getHypervisorVersion());
 +        hpvCapabilitiesResponse.setIsSecurityGroupEnabled(hpvCapabilities.isSecurityGroupEnabled());
 +        hpvCapabilitiesResponse.setMaxGuestsLimit(hpvCapabilities.getMaxGuestsLimit());
 +        hpvCapabilitiesResponse.setMaxDataVolumesLimit(hpvCapabilities.getMaxDataVolumesLimit());
 +        hpvCapabilitiesResponse.setMaxHostsPerCluster(hpvCapabilities.getMaxHostsPerCluster());
 +        hpvCapabilitiesResponse.setIsStorageMotionSupported(hpvCapabilities.isStorageMotionSupported());
 +        return hpvCapabilitiesResponse;
 +    }
 +
 +    // TODO: we may need to refactor once ControlledEntityResponse and
 +    // ControlledEntity id to uuid conversion are all done.
 +    // currently code is scattered in
 +    private void populateOwner(ControlledEntityResponse response, ControlledEntity object) {
 +        Account account = ApiDBUtils.findAccountById(object.getAccountId());
 +
 +        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
 +            // find the project
 +            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
 +            response.setProjectId(project.getUuid());
 +            response.setProjectName(project.getName());
 +        } else {
 +            response.setAccountName(account.getAccountName());
 +        }
 +
 +        Domain domain = ApiDBUtils.findDomainById(object.getDomainId());
 +        response.setDomainId(domain.getUuid());
 +        response.setDomainName(domain.getName());
 +    }
 +
 +    public static void populateOwner(ControlledViewEntityResponse response, ControlledViewEntity object) {
 +
 +        if (object.getAccountType() == Account.ACCOUNT_TYPE_PROJECT) {
 +            response.setProjectId(object.getProjectUuid());
 +            response.setProjectName(object.getProjectName());
 +        } else {
 +            response.setAccountName(object.getAccountName());
 +        }
 +
 +        response.setDomainId(object.getDomainUuid());
 +        response.setDomainName(object.getDomainName());
 +    }
 +
 +    private void populateAccount(ControlledEntityResponse response, long accountId) {
 +        Account account = ApiDBUtils.findAccountById(accountId);
 +        if (account == null) {
 +            s_logger.debug("Unable to find account with id: " + accountId);
 +        } else if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
 +            // find the project
 +            Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
 +            if (project != null) {
 +                response.setProjectId(project.getUuid());
 +                response.setProjectName(project.getName());
 +                response.setAccountName(account.getAccountName());
 +            } else {
 +                s_logger.debug("Unable to find project with id: " + account.getId());
 +            }
 +        } else {
 +            response.setAccountName(account.getAccountName());
 +        }
 +    }
 +
 +    private void populateDomain(ControlledEntityResponse response, long domainId) {
 +        Domain domain = ApiDBUtils.findDomainById(domainId);
 +
 +        response.setDomainId(domain.getUuid());
 +        response.setDomainName(domain.getName());
 +    }
 +
 +    @Override
 +    public ProjectAccountResponse createProjectAccountResponse(ProjectAccount projectAccount) {
 +        ProjectAccountJoinVO vProj = ApiDBUtils.newProjectAccountView(projectAccount);
 +        List<ProjectAccountResponse> listProjs = ViewResponseHelper.createProjectAccountResponse(vProj);
 +        assert listProjs != null && listProjs.size() == 1 : "There should be one project account returned";
 +        return listProjs.get(0);
 +    }
 +
 +    @Override
 +    public ProjectInvitationResponse createProjectInvitationResponse(ProjectInvitation invite) {
 +        ProjectInvitationJoinVO vInvite = ApiDBUtils.newProjectInvitationView(invite);
 +        return ApiDBUtils.newProjectInvitationResponse(vInvite);
 +    }
 +
 +    @Override
 +    public SystemVmInstanceResponse createSystemVmInstanceResponse(VirtualMachine vm) {
 +        SystemVmInstanceResponse vmResponse = new SystemVmInstanceResponse();
 +        vmResponse.setId(vm.getUuid());
 +        vmResponse.setSystemVmType(vm.getType().toString().toLowerCase());
 +        vmResponse.setName(vm.getHostName());
 +        if (vm.getHostId() != null) {
 +            Host host = ApiDBUtils.findHostById(vm.getHostId());
 +            if (host != null) {
 +                vmResponse.setHostId(host.getUuid());
 +            }
 +        }
 +        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();
 +
 +        DataCenter zone = ApiDBUtils.findZoneById(result.getDataCenterId());
 +        if (zone != null) {
 +            response.setZoneId(zone.getUuid());
 +        }
 +        response.setNetworkSpeed(result.getSpeed());
 +        response.setVlan(result.getVnetString());
 +        if (result.getDomainId() != null) {
 +            Domain domain = ApiDBUtils.findDomainById(result.getDomainId());
 +            if (domain != null) {
 +                response.setDomainId(domain.getUuid());
 +            }
 +        }
 +        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 GuestVlanRangeResponse createDedicatedGuestVlanRangeResponse(GuestVlan vlan) {
 +        GuestVlanRangeResponse guestVlanRangeResponse = new GuestVlanRangeResponse();
 +
 +        guestVlanRangeResponse.setId(vlan.getUuid());
 +        Long accountId = ApiDBUtils.getAccountIdForGuestVlan(vlan.getId());
 +        Account owner = ApiDBUtils.findAccountById(accountId);
 +        if (owner != null) {
 +            populateAccount(guestVlanRangeResponse, owner.getId());
 +            populateDomain(guestVlanRangeResponse, owner.getDomainId());
 +        }
 +        guestVlanRangeResponse.setGuestVlanRange(vlan.getGuestVlanRange());
 +        guestVlanRangeResponse.setPhysicalNetworkId(vlan.getPhysicalNetworkId());
 +        PhysicalNetworkVO physicalNetwork = ApiDBUtils.findPhysicalNetworkById(vlan.getPhysicalNetworkId());
 +        guestVlanRangeResponse.setZoneId(physicalNetwork.getDataCenterId());
 +
 +        return guestVlanRangeResponse;
 +    }
 +
 +    @Override
 +    public ServiceResponse createNetworkServiceResponse(Service service) {
 +        ServiceResponse response = new ServiceResponse();
 +        response.setName(service.getName());
 +
 +        // set list of capabilities required for the service
 +        List<CapabilityResponse> capabilityResponses = new ArrayList<CapabilityResponse>();
 +        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<? extends Network.Provider> serviceProviders = ApiDBUtils.getProvidersForService(service);
 +        List<ProviderResponse> serviceProvidersResponses = new ArrayList<ProviderResponse>();
 +        for (Network.Provider serviceProvider : serviceProviders) {
 +            // return only Virtual Router/JuniperSRX/CiscoVnmc as a provider for the firewall
 +            if (service == Service.Firewall
 +                    && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX || serviceProvider == Provider.CiscoVnmc || serviceProvider == Provider.PaloAlto || serviceProvider == Provider.NuageVsp || serviceProvider == Provider.BigSwitchBcf)) {
 +                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());
 +        PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(result.getPhysicalNetworkId());
 +        if (pnw != null) {
 +            response.setPhysicalNetworkId(pnw.getUuid());
 +        }
 +        PhysicalNetwork dnw = ApiDBUtils.findPhysicalNetworkById(result.getDestinationPhysicalNetworkId());
 +        if (dnw != null) {
 +            response.setDestinationPhysicalNetworkId(dnw.getUuid());
 +        }
 +        response.setState(result.getState().toString());
 +
 +        // set enabled services
 +        List<String> services = new ArrayList<String>();
 +        for (Service service : result.getEnabledServices()) {
 +            services.add(service.getName());
 +        }
 +        response.setServices(services);
 +
 +        Provider serviceProvider = Provider.getProvider(result.getProviderName());
 +        boolean canEnableIndividualServices = ApiDBUtils.canElementEnableIndividualServices(serviceProvider);
 +        response.setCanEnableIndividualServices(canEnableIndividualServices);
 +
 +        response.setObjectName("networkserviceprovider");
 +        return response;
 +    }
 +
 +    @Override
 +    public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType result) {
 +        TrafficTypeResponse response = new TrafficTypeResponse();
 +        response.setId(result.getUuid());
 +        PhysicalNetwork pnet = ApiDBUtils.findPhysicalNetworkById(result.getPhysicalNetworkId());
 +        if (pnet != null) {
 +            response.setPhysicalNetworkId(pnet.getUuid());
 +        }
 +        if (result.getTrafficType() != null) {
 +            response.setTrafficType(result.getTrafficType().toString());
 +        }
 +
 +        response.setXenLabel(result.getXenNetworkLabel());
 +        response.setKvmLabel(result.getKvmNetworkLabel());
 +        response.setVmwareLabel(result.getVmwareNetworkLabel());
 +        response.setHypervLabel(result.getHypervNetworkLabel());
 +        response.setOvm3Label(result.getOvm3NetworkLabel());
 +
 +        response.setObjectName("traffictype");
 +        return response;
 +    }
 +
 +    @Override
 +    public VirtualRouterProviderResponse createVirtualRouterProviderResponse(VirtualRouterProvider result) {
 +        //generate only response of the VR/VPCVR provider type
 +        if (!(result.getType() == VirtualRouterProvider.Type.VirtualRouter || result.getType() == VirtualRouterProvider.Type.VPCVirtualRouter)) {
 +            return null;
 +        }
 +        VirtualRouterProviderResponse response = new VirtualRouterProviderResponse();
 +        response.setId(result.getUuid());
 +        PhysicalNetworkServiceProvider nsp = ApiDBUtils.findPhysicalNetworkServiceProviderById(result.getNspId());
 +        if (nsp != null) {
 +            response.setNspId(nsp.getUuid());
 +        }
 +        response.setEnabled(result.isEnabled());
 +
 +        response.setObjectName("virtualrouterelement");
 +        return response;
 +    }
 +
 +    @Override
 +    public OvsProviderResponse createOvsProviderResponse(OvsProvider result) {
 +
 +        OvsProviderResponse response = new OvsProviderResponse();
 +        response.setId(result.getUuid());
 +        PhysicalNetworkServiceProvider nsp = ApiDBUtils.findPhysicalNetworkServiceProviderById(result.getNspId());
 +        if (nsp != null) {
 +            response.setNspId(nsp.getUuid());
 +        }
 +        response.setEnabled(result.isEnabled());
 +
 +        response.setObjectName("ovselement");
 +        return response;
 +    }
 +
 +    @Override
 +    public LBStickinessResponse createLBStickinessPolicyResponse(StickinessPolicy stickinessPolicy, LoadBalancer lb) {
 +        LBStickinessResponse spResponse = new LBStickinessResponse();
 +
 +        spResponse.setlbRuleId(lb.getUuid());
 +        Account accountTemp = ApiDBUtils.findAccountById(lb.getAccountId());
 +        if (accountTemp != null) {
 +            spResponse.setAccountName(accountTemp.getAccountName());
 +            Domain domain = ApiDBUtils.findDomainById(accountTemp.getDomainId());
 +            if (domain != null) {
 +                spResponse.setDomainId(domain.getUuid());
 +                spResponse.setDomainName(domain.getName());
 +            }
 +        }
 +
 +        List<LBStickinessPolicyResponse> responses = new ArrayList<LBStickinessPolicyResponse>();
 +        LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(stickinessPolicy);
 +        responses.add(ruleResponse);
 +
 +        spResponse.setRules(responses);
 +
 +        spResponse.setObjectName("stickinesspolicies");
 +        return spResponse;
 +    }
 +
 +    @Override
 +    public LBStickinessResponse createLBStickinessPolicyResponse(List<? extends StickinessPolicy> stickinessPolicies, LoadBalancer lb) {
 +        LBStickinessResponse spResponse = new LBStickinessResponse();
 +
 +        if (lb == null) {
 +            return spResponse;
 +        }
 +        spResponse.setlbRuleId(lb.getUuid());
 +        Account account = ApiDBUtils.findAccountById(lb.getAccountId());
 +        if (account != null) {
 +            spResponse.setAccountName(account.getAccountName());
 +            Domain domain = ApiDBUtils.findDomainById(account.getDomainId());
 +            if (domain != null) {
 +                spResponse.setDomainId(domain.getUuid());
 +                spResponse.setDomainName(domain.getName());
 +            }
 +        }
 +
 +        List<LBStickinessPolicyResponse> responses = new ArrayList<LBStickinessPolicyResponse>();
 +        for (StickinessPolicy stickinessPolicy : stickinessPolicies) {
 +            LBStickinessPolicyResponse ruleResponse = new LBStickinessPolicyResponse(stickinessPolicy);
 +            responses.add(ruleResponse);
 +        }
 +        spResponse.setRules(responses);
 +
 +        spResponse.setObjectName("stickinesspolicies");
 +        return spResponse;
 +    }
 +
 +    @Override
 +    public LBHealthCheckResponse createLBHealthCheckPolicyResponse(List<? extends HealthCheckPolicy> healthcheckPolicies, LoadBalancer lb) {
 +        LBHealthCheckResponse hcResponse = new LBHealthCheckResponse();
 +
 +        if (lb == null) {
 +            return hcResponse;
 +        }
 +        hcResponse.setlbRuleId(lb.getUuid());
 +        Account account = ApiDBUtils.findAccountById(lb.getAccountId());
 +        if (account != null) {
 +            hcResponse.setAccountName(account.getAccountName());
 +            Domain domain = ApiDBUtils.findDomainById(account.getDomainId());
 +            if (domain != null) {
 +                hcResponse.setDomainId(domain.getUuid());
 +                hcResponse.setDomainName(domain.getName());
 +            }
 +        }
 +
 +        List<LBHealthCheckPolicyResponse> responses = new ArrayList<LBHealthCheckPolicyResponse>();
 +        for (HealthCheckPolicy healthcheckPolicy : healthcheckPolicies) {
 +            LBHealthCheckPolicyResponse ruleResponse = new LBHealthCheckPolicyResponse(healthcheckPolicy);
 +            responses.add(ruleResponse);
 +        }
 +        hcResponse.setRules(responses);
 +
 +        hcResponse.setObjectName("healthcheckpolicies");
 +        return hcResponse;
 +    }
 +
 +    @Override
 +    public LBHealthCheckResponse createLBHealthCheckPolicyResponse(HealthCheckPolicy healthcheckPolicy, LoadBalancer lb) {
 +        LBHealthCheckResponse hcResponse = new LBHealthCheckResponse();
 +
 +        hcResponse.setlbRuleId(lb.getUuid());
 +        Account accountTemp = ApiDBUtils.findAccountById(lb.getAccountId());
 +        if (accountTemp != null) {
 +            hcResponse.setAccountName(accountTemp.getAccountName());
 +            Domain domain = ApiDBUtils.findDomainById(accountTemp.getDomainId());
 +            if (domain != null) {
 +                hcResponse.setDomainId(domain.getUuid());
 +                hcResponse.setDomainName(domain.getName());
 +            }
 +        }
 +
 +        List<LBHealthCheckPolicyResponse> responses = new ArrayList<LBHealthCheckPolicyResponse>();
 +        LBHealthCheckPolicyResponse ruleResponse = new LBHealthCheckPolicyResponse(healthcheckPolicy);
 +        responses.add(ruleResponse);
 +        hcResponse.setRules(responses);
 +        hcResponse.setObjectName("healthcheckpolicies");
 +        return hcResponse;
 +    }
 +
 +    @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 RegionResponse createRegionResponse(Region region) {
 +        RegionResponse response = new RegionResponse();
 +        response.setId(region.getId());
 +        response.setName(region.getName());
 +        response.setEndPoint(region.getEndPoint());
 +        response.setObjectName("region");
 +        response.setGslbServiceEnabled(region.checkIfServiceEnabled(Region.Service.Gslb));
 +        response.setPortableipServiceEnabled(region.checkIfServiceEnabled(Region.Service.PortableIp));
 +        return response;
 +    }
 +
 +    @Override
 +    public ResourceTagResponse createResourceTagResponse(ResourceTag resourceTag, boolean keyValueOnly) {
 +        ResourceTagJoinVO rto = ApiDBUtils.newResourceTagView(resourceTag);
 +        if(rto == null)
 +            return null;
 +        return ApiDBUtils.newResourceTagResponse(rto, keyValueOnly);
 +    }
 +
 +    @Override
 +    public VpcOfferingResponse createVpcOfferingResponse(VpcOffering offering) {
 +        VpcOfferingResponse response = new VpcOfferingResponse();
 +        response.setId(offering.getUuid());
 +        response.setName(offering.getName());
 +        response.setDisplayText(offering.getDisplayText());
 +        response.setIsDefault(offering.isDefault());
 +        response.setState(offering.getState().name());
 +        response.setSupportsDistributedRouter(offering.supportsDistributedRouter());
 +        response.setSupportsRegionLevelVpc(offering.offersRegionLevelVPC());
 +
 +        Map<Service, Set<Provider>> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId());
 +        List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();
 +        for (Map.Entry<Service, Set<Provider>> entry : serviceProviderMap.entrySet()) {
 +            Service service = entry.getKey();
 +            Set<Provider> srvc_providers = entry.getValue();
 +
 +            ServiceResponse svcRsp = new ServiceResponse();
 +            // skip gateway service
 +            if (service == Service.Gateway) {
 +                continue;
 +            }
 +            svcRsp.setName(service.getName());
 +            List<ProviderResponse> providers = new ArrayList<ProviderResponse>();
 +            for (Provider provider : srvc_providers) {
 +                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(ResponseView view, Vpc vpc) {
 +        VpcResponse response = new VpcResponse();
 +        response.setId(vpc.getUuid());
 +        response.setName(vpc.getName());
 +        response.setDisplayText(vpc.getDisplayText());
 +        response.setState(vpc.getState().name());
 +        VpcOffering voff = ApiDBUtils.findVpcOfferingById(vpc.getVpcOfferingId());
 +        if (voff != null) {
 +            response.setVpcOfferingId(voff.getUuid());
 +        }
 +        response.setCidr(vpc.getCidr());
 +        response.setRestartRequired(vpc.isRestartRequired());
 +        response.setNetworkDomain(vpc.getNetworkDomain());
 +        response.setForDisplay(vpc.isDisplay());
 +        response.setUsesDistributedRouter(vpc.usesDistributedRouter());
 +        response.setRedundantRouter(vpc.isRedundant());
 +        response.setRegionLevelVpc(vpc.isRegionLevelVpc());
 +
 +        Map<Service, Set<Provider>> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId());
 +        List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();
 +        for (Map.Entry<Service,Set<Provider>>entry : serviceProviderMap.entrySet()) {
 +            Service service = entry.getKey();
 +            Set<Provider> serviceProviders = entry.getValue();
 +            ServiceResponse svcRsp = new ServiceResponse();
 +            // skip gateway service
 +            if (service == Service.Gateway) {
 +                continue;
 +            }
 +            svcRsp.setName(service.getName());
 +            List<ProviderResponse> providers = new ArrayList<ProviderResponse>();
 +            for (Provider provider : serviceProviders) {
 +                if (provider != null) {
 +                    ProviderResponse providerRsp = new ProviderResponse();
 +                    providerRsp.setName(provider.getName());
 +                    providers.add(providerRsp);
 +                }
 +            }
 +            svcRsp.setProviders(providers);
 +
 +            serviceResponses.add(svcRsp);
 +        }
 +
 +        List<NetworkResponse> networkResponses = new ArrayList<NetworkResponse>();
 +        List<? extends Network> networks = ApiDBUtils.listVpcNetworks(vpc.getId());
 +        for (Network network : networks) {
 +            NetworkResponse ntwkRsp = createNetworkResponse(view, network);
 +            networkResponses.add(ntwkRsp);
 +        }
 +
 +        DataCenter zone = ApiDBUtils.findZoneById(vpc.getZoneId());
 +        if (zone != null) {
 +            response.setZoneId(zone.getUuid());
 +            response.setZoneName(zone.getName());
 +        }
 +
 +        response.setNetworks(networkResponses);
 +        response.setServices(serviceResponses);
 +        populateOwner(response, vpc);
 +
 +        // set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.Vpc, vpc.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
 +        }
 +        response.setTags(tagResponses);
 +        response.setObjectName("vpc");
 +        return response;
 +    }
 +
 +    @Override
 +    public PrivateGatewayResponse createPrivateGatewayResponse(PrivateGateway result) {
 +        PrivateGatewayResponse response = new PrivateGatewayResponse();
 +        response.setId(result.getUuid());
 +        response.setBroadcastUri(result.getBroadcastUri());
 +        response.setGateway(result.getGateway());
 +        response.setNetmask(result.getNetmask());
 +        if (result.getVpcId() != null) {
 +            Vpc vpc = ApiDBUtils.findVpcById(result.getVpcId());
 +            response.setVpcId(vpc.getUuid());
 +        }
 +
 +        DataCenter zone = ApiDBUtils.findZoneById(result.getZoneId());
 +        if (zone != null) {
 +            response.setZoneId(zone.getUuid());
 +            response.setZoneName(zone.getName());
 +        }
 +        response.setAddress(result.getIp4Address());
 +        PhysicalNetwork pnet = ApiDBUtils.findPhysicalNetworkById(result.getPhysicalNetworkId());
 +        if (pnet != null) {
 +            response.setPhysicalNetworkId(pnet.getUuid());
 +        }
 +
 +        populateAccount(response, result.getAccountId());
 +        populateDomain(response, result.getDomainId());
 +        response.setState(result.getState().toString());
 +        response.setSourceNat(result.getSourceNat());
 +
 +        NetworkACL acl =  ApiDBUtils.findByNetworkACLId(result.getNetworkACLId());
 +        if (acl != null) {
 +            response.setAclId(acl.getUuid());
 +        }
 +
 +        response.setObjectName("privategateway");
 +
 +        return response;
 +    }
 +
 +    @Override
 +    public CounterResponse createCounterResponse(Counter counter) {
 +        CounterResponse response = new CounterResponse();
 +        response.setId(counter.getUuid());
 +        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.getUuid());
 +        List<CounterResponse> counterResponseList = new ArrayList<CounterResponse>();
 +        counterResponseList.add(createCounterResponse(ApiDBUtils.getCounter(condition.getCounterid())));
 +        response.setCounterResponse(counterResponseList);
 +        response.setRelationalOperator(condition.getRelationalOperator().toString());
 +        response.setThreshold(condition.getThreshold());
 +        response.setObjectName("condition");
 +        populateOwner(response, condition);
 +        return response;
 +    }
 +
 +    @Override
 +    public AutoScaleVmProfileResponse createAutoScaleVmProfileResponse(AutoScaleVmProfile profile) {
 +        AutoScaleVmProfileResponse response = new AutoScaleVmProfileResponse();
 +        response.setId(profile.getUuid());
 +        if (profile.getZoneId() != null) {
 +            DataCenter zone = ApiDBUtils.findZoneById(profile.getZoneId());
 +            if (zone != null) {
 +                response.setZoneId(zone.getUuid());
 +            }
 +        }
 +        if (profile.getServiceOfferingId() != null) {
 +            ServiceOffering so = ApiDBUtils.findServiceOfferingById(profile.getServiceOfferingId());
 +            if (so != null) {
 +                response.setServiceOfferingId(so.getUuid());
 +            }
 +        }
 +        if (profile.getTemplateId() != null) {
 +            VMTemplateVO template = ApiDBUtils.findTemplateById(profile.getTemplateId());
 +            if (template != null) {
 +                response.setTemplateId(template.getUuid());
 +            }
 +        }
 +        response.setOtherDeployParams(profile.getOtherDeployParams());
 +        response.setCounterParams(profile.getCounterParams());
 +        response.setDestroyVmGraceperiod(profile.getDestroyVmGraceperiod());
 +        User user = ApiDBUtils.findUserById(profile.getAutoScaleUserId());
 +        if (user != null) {
 +            response.setAutoscaleUserId(user.getUuid());
 +        }
 +        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.getUuid());
 +        response.setDuration(policy.getDuration());
 +        response.setQuietTime(policy.getQuietTime());
 +        response.setAction(policy.getAction());
 +        List<ConditionVO> vos = ApiDBUtils.getAutoScalePolicyConditions(policy.getId());
 +        ArrayList<ConditionResponse> conditions = new ArrayList<ConditionResponse>(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.getUuid());
 +        response.setMinMembers(vmGroup.getMinMembers());
 +        response.setMaxMembers(vmGroup.getMaxMembers());
 +        response.setState(vmGroup.getState());
 +        response.setInterval(vmGroup.getInterval());
 +        response.setForDisplay(vmGroup.isDisplay());
 +        AutoScaleVmProfileVO profile = ApiDBUtils.findAutoScaleVmProfileById(vmGroup.getProfileId());
 +        if (profile != null) {
 +            response.setProfileId(profile.getUuid());
 +        }
 +        FirewallRuleVO fw = ApiDBUtils.findFirewallRuleById(vmGroup.getLoadBalancerId());
 +        if (fw != null) {
 +            response.setLoadBalancerId(fw.getUuid());
 +        }
 +
 +        List<AutoScalePolicyResponse> scaleUpPoliciesResponse = new ArrayList<AutoScalePolicyResponse>();
 +        List<AutoScalePolicyResponse> scaleDownPoliciesResponse = new ArrayList<AutoScalePolicyResponse>();
 +        response.setScaleUpPolicies(scaleUpPoliciesResponse);
 +        response.setScaleDownPolicies(scaleDownPoliciesResponse);
 +        response.setObjectName("autoscalevmgroup");
 +
 +        // Fetch policies for vmgroup
 +        List<AutoScalePolicy> scaleUpPolicies = new ArrayList<AutoScalePolicy>();
 +        List<AutoScalePolicy> scaleDownPolicies = new ArrayList<AutoScalePolicy>();
 +        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.getUuid());
 +        if (result.getVpcId() != null) {
 +            Vpc vpc = ApiDBUtils.findVpcById(result.getVpcId());
 +            if (vpc != null) {
 +                response.setVpcId(vpc.getUuid());
 +            }
 +        }
 +        response.setCidr(result.getCidr());
 +
 +        StaticRoute.State state = result.getState();
 +        if (state.equals(StaticRoute.State.Revoke)) {
 +            state = StaticRoute.State.Deleting;
 +        }
 +        response.setState(state.toString());
 +        populateAccount(response, result.getAccountId());
 +        populateDomain(response, result.getDomainId());
 +
 +        // set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.StaticRoute, result.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses,tagResponse);
 +        }
 +        response.setTags(tagResponses);
 +        response.setObjectName("staticroute");
 +
 +        return response;
 +    }
 +
 +    @Override
 +    public Site2SiteVpnGatewayResponse createSite2SiteVpnGatewayResponse(Site2SiteVpnGateway result) {
 +        Site2SiteVpnGatewayResponse response = new Site2SiteVpnGatewayResponse();
 +        response.setId(result.getUuid());
 +        response.setIp(ApiDBUtils.findIpAddressById(result.getAddrId()).getAddress().toString());
 +        Vpc vpc = ApiDBUtils.findVpcById(result.getVpcId());
 +        if (vpc != null) {
 +            response.setVpcId(vpc.getUuid());
 +        }
 +        response.setRemoved(result.getRemoved());
 +        response.setForDisplay(result.isDisplay());
 +        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.getUuid());
 +        response.setName(result.getName());
 +        response.setGatewayIp(result.getGatewayIp());
 +        response.setGuestCidrList(result.getGuestCidrList());
 +        response.setIpsecPsk(result.getIpsecPsk());
 +        response.setIkePolicy(result.getIkePolicy());
 +        response.setEspPolicy(result.getEspPolicy());
 +        response.setIkeLifetime(result.getIkeLifetime());
 +        response.setEspLifetime(result.getEspLifetime());
 +        response.setDpd(result.getDpd());
 +        response.setEncap(result.getEncap());
 +        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.getUuid());
 +        response.setPassive(result.isPassive());
 +
 +        Long vpnGatewayId = result.getVpnGatewayId();
 +        if (vpnGatewayId != null) {
 +            Site2SiteVpnGateway vpnGateway = ApiDBUtils.findVpnGatewayById(vpnGatewayId);
 +            if (vpnGateway != null) {
 +                response.setVpnGatewayId(vpnGateway.getUuid());
 +                long ipId = vpnGateway.getAddrId();
 +                IPAddressVO ipObj = ApiDBUtils.findIpAddressById(ipId);
 +                response.setIp(ipObj.getAddress().addr());
 +            }
 +        }
 +
 +        Long customerGatewayId = result.getCustomerGatewayId();
 +        if (customerGatewayId != null) {
 +            Site2SiteCustomerGateway customerGateway = ApiDBUtils.findCustomerGatewayById(customerGatewayId);
 +            if (customerGateway != null) {
 +                response.setCustomerGatewayId(customerGateway.getUuid());
 +                response.setGatewayIp(customerGateway.getGatewayIp());
 +                response.setGuestCidrList(customerGateway.getGuestCidrList());
 +                response.setIpsecPsk(customerGateway.getIpsecPsk());
 +                response.setIkePolicy(customerGateway.getIkePolicy());
 +                response.setEspPolicy(customerGateway.getEspPolicy());
 +                response.setIkeLifetime(customerGateway.getIkeLifetime());
 +                response.setEspLifetime(customerGateway.getEspLifetime());
 +                response.setDpd(customerGateway.getDpd());
 +                response.setEncap(customerGateway.getEncap());
 +            }
 +        }
 +
 +        populateAccount(response, result.getAccountId());
 +        populateDomain(response, result.getDomainId());
 +
 +        response.setState(result.getState().toString());
 +        response.setCreated(result.getCreated());
 +        response.setRemoved(result.getRemoved());
 +        response.setForDisplay(result.isDisplay());
 +        response.setObjectName("vpnconnection");
 +        return response;
 +    }
 +
 +    @Override
 +    public GuestOSResponse createGuestOSResponse(GuestOS guestOS) {
 +        GuestOSResponse response = new GuestOSResponse();
 +        response.setDescription(guestOS.getDisplayName());
 +        response.setId(guestOS.getUuid());
 +        response.setIsUserDefined(guestOS.getIsUserDefined());
 +        GuestOSCategoryVO category = ApiDBUtils.findGuestOsCategoryById(guestOS.getCategoryId());
 +        if (category != null) {
 +            response.setOsCategoryId(category.getUuid());
 +        }
 +
 +        response.setObjectName("ostype");
 +        return response;
 +    }
 +
 +    @Override
 +    public GuestOsMappingResponse createGuestOSMappingResponse(GuestOSHypervisor guestOSHypervisor) {
 +        GuestOsMappingResponse response = new GuestOsMappingResponse();
 +        response.setId(guestOSHypervisor.getUuid());
 +        response.setHypervisor(guestOSHypervisor.getHypervisorType());
 +        response.setHypervisorVersion(guestOSHypervisor.getHypervisorVersion());
 +        response.setOsNameForHypervisor((guestOSHypervisor.getGuestOsName()));
 +        response.setIsUserDefined(Boolean.valueOf(guestOSHypervisor.getIsUserDefined()).toString());
 +        GuestOS guestOs = ApiDBUtils.findGuestOSById(guestOSHypervisor.getGuestOsId());
 +        if (guestOs != null) {
 +            response.setOsStdName(guestOs.getDisplayName());
 +            response.setOsTypeId(guestOs.getUuid());
 +        }
 +
 +        response.setObjectName("guestosmapping");
 +        return response;
 +    }
 +
 +    @Override
 +    public SnapshotScheduleResponse createSnapshotScheduleResponse(SnapshotSchedule snapshotSchedule) {
 +        SnapshotScheduleResponse response = new SnapshotScheduleResponse();
 +        response.setId(snapshotSchedule.getUuid());
 +        if (snapshotSchedule.getVolumeId() != null) {
 +            Volume vol = ApiDBUtils.findVolumeById(snapshotSchedule.getVolumeId());
 +            if (vol != null) {
 +                response.setVolumeId(vol.getUuid());
 +            }
 +        }
 +        if (snapshotSchedule.getPolicyId() != null) {
 +            SnapshotPolicy policy = ApiDBUtils.findSnapshotPolicyById(snapshotSchedule.getPolicyId());
 +            if (policy != null) {
 +                response.setSnapshotPolicyId(policy.getUuid());
 +            }
 +        }
 +        response.setScheduled(snapshotSchedule.getScheduledTimestamp());
 +
 +        response.setObjectName("snapshot");
 +        return response;
 +    }
 +
 +    @Override
 +    public Map<String, Set<ResourceTagResponse>> getUsageResourceTags()
 +    {
 +        try {
 +            return _resourceTagDao.listTags();
 +        } catch(Exception ex) {
 +            s_logger.warn("Failed to get resource details for Usage data due to exception : ", ex);
 +        }
 +        return null;
 +    }
 +
 +    @Override
 +    public UsageRecordResponse createUsageResponse(Usage usageRecord) {
 +        return createUsageResponse(usageRecord, null);
 +    }
 +
 +    @Override
 +    public UsageRecordResponse createUsageResponse(Usage usageRecord, Map<String, Set<ResourceTagResponse>> resourceTagResponseMap) {
 +        UsageRecordResponse usageRecResponse = new UsageRecordResponse();
 +        Account account = ApiDBUtils.findAccountById(usageRecord.getAccountId());
 +        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
 +            //find the project
 +            Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(account.getId());
 +            if (project != null) {
 +                usageRecResponse.setProjectId(project.getUuid());
 +                usageRecResponse.setProjectName(project.getName());
 +            }
 +        } else {
 +            usageRecResponse.setAccountId(account.getUuid());
 +            usageRecResponse.setAccountName(account.getAccountName());
 +        }
 +
 +        Domain domain = ApiDBUtils.findDomainById(usageRecord.getDomainId());
 +        if (domain != null) {
 +            usageRecResponse.setDomainId(domain.getUuid());
 +            usageRecResponse.setDomainName(domain.getName());
 +        }
 +
 +        if (usageRecord.getZoneId() != null) {
 +            DataCenter zone = ApiDBUtils.findZoneById(usageRecord.getZoneId());
 +            if (zone != null) {
 +                usageRecResponse.setZoneId(zone.getUuid());
 +            }
 +        }
 +        usageRecResponse.setDescription(usageRecord.getDescription());
 +        usageRecResponse.setUsage(usageRecord.getUsageDisplay());
 +        usageRecResponse.setUsageType(usageRecord.getUsageType());
 +        if (usageRecord.getVmInstanceId() != null) {
 +            VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId());
 +            if (vm != null) {
 +                usageRecResponse.setVirtualMachineId(vm.getUuid());
 +            }
 +        }
 +        usageRecResponse.setVmName(usageRecord.getVmName());
 +        if (usageRecord.getTemplateId() != null) {
 +            VMTemplateVO template = ApiDBUtils.findTemplateById(usageRecord.getTemplateId());
 +            if (template != null) {
 +                usageRecResponse.setTemplateId(template.getUuid());
 +            }
 +        }
 +
 +        ResourceTag.ResourceObjectType resourceType = null;
 +        Long resourceId = null;
 +        if (usageRecord.getUsageType() == UsageTypes.RUNNING_VM || usageRecord.getUsageType() == UsageTypes.ALLOCATED_VM) {
 +            ServiceOfferingVO svcOffering = _entityMgr.findByIdIncludingRemoved(ServiceOfferingVO.class, usageRecord.getOfferingId().toString());
 +            //Service Offering Id
 +            if(svcOffering != null) {
 +                usageRecResponse.setOfferingId(svcOffering.getUuid());
 +            }
 +            //VM Instance ID
 +            VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString());
 +            if (vm != null) {
 +                resourceType = ResourceTag.ResourceObjectType.UserVm;
 +                usageRecResponse.setUsageId(vm.getUuid());
 +                resourceId = vm.getId();
 +            }
 +            //Hypervisor Type
 +            usageRecResponse.setType(usageRecord.getType());
 +            //Dynamic compute offerings details
 +            if(usageRecord.getCpuCores() != null) {
 +                usageRecResponse.setCpuNumber(usageRecord.getCpuCores());
 +            } else if (svcOffering.getCpu() != null){
 +                usageRecResponse.setCpuNumber(svcOffering.getCpu().longValue());
 +            }
 +            if(usageRecord.getCpuSpeed() != null) {
 +                usageRecResponse.setCpuSpeed(usageRecord.getCpuSpeed());
 +            } else if(svcOffering.getSpeed() != null){
 +                usageRecResponse.setCpuSpeed(svcOffering.getSpeed().longValue());
 +            }
 +            if(usageRecord.getMemory() != null) {
 +                usageRecResponse.setMemory(usageRecord.getMemory());
 +            } else if(svcOffering.getRamSize() != null) {
 +                usageRecResponse.setMemory(svcOffering.getRamSize().longValue());
 +            }
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.IP_ADDRESS) {
 +            //isSourceNAT
 +            usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat")) ? true : false);
 +            //isSystem
 +            usageRecResponse.setSystem((usageRecord.getSize() == 1) ? true : false);
 +            //IP Address ID
 +            IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString());
 +            if (ip != null) {
 +                resourceType = ResourceObjectType.PublicIpAddress;
 +                resourceId = ip.getId();
 +                usageRecResponse.setUsageId(ip.getUuid());
 +            }
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) {
 +            //Device Type
 +            resourceType = ResourceObjectType.UserVm;
 +            usageRecResponse.setType(usageRecord.getType());
 +            if (usageRecord.getType().equals("DomainRouter") || usageRecord.getType().equals("UserVm")) {
 +                //Domain Router Id
 +                VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getUsageId().toString());
 +                if (vm != null) {
 +                    resourceId = vm.getId();
 +                    usageRecResponse.setUsageId(vm.getUuid());
 +                }
 +            } else {
 +                //External Device Host Id
 +                HostVO host = _entityMgr.findByIdIncludingRemoved(HostVO.class, usageRecord.getUsageId().toString());
 +                if (host != null) {
 +                    usageRecResponse.setUsageId(host.getUuid());
 +                }
 +            }
 +            //Network ID
 +            if((usageRecord.getNetworkId() != null) && (usageRecord.getNetworkId() != 0)) {
 +                NetworkVO network = _entityMgr.findByIdIncludingRemoved(NetworkVO.class, usageRecord.getNetworkId().toString());
 +                if (network != null) {
 +                    resourceType = ResourceObjectType.Network;
 +                    resourceId = network.getId();
 +                    usageRecResponse.setNetworkId(network.getUuid());
 +                }
 +            }
 +        } else if (usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_IO_WRITE
 +                || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_READ || usageRecord.getUsageType() == UsageTypes.VM_DISK_BYTES_WRITE) {
 +            //Device Type
 +            usageRecResponse.setType(usageRecord.getType());
 +            resourceType = ResourceObjectType.Volume;
 +            //VM Instance Id
 +            VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId().toString());
 +            if (vm != null) {
 +                usageRecResponse.setVirtualMachineId(vm.getUuid());
 +            }
 +            //Volume ID
 +            VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString());
 +            if (volume != null) {
 +                usageRecResponse.setUsageId(volume.getUuid());
 +                resourceId = volume.getId();
 +            }
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.VOLUME) {
 +            //Volume ID
 +            VolumeVO volume = _entityMgr.findByIdIncludingRemoved(VolumeVO.class, usageRecord.getUsageId().toString());
 +            resourceType = ResourceObjectType.Volume;
 +            if (volume != null) {
 +                usageRecResponse.setUsageId(volume.getUuid());
 +                resourceId = volume.getId();
 +            }
 +            //Volume Size
 +            usageRecResponse.setSize(usageRecord.getSize());
 +            //Disk Offering Id
 +            if (usageRecord.getOfferingId() != null) {
 +                DiskOfferingVO diskOff = _entityMgr.findByIdIncludingRemoved(DiskOfferingVO.class, usageRecord.getOfferingId().toString());
 +                usageRecResponse.setOfferingId(diskOff.getUuid());
 +            }
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.TEMPLATE || usageRecord.getUsageType() == UsageTypes.ISO) {
 +            //Template/ISO ID
 +            VMTemplateVO tmpl = _entityMgr.findByIdIncludingRemoved(VMTemplateVO.class, usageRecord.getUsageId().toString());
 +            if (tmpl != null) {
 +                usageRecResponse.setUsageId(tmpl.getUuid());
 +                resourceId = tmpl.getId();
 +            }
 +            //Template/ISO Size
 +            usageRecResponse.setSize(usageRecord.getSize());
 +            if (usageRecord.getUsageType() == UsageTypes.ISO) {
 +                usageRecResponse.setVirtualSize(usageRecord.getSize());
 +                resourceType = ResourceObjectType.ISO;
 +            } else {
 +                usageRecResponse.setVirtualSize(usageRecord.getVirtualSize());
 +                resourceType = ResourceObjectType.Template;
 +            }
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.SNAPSHOT) {
 +            //Snapshot ID
 +            SnapshotVO snap = _entityMgr.findByIdIncludingRemoved(SnapshotVO.class, usageRecord.getUsageId().toString());
 +            resourceType = ResourceObjectType.Snapshot;
 +            if (snap != null) {
 +                usageRecResponse.setUsageId(snap.getUuid());
 +                resourceId = snap.getId();
 +            }
 +            //Snapshot Size
 +            usageRecResponse.setSize(usageRecord.getSize());
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY) {
 +            //Load Balancer Policy ID
 +            LoadBalancerVO lb = _entityMgr.findByIdIncludingRemoved(LoadBalancerVO.class, usageRecord.getUsageId().toString());
 +            resourceType = ResourceObjectType.LoadBalancer;
 +            if (lb != null) {
 +                usageRecResponse.setUsageId(lb.getUuid());
 +                resourceId = lb.getId();
 +            }
 +        } else if (usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE) {
 +            //Port Forwarding Rule ID
 +            PortForwardingRuleVO pf = _entityMgr.findByIdIncludingRemoved(PortForwardingRuleVO.class, usageRecord.getUsageId().toString());
 +            resourceType = ResourceObjectType.PortForwardingRule;
 +            if (pf != null) {
 +                usageRecResponse.setUsageId(pf.getUuid());
 +                resourceId = pf.getId();
 +            }
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING) {
 +            //Network Offering Id
 +            NetworkOfferingVO netOff = _entityMgr.findByIdIncludingRemoved(NetworkOfferingVO.class, usageRecord.getOfferingId().toString());
 +            usageRecResponse.setOfferingId(netOff.getUuid());
 +            //is Default
 +            usageRecResponse.setDefault((usageRecord.getUsageId() == 1) ? true : false);
 +
 +        } else if (usageRecord.getUsageType() == UsageTypes.VPN_USERS) {
 +            //VPN User ID
 +            VpnUserVO vpnUser = _entityMgr.findByIdIncludingRemoved(VpnUserVO.class, usageRecord.getUsageId().toString());
 +            if (vpnUser != null) {
 +                usageRecResponse.setUsageId(vpnUser.getUuid());
 +            }
 +        } else if (usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP) {
 +            //Security Group Id
 +            SecurityGroupVO sg = _entityMgr.findByIdIncludingRemoved(SecurityGroupVO.class, usageRecord.getUsageId().toString());
 +            resourceType = ResourceObjectType.SecurityGroup;
 +            if (sg != null) {
 +                resourceId = sg.getId();
 +                usageRecResponse.setUsageId(sg.getUuid());
 +            }
 +        } else if (usageRecord.getUsageType() == UsageTypes.VM_SNAPSHOT) {
 +            VMInstanceVO vm = _entityMgr.findByIdIncludingRemoved(VMInstanceVO.class, usageRecord.getVmInstanceId().toString());
 +            resourceType = ResourceObjectType.UserVm;
 +            if (vm != null) {
 +                resourceId = vm.getId();
 +                usageRecResponse.setVmName(vm.getInstanceName());
 +                usageRecResponse.setUsageId(vm.getUuid());
 +            }
 +            usageRecResponse.setSize(usageRecord.getSize());
 +            if (usageRecord.getOfferingId() != null) {
 +                usageRecResponse.setOfferingId(usageRecord.getOfferingId().toString());
 +            }
 +        }
 +
 +        if(resourceTagResponseMap != null && resourceTagResponseMap.get(resourceId + ":" + resourceType) != null) {
 +             usageRecResponse.setTags(resourceTagResponseMap.get(resourceId + ":" + resourceType));
 +        }
 +
 +        if (usageRecord.getRawUsage() != null) {
 +            DecimalFormat decimalFormat = new DecimalFormat("###########.######");
 +            usageRecResponse.setRawUsage(decimalFormat.format(usageRecord.getRawUsage()));
 +        }
 +
 +        if (usageRecord.getStartDate() != null) {
 +            usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate()));
 +        }
 +        if (usageRecord.getEndDate() != null) {
 +            usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate()));
 +        }
 +
 +        return usageRecResponse;
 +    }
 +
 +    public String getDateStringInternal(Date inputDate) {
 +        if (inputDate == null) {
 +            return null;
 +        }
 +
 +        TimeZone tz = _usageSvc.getUsageTimezone();
 +        Calendar cal = Calendar.getInstance(tz);
 +        cal.setTime(inputDate);
 +
 +        StringBuilder sb = new StringBuilder(32);
 +        sb.append(cal.get(Calendar.YEAR)).append('-');
 +
 +        int month = cal.get(Calendar.MONTH) + 1;
 +        if (month < 10) {
 +            sb.append('0');
 +        }
 +        sb.append(month).append('-');
 +
 +        int day = cal.get(Calendar.DAY_OF_MONTH);
 +        if (day < 10) {
 +            sb.append('0');
 +        }
 +        sb.append(day);
 +
 +        sb.append("'T'");
 +
 +        int hour = cal.get(Calendar.HOUR_OF_DAY);
 +        if (hour < 10) {
 +            sb.append('0');
 +        }
 +        sb.append(hour).append(':');
 +
 +        int minute = cal.get(Calendar.MINUTE);
 +        if (minute < 10) {
 +            sb.append('0');
 +        }
 +        sb.append(minute).append(':');
 +
 +        int seconds = cal.get(Calendar.SECOND);
 +        if (seconds < 10) {
 +            sb.append('0');
 +        }
 +        sb.append(seconds);
 +
 +        double offset = cal.get(Calendar.ZONE_OFFSET);
 +        if (tz.inDaylightTime(inputDate)) {
 +            offset += (1.0 * tz.getDSTSavings()); // add the timezone's DST
 +            // value (typically 1 hour
 +            // expressed in milliseconds)
 +        }
 +
 +        offset = offset / (1000d * 60d * 60d);
 +        int hourOffset = (int)offset;
 +        double decimalVal = Math.abs(offset) - Math.abs(hourOffset);
 +        int minuteOffset = (int)(decimalVal * 60);
 +
 +        if (hourOffset < 0) {
 +            if (hourOffset > -10) {
 +                sb.append("-0");
 +            } else {
 +                sb.append('-');
 +            }
 +            sb.append(Math.abs(hourOffset));
 +        } else {
 +            if (hourOffset < 10) {
 +                sb.append("+0");
 +            } else {
 +                sb.append("+");
 +            }
 +            sb.append(hourOffset);
 +        }
 +
 +        sb.append(':');
 +
 +        if (minuteOffset == 0) {
 +            sb.append("00");
 +        } else if (minuteOffset < 10) {
 +            sb.append('0').append(minuteOffset);
 +        } else {
 +            sb.append(minuteOffset);
 +        }
 +
 +        return sb.toString();
 +    }
 +
 +    @Override
 +    public TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor) {
 +        Map<String, String> tmDetails = ApiDBUtils.findHostDetailsById(trafficMonitor.getId());
 +        TrafficMonitorResponse response = new TrafficMonitorResponse();
 +        response.setId(trafficMonitor.getUuid());
 +        response.setIpAddress(trafficMonitor.getPrivateIpAddress());
 +        response.setNumRetries(tmDetails.get("numRetries"));
 +        response.setTimeout(tmDetails.get("timeout"));
 +        return response;
 +    }
 +
 +    @Override
 +    public NicSecondaryIpResponse createSecondaryIPToNicResponse(NicSecondaryIp result) {
 +        NicSecondaryIpResponse response = new NicSecondaryIpResponse();
 +        NicVO nic = _entityMgr.findById(NicVO.class, result.getNicId());
 +        NetworkVO network = _entityMgr.findById(NetworkVO.class, result.getNetworkId());
 +        response.setId(result.getUuid());
 +        response.setIpAddr(result.getIp4Address());
 +        response.setNicId(nic.getUuid());
 +        response.setNwId(network.getUuid());
 +        response.setObjectName("nicsecondaryip");
 +        return response;
 +    }
 +
 +    /**
 +     * The resulting Response attempts to be in line with what is returned from
 +     * @see com.cloud.api.query.dao.UserVmJoinDaoImpl#setUserVmResponse(ResponseView, UserVmResponse, UserVmJoinVO)
 +     */
 +    @Override
 +    public NicResponse createNicResponse(Nic result) {
 +        NicResponse response = new NicResponse();
 +        NetworkVO network = _entityMgr.findById(NetworkVO.class, result.getNetworkId());
 +        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, result.getInstanceId());
 +        UserVmJoinVO userVm = _entityMgr.findById(UserVmJoinVO.class, result.getInstanceId());
 +        List<NicExtraDhcpOptionVO> nicExtraDhcpOptionVOs = _nicExtraDhcpOptionDao.listByNicId(result.getId());
 +
 +        // The numbered comments are to keep track of the data returned from here and UserVmJoinDaoImpl.setUserVmResponse()
 +        // the data can't be identical but some tidying up/unifying might be possible
 +        /*1: nicUuid*/
 +        response.setId(result.getUuid());
 +        /*2: networkUuid*/
 +        response.setNetworkid(network.getUuid());
 +        /*3: vmId*/
 +        if (vm != null) {
 +            response.setVmId(vm.getUuid());
 +        }
 +
 +        if (userVm != null){
 +            if (userVm.getTrafficType() != null) {
 +                /*4: trafficType*/
 +                response.setTrafficType(userVm.getTrafficType().toString());
 +            }
 +            if (userVm.getGuestType() != null) {
 +                /*5: guestType*/
 +                response.setType(userVm.getGuestType().toString());
 +            }
 +        }
 +        /*6: ipAddress*/
 +        response.setIpaddress(result.getIPv4Address());
 +        /*7: gateway*/
 +        response.setGateway(result.getIPv4Gateway());
 +        /*8: netmask*/
 +        response.setNetmask(result.getIPv4Netmask());
 +        /*9: networkName*/
 +        if(userVm != null && userVm.getNetworkName() != null) {
 +            response.setNetworkName(userVm.getNetworkName());
 +        }
 +        /*10: macAddress*/
 +        response.setMacAddress(result.getMacAddress());
 +        /*11: IPv6Address*/
 +        if (result.getIPv6Address() != null) {
 +            response.setIp6Address(result.getIPv6Address());
 +        }
 +        /*12: IPv6Gateway*/
 +        if (result.getIPv6Gateway() != null) {
 +            response.setIp6Gateway(result.getIPv6Gateway());
 +        }
 +        /*13: IPv6Cidr*/
 +        if (result.getIPv6Cidr() != null) {
 +            response.setIp6Cidr(result.getIPv6Cidr());
 +        }
 +        /*14: deviceId*/
 +        response.setDeviceId(String.valueOf(result.getDeviceId()));
 +        /*15: broadcastURI*/
 +        if (result.getBroadcastUri() != null) {
 +            response.setBroadcastUri(result.getBroadcastUri().toString());
 +        }
 +        /*16: isolationURI*/
 +        if (result.getIsolationUri() != null) {
 +            response.setIsolationUri(result.getIsolationUri().toString());
 +        }
 +        /*17: default*/
 +        response.setIsDefault(result.isDefaultNic());
 +        if (result.getSecondaryIp()) {
 +            List<NicSecondaryIpVO> secondaryIps = ApiDBUtils.findNicSecondaryIps(result.getId());
 +            if (secondaryIps != null) {
 +                List<NicSecondaryIpResponse> ipList = new ArrayList<NicSecondaryIpResponse>();
 +                for (NicSecondaryIpVO ip : secondaryIps) {
 +                    NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse();
 +                    ipRes.setId(ip.getUuid());
 +                    ipRes.setIpAddr(ip.getIp4Address());
 +                    ipList.add(ipRes);
 +                }
 +                response.setSecondaryIps(ipList);
 +            }
 +        }
 +        /*18: extra dhcp options */
 +        List<NicExtraDhcpOptionResponse> nicExtraDhcpOptionResponses = nicExtraDhcpOptionVOs
 +                .stream()
 +                .map(vo -> new NicExtraDhcpOptionResponse(Dhcp.DhcpOptionCode.valueOfInt(vo.getCode()).getName(), vo.getCode(), vo.getValue()))
 +                .collect(Collectors.toList());
 +
 +        response.setExtraDhcpOptions(nicExtraDhcpOptionResponses);
 +
 +        if (result instanceof NicVO){
 +            if (((NicVO)result).getNsxLogicalSwitchUuid() != null){
 +                response.setNsxLogicalSwitch(((NicVO)result).getNsxLogicalSwitchUuid());
 +            }
 +            if (((NicVO)result).getNsxLogicalSwitchPortUuid() != null){
 +                response.setNsxLogicalSwitchPort(((NicVO)result).getNsxLogicalSwitchPortUuid());
 +            }
 +        }
 +        return response;
 +    }
 +
 +    @Override
 +    public ApplicationLoadBalancerResponse createLoadBalancerContainerReponse(ApplicationLoadBalancerRule lb, Map<Ip, UserVm> lbInstances) {
 +
 +        ApplicationLoadBalancerResponse lbResponse = new ApplicationLoadBalancerResponse();
 +        lbResponse.setId(lb.getUuid());
 +        lbResponse.setName(lb.getName());
 +        lbResponse.setDescription(lb.getDescription());
 +        lbResponse.setAlgorithm(lb.getAlgorithm());
 +        lbResponse.setForDisplay(lb.isDisplay());
 +        Network nw = ApiDBUtils.findNetworkById(lb.getNetworkId());
 +        lbResponse.setNetworkId(nw.getUuid());
 +        populateOwner(lbResponse, lb);
 +
 +        if (lb.getScheme() == Scheme.Internal) {
 +            lbResponse.setSourceIp(lb.getSourceIp().addr());
 +            //TODO - create the view for the load balancer rule to reflect the network uuid
 +            Network network = ApiDBUtils.findNetworkById(lb.getNetworkId());
 +            lbResponse.setSourceIpNetworkId(network.getUuid());
 +        } else {
 +            //for public, populate the ip information from the ip address
 +            IpAddress publicIp = ApiDBUtils.findIpAddressById(lb.getSourceIpAddressId());
 +            lbResponse.setSourceIp(publicIp.getAddress().addr());
 +            Network ntwk = ApiDBUtils.findNetworkById(publicIp.getNetworkId());
 +            lbResponse.setSourceIpNetworkId(ntwk.getUuid());
 +        }
 +
 +        //set load balancer rules information (only one rule per load balancer in this release)
 +        List<ApplicationLoadBalancerRuleResponse> ruleResponses = new ArrayList<ApplicationLoadBalancerRuleResponse>();
 +        ApplicationLoadBalancerRuleResponse ruleResponse = new ApplicationLoadBalancerRuleResponse();
 +        ruleResponse.setInstancePort(lb.getDefaultPortStart());
 +        ruleResponse.setSourcePort(lb.getSourcePortStart());
 +        FirewallRule.State stateToSet = lb.getState();
 +        if (stateToSet.equals(FirewallRule.State.Revoke)) {
 +            stateToSet = FirewallRule.State.Deleting;
 +        }
 +        ruleResponse.setState(stateToSet.toString());
 +        ruleResponse.setObjectName("loadbalancerrule");
 +        ruleResponses.add(ruleResponse);
 +        lbResponse.setLbRules(ruleResponses);
 +
 +        //set Lb instances information
 +        List<ApplicationLoadBalancerInstanceResponse> instanceResponses = new ArrayList<ApplicationLoadBalancerInstanceResponse>();
 +        for (Map.Entry<Ip,UserVm> entry : lbInstances.entrySet()) {
 +            Ip ip = entry.getKey();
 +            UserVm vm = entry.getValue();
 +            ApplicationLoadBalancerInstanceResponse instanceResponse = new ApplicationLoadBalancerInstanceResponse();
 +            instanceResponse.setIpAddress(ip.addr());
 +            instanceResponse.setId(vm.getUuid());
 +            instanceResponse.setName(vm.getInstanceName());
 +            instanceResponse.setObjectName("loadbalancerinstance");
 +            instanceResponses.add(instanceResponse);
 +        }
 +
 +        lbResponse.setLbInstances(instanceResponses);
 +
 +        //set tag information
 +        List<? extends ResourceTag> tags = ApiDBUtils.listByResourceTypeAndId(ResourceObjectType.LoadBalancer, lb.getId());
 +        List<ResourceTagResponse> tagResponses = new ArrayList<ResourceTagResponse>();
 +        for (ResourceTag tag : tags) {
 +            ResourceTagResponse tagResponse = createResourceTagResponse(tag, true);
 +            CollectionUtils.addIgnoreNull(tagResponses,tagResponse);
 +        }
 +        lbResponse.setTags(tagResponses);
 +
 +        lbResponse.setObjectName("loadbalancer");
 +        return lbResponse;
 +    }
 +
 +    @Override
 +    public AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group) {
 +
 +        AffinityGroupResponse response = new AffinityGroupResponse();
 +
 +        Account account = ApiDBUtils.findAccountById(group.getAccountId());
 +        response.setId(group.getUuid());
 +        response.setAccountName(account.getAccountName());
 +        response.setName(group.getName());
 +        response.setType(group.getType());
 +        response.setDescription(group.getDescription());
 +        Domain domain = ApiDBUtils.findDomainById(account.getDomainId());
 +        if (domain != null) {
 +            response.setDomainId(domain.getUuid());
 +            response.setDomainName(domain.getName());
 +        }
 +
 +        response.setObjectName("affinitygroup");
 +        return response;
 +    }
 +
 +    @Override
 +    public Long getAffinityGroupId(String groupName, long accountId) {
 +        AffinityGroup ag = ApiDBUtils.getAffinityGroup(groupName, accountId);
 +        if (ag == null) {
 +            return null;
 +        } else {
 +            return ag.getId();
 +        }
 +    }
 +
 +
 +    @Override
 +    public PortableIpRangeResponse createPortableIPRangeResponse(PortableIpRange ipRange) {
 +        PortableIpRangeResponse response = new PortableIpRangeResponse();
 +        response.setId(ipRange.getUuid());
 +        String ipRangeStr = ipRange.getIpRange();
 +        if (ipRangeStr != null) {
 +            String[] range = ipRangeStr.split("-");
 +            response.setStartIp(range[0]);
 +            response.setEndIp(range[1]);
 +        }
 +        response.setVlan(ipRange.getVlanTag());
 +        response.setGateway(ipRange.getGateway());
 +        response.setNetmask(ipRange.getNetmask());
 +        response.setRegionId(ipRange.getRegionId());
 +        response.setObjectName("portableiprange");
 +        return response;
 +    }
 +
 +    @Override
 +    public PortableIpResponse createPortableIPResponse(PortableIp portableIp) {
 +        PortableIpResponse response = new PortableIpResponse();
 +        response.setAddress(portableIp.getAddress());
 +        Long accountId =  portableIp.getAllocatedInDomainId();
 +        if (accountId != null) {
 +            Account account = ApiDBUtils.findAccountById(accountId);
 +            response.setAllocatedToAccountId(account.getAccountName());
 +            Domain domain = ApiDBUtils.findDomainById(account.getDomainId());
 +            response.setAllocatedInDomainId(domain.getUuid());
 +        }
 +
 +        response.setAllocatedTime(portableIp.getAllocatedTime());
 +
 +        if (portableIp.getAssociatedDataCenterId() != null) {
 +            DataCenter zone = ApiDBUtils.findZoneById(portableIp.getAssociatedDataCenterId());
 +            if (zone != null) {
 +                response.setAssociatedDataCenterId(zone.getUuid());
 +            }
 +        }
 +
 +        if (portableIp.getPhysicalNetworkId() != null) {
 +            PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(portableIp.getPhysicalNetworkId());
 +            if (pnw != null) {
 +                response.setPhysicalNetworkId(pnw.getUuid());
 +            }
 +        }
 +
 +        if (portableIp.getAssociatedWithNetworkId() != null) {
 +            Network ntwk = ApiDBUtils.findNetworkById(portableIp.getAssociatedWithNetworkId());
 +            if (ntwk != null) {
 +                response.setAssociatedWithNetworkId(ntwk.getUuid());
 +            }
 +        }
 +
 +        if (portableIp.getAssociatedWithVpcId() != null) {
 +            Vpc vpc = ApiDBUtils.findVpcById(portableIp.getAssociatedWithVpcId());
 +            if (vpc != null) {
 +                response.setAssociatedWithVpcId(vpc.getUuid());
 +            }
 +        }
 +
 +        response.setState(portableIp.getState().name());
 +        response.setObjectName("portableip");
 +        return response;
 +    }
 +
 +    @Override
 +    public InternalLoadBalancerElementResponse createInternalLbElementResponse(VirtualRouterProvider result) {
 +        if (result.getType() != VirtualRouterProvider.Type.InternalLbVm) {
 +            return null;
 +        }
 +        InternalLoadBalancerElementResponse response = new InternalLoadBalancerElementResponse();
 +        response.setId(result.getUuid());
 +        PhysicalNetworkServiceProvider nsp = ApiDBUtils.findPhysicalNetworkServiceProviderById(result.getNspId());
 +        if (nsp != null) {
 +            response.setNspId(nsp.getUuid());
 +        }
 +        response.setEnabled(result.isEnabled());
 +
 +        response.setObjectName("internalloadbalancerelement");
 +        return response;
 +    }
 +
 +    @Override
 +    public IsolationMethodResponse createIsolationMethodResponse(IsolationType method) {
 +        IsolationMethodResponse response = new IsolationMethodResponse();
 +        response.setIsolationMethodName(method.toString());
 +        response.setObjectName("isolationmethod");
 +        return response;
 +    }
 +
 +    @Override
 +    public NetworkACLResponse createNetworkACLResponse(NetworkACL networkACL) {
 +        NetworkACLResponse response = new NetworkACLResponse();
 +        response.setId(networkACL.getUuid());
 +        response.setName(networkACL.getName());
 +        response.setDescription(networkACL.getDescription());
 +        response.setForDisplay(networkACL.isDisplay());
 +        Vpc vpc = ApiDBUtils.findVpcById(networkACL.getVpcId());
 +        if (vpc != null) {
 +            response.setVpcId(vpc.getUuid());
 +        }
 +        response.setObjectName("networkacllist");
 +        return response;
 +    }
 +
 +    @Override
 +    public ListResponse<UpgradeRouterTemplateResponse> createUpgradeRouterTemplateResponse(List<Long> jobIds) {
 +        ListResponse<UpgradeRouterTemplateResponse> response = new ListResponse<UpgradeRouterTemplateResponse>();
 +        List<UpgradeRouterTemplateResponse> responses = new ArrayList<UpgradeRouterTemplateResponse>();
 +        for (Long jobId : jobIds) {
 +            UpgradeRouterTemplateResponse routerResponse = new UpgradeRouterTemplateResponse();
 +            AsyncJob job = _entityMgr.findById(AsyncJob.class, jobId);
 +            routerResponse.setAsyncJobId((job.getUuid()));
 +            routerResponse.setObjectName("asyncjobs");
 +            responses.add(routerResponse);
 +        }
 +        response.setResponses(responses);
 +        return response;
 +    }
 +
 +    @Override
 +    public SSHKeyPairResponse createSSHKeyPairResponse(SSHKeyPair sshkeyPair, boolean privatekey) {
 +        SSHKeyPairResponse response = new SSHKeyPairResponse(sshkeyPair.getName(), sshkeyPair.getFingerprint());
 +        if (privatekey) {
 +            response = new CreateSSHKeyPairResponse(sshkeyPair.getName(), sshkeyPair.getFingerprint(), sshkeyPair.getPrivateKey());
 +        }
 +        Account account = ApiDBUtils.findAccountById(sshkeyPair.getAccountId());
 +        response.setAccountName(account.getAccountName());
 +        Domain domain = ApiDBUtils.findDomainById(sshkeyPair.getDomainId());
 +        response.setDomainId(domain.getUuid());
 +        response.setDomainName(domain.getName());
 +        return response;
 +    }
 +}
diff --cc server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
index 729ef2b,0000000..c67611a
mode 100644,000000..100644
--- a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
+++ b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
@@@ -1,300 -1,0 +1,302 @@@
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with 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.
 +package com.cloud.api.query.dao;
 +
 +import java.util.ArrayList;
 +import java.util.List;
 +
 +import javax.inject.Inject;
 +
 +import org.apache.log4j.Logger;
 +import org.springframework.stereotype.Component;
 +
 +import org.apache.cloudstack.api.response.DomainRouterResponse;
 +import org.apache.cloudstack.api.response.NicResponse;
 +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
 +import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 +import org.apache.cloudstack.utils.CloudStackVersion;
 +
 +import com.cloud.api.ApiResponseHelper;
 +import com.cloud.api.query.vo.DomainRouterJoinVO;
 +import com.cloud.network.Networks.TrafficType;
 +import com.cloud.network.router.VirtualRouter;
 +import com.cloud.network.router.VirtualRouter.Role;
 +import com.cloud.user.Account;
 +import com.cloud.user.AccountManager;
 +import com.cloud.utils.db.GenericDaoBase;
 +import com.cloud.utils.db.SearchBuilder;
 +import com.cloud.utils.db.SearchCriteria;
 +
 +@Component
 +public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO, Long> implements DomainRouterJoinDao {
 +    public static final Logger s_logger = Logger.getLogger(DomainRouterJoinDaoImpl.class);
 +
 +    @Inject
 +    private ConfigurationDao  _configDao;
 +    @Inject
 +    public AccountManager _accountMgr;
 +
 +    private final SearchBuilder<DomainRouterJoinVO> vrSearch;
 +
 +    private final SearchBuilder<DomainRouterJoinVO> vrIdSearch;
 +
 +    protected DomainRouterJoinDaoImpl() {
 +
 +        vrSearch = createSearchBuilder();
 +        vrSearch.and("idIN", vrSearch.entity().getId(), SearchCriteria.Op.IN);
 +        vrSearch.done();
 +
 +        vrIdSearch = createSearchBuilder();
 +        vrIdSearch.and("id", vrIdSearch.entity().getId(), SearchCriteria.Op.EQ);
 +        vrIdSearch.done();
 +
 +        _count = "select count(distinct id) from domain_router_view WHERE ";
 +    }
 +
 +    @Override
 +    public DomainRouterResponse newDomainRouterResponse(DomainRouterJoinVO router, Account caller) {
 +        DomainRouterResponse routerResponse = new DomainRouterResponse();
 +        routerResponse.setId(router.getUuid());
 +        routerResponse.setZoneId(router.getDataCenterUuid());
 +        routerResponse.setName(router.getName());
 +        routerResponse.setTemplateId(router.getTemplateUuid());
 +        routerResponse.setCreated(router.getCreated());
 +        routerResponse.setState(router.getState());
 +        routerResponse.setIsRedundantRouter(router.isRedundantRouter());
-         routerResponse.setRedundantState(router.getRedundantState().toString());
++        if (router.getRedundantState() != null) {
++            routerResponse.setRedundantState(router.getRedundantState().toString());
++        }
 +        if (router.getTemplateVersion() != null) {
 +            String routerVersion = CloudStackVersion.trimRouterVersion(router.getTemplateVersion());
 +            routerResponse.setVersion(routerVersion);
 +            routerResponse.setRequiresUpgrade((CloudStackVersion.compare(routerVersion, NetworkOrchestrationService.MinVRVersion.valueIn(router.getDataCenterId())) < 0));
 +        } else {
 +            routerResponse.setVersion("UNKNOWN");
 +            routerResponse.setRequiresUpgrade(true);
 +        }
 +
 +        if (caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN
 +                || _accountMgr.isRootAdmin(caller.getId())) {
 +            if (router.getHostId() != null) {
 +                routerResponse.setHostId(router.getHostUuid());
 +                routerResponse.setHostName(router.getHostName());
 +                routerResponse.setHypervisor(router.getHypervisorType().toString());
 +            }
 +            routerResponse.setPodId(router.getPodUuid());
 +            long nic_id = router.getNicId();
 +            if (nic_id > 0) {
 +                TrafficType ty = router.getTrafficType();
 +                if (ty != null) {
 +                    // legacy code, public/control/guest nic info is kept in
 +                    // nics response object
 +                    if (ty == TrafficType.Public) {
 +                        routerResponse.setPublicIp(router.getIpAddress());
 +                        routerResponse.setPublicMacAddress(router.getMacAddress());
 +                        routerResponse.setPublicNetmask(router.getNetmask());
 +                        routerResponse.setGateway(router.getGateway());
 +                        routerResponse.setPublicNetworkId(router.getNetworkUuid());
 +                    } else if (ty == TrafficType.Control) {
 +                        routerResponse.setLinkLocalIp(router.getIpAddress());
 +                        routerResponse.setLinkLocalMacAddress(router.getMacAddress());
 +                        routerResponse.setLinkLocalNetmask(router.getNetmask());
 +                        routerResponse.setLinkLocalNetworkId(router.getNetworkUuid());
 +                    } else if (ty == TrafficType.Guest) {
 +                        routerResponse.setGuestIpAddress(router.getIpAddress());
 +                        routerResponse.setGuestMacAddress(router.getMacAddress());
 +                        routerResponse.setGuestNetmask(router.getNetmask());
 +                        routerResponse.setGuestNetworkId(router.getNetworkUuid());
 +                        routerResponse.setGuestNetworkName(router.getNetworkName());
 +                        routerResponse.setNetworkDomain(router.getNetworkDomain());
 +                    }
 +                }
 +
 +                NicResponse nicResponse = new NicResponse();
 +                nicResponse.setId(router.getNicUuid());
 +                nicResponse.setIpaddress(router.getIpAddress());
 +                nicResponse.setGateway(router.getGateway());
 +                nicResponse.setNetmask(router.getNetmask());
 +                nicResponse.setNetworkid(router.getNetworkUuid());
 +                nicResponse.setNetworkName(router.getNetworkName());
 +                nicResponse.setMacAddress(router.getMacAddress());
 +                nicResponse.setIp6Address(router.getIp6Address());
 +                nicResponse.setIp6Gateway(router.getIp6Gateway());
 +                nicResponse.setIp6Cidr(router.getIp6Cidr());
 +                if (router.getBroadcastUri() != null) {
 +                    nicResponse.setBroadcastUri(router.getBroadcastUri().toString());
 +                }
 +                if (router.getIsolationUri() != null) {
 +                    nicResponse.setIsolationUri(router.getIsolationUri().toString());
 +                }
 +                if (router.getTrafficType() != null) {
 +                    nicResponse.setTrafficType(router.getTrafficType().toString());
 +                }
 +                if (router.getGuestType() != null) {
 +                    nicResponse.setType(router.getGuestType().toString());
 +                }
 +                nicResponse.setIsDefault(router.isDefaultNic());
 +                nicResponse.setObjectName("nic");
 +                routerResponse.addNic(nicResponse);
 +            }
 +        }
 +
 +        routerResponse.setServiceOfferingId(router.getServiceOfferingUuid());
 +        routerResponse.setServiceOfferingName(router.getServiceOfferingName());
 +
 +        // populate owner.
 +        ApiResponseHelper.populateOwner(routerResponse, router);
 +
 +        routerResponse.setDomainId(router.getDomainUuid());
 +        routerResponse.setDomainName(router.getDomainName());
 +
 +        routerResponse.setZoneName(router.getDataCenterName());
 +        routerResponse.setDns1(router.getDns1());
 +        routerResponse.setDns2(router.getDns2());
 +
 +        routerResponse.setIp6Dns1(router.getIp6Dns1());
 +        routerResponse.setIp6Dns2(router.getIp6Dns2());
 +
 +        routerResponse.setVpcId(router.getVpcUuid());
 +        routerResponse.setVpcName(router.getVpcName());
 +
 +        routerResponse.setRole(router.getRole().toString());
 +
 +        // set async job
 +        if (router.getJobId() != null) {
 +            routerResponse.setJobId(router.getJobUuid());
 +            routerResponse.setJobStatus(router.getJobStatus());
 +        }
 +
 +        if (router.getRole() == Role.INTERNAL_LB_VM) {
 +            routerResponse.setObjectName("internalloadbalancervm");
 +        } else {
 +            routerResponse.setObjectName("router");
 +        }
 +
 +        return routerResponse;
 +    }
 +
 +    @Override
 +    public DomainRouterResponse setDomainRouterResponse(DomainRouterResponse vrData, DomainRouterJoinVO vr) {
 +        long nic_id = vr.getNicId();
 +        if (nic_id > 0) {
 +            TrafficType ty = vr.getTrafficType();
 +            if (ty != null) {
 +                // legacy code, public/control/guest nic info is kept in
 +                // nics response object
 +                if (ty == TrafficType.Public) {
 +                    vrData.setPublicIp(vr.getIpAddress());
 +                    vrData.setPublicMacAddress(vr.getMacAddress());
 +                    vrData.setPublicNetmask(vr.getNetmask());
 +                    vrData.setGateway(vr.getGateway());
 +                    vrData.setPublicNetworkId(vr.getNetworkUuid());
 +                } else if (ty == TrafficType.Control) {
 +                    vrData.setLinkLocalIp(vr.getIpAddress());
 +                    vrData.setLinkLocalMacAddress(vr.getMacAddress());
 +                    vrData.setLinkLocalNetmask(vr.getNetmask());
 +                    vrData.setLinkLocalNetworkId(vr.getNetworkUuid());
 +                } else if (ty == TrafficType.Guest) {
 +                    vrData.setGuestIpAddress(vr.getIpAddress());
 +                    vrData.setGuestMacAddress(vr.getMacAddress());
 +                    vrData.setGuestNetmask(vr.getNetmask());
 +                    vrData.setGuestNetworkId(vr.getNetworkUuid());
 +                    vrData.setGuestNetworkName(vr.getNetworkName());
 +                    vrData.setNetworkDomain(vr.getNetworkDomain());
 +                }
 +            }
 +            NicResponse nicResponse = new NicResponse();
 +            nicResponse.setId(vr.getNicUuid());
 +            nicResponse.setIpaddress(vr.getIpAddress());
 +            nicResponse.setGateway(vr.getGateway());
 +            nicResponse.setNetmask(vr.getNetmask());
 +            nicResponse.setNetworkid(vr.getNetworkUuid());
 +            nicResponse.setNetworkName(vr.getNetworkName());
 +            nicResponse.setMacAddress(vr.getMacAddress());
 +            nicResponse.setIp6Address(vr.getIp6Address());
 +            nicResponse.setIp6Gateway(vr.getIp6Gateway());
 +            nicResponse.setIp6Cidr(vr.getIp6Cidr());
 +            if (vr.getBroadcastUri() != null) {
 +                nicResponse.setBroadcastUri(vr.getBroadcastUri().toString());
 +            }
 +            if (vr.getIsolationUri() != null) {
 +                nicResponse.setIsolationUri(vr.getIsolationUri().toString());
 +            }
 +            if (vr.getTrafficType() != null) {
 +                nicResponse.setTrafficType(vr.getTrafficType().toString());
 +            }
 +            if (vr.getGuestType() != null) {
 +                nicResponse.setType(vr.getGuestType().toString());
 +            }
 +            nicResponse.setIsDefault(vr.isDefaultNic());
 +            nicResponse.setObjectName("nic");
 +            vrData.addNic(nicResponse);
 +        }
 +        return vrData;
 +    }
 +
 +    @Override
 +    public List<DomainRouterJoinVO> searchByIds(Long... vrIds) {
 +        // set detail batch query size
 +        int DETAILS_BATCH_SIZE = 2000;
 +        String batchCfg = _configDao.getValue("detail.batch.query.size");
 +        if (batchCfg != null) {
 +            DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg);
 +        }
 +        // query details by batches
 +        List<DomainRouterJoinVO> uvList = new ArrayList<DomainRouterJoinVO>();
 +        // query details by batches
 +        int curr_index = 0;
 +        if (vrIds.length > DETAILS_BATCH_SIZE) {
 +            while ((curr_index + DETAILS_BATCH_SIZE) <= vrIds.length) {
 +                Long[] ids = new Long[DETAILS_BATCH_SIZE];
 +                for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) {
 +                    ids[k] = vrIds[j];
 +                }
 +                SearchCriteria<DomainRouterJoinVO> sc = vrSearch.create();
 +                sc.setParameters("idIN", ids);
 +                List<DomainRouterJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
 +                if (vms != null) {
 +                    uvList.addAll(vms);
 +                }
 +                curr_index += DETAILS_BATCH_SIZE;
 +            }
 +        }
 +        if (curr_index < vrIds.length) {
 +            int batch_size = (vrIds.length - curr_index);
 +            // set the ids value
 +            Long[] ids = new Long[batch_size];
 +            for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) {
 +                ids[k] = vrIds[j];
 +            }
 +            SearchCriteria<DomainRouterJoinVO> sc = vrSearch.create();
 +            sc.setParameters("idIN", ids);
 +            List<DomainRouterJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
 +            if (vms != null) {
 +                uvList.addAll(vms);
 +            }
 +        }
 +        return uvList;
 +    }
 +
 +    @Override
 +    public List<DomainRouterJoinVO> newDomainRouterView(VirtualRouter vr) {
 +
 +        SearchCriteria<DomainRouterJoinVO> sc = vrIdSearch.create();
 +        sc.setParameters("id", vr.getId());
 +        return searchIncludingRemoved(sc, null, null, false);
 +    }
 +
 +}
diff --cc server/src/main/java/com/cloud/network/NetworkServiceImpl.java
index 8d93b7d,0000000..f1397a1
mode 100644,000000..100644
--- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
@@@ -1,4509 -1,0 +1,4517 @@@
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with 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.
 +package com.cloud.network;
 +
 +import java.net.Inet6Address;
 +import java.net.InetAddress;
 +import java.net.URI;
 +import java.net.UnknownHostException;
 +import java.security.InvalidParameterException;
 +import java.sql.PreparedStatement;
 +import java.sql.ResultSet;
 +import java.sql.SQLException;
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.Collections;
 +import java.util.Comparator;
 +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 javax.inject.Inject;
 +import javax.naming.ConfigurationException;
 +
 +import org.apache.log4j.Logger;
 +
 +import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 +import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 +import org.apache.cloudstack.api.ApiConstants;
 +import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
 +import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin;
 +import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
 +import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
 +import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
 +import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
 +import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
 +import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
 +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
 +import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
 +import org.apache.cloudstack.context.CallContext;
 +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
 +import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 +import org.apache.cloudstack.framework.messagebus.MessageBus;
 +import org.apache.cloudstack.framework.messagebus.PublishScope;
 +import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
 +
 +import com.cloud.api.ApiDBUtils;
 +import com.cloud.configuration.Config;
 +import com.cloud.configuration.ConfigurationManager;
 +import com.cloud.configuration.Resource;
 +import com.cloud.dc.DataCenter;
 +import com.cloud.dc.DataCenter.NetworkType;
 +import com.cloud.dc.DataCenterVO;
 +import com.cloud.dc.DataCenterVnetVO;
 +import com.cloud.dc.Vlan.VlanType;
 +import com.cloud.dc.VlanVO;
 +import com.cloud.dc.dao.DataCenterDao;
 +import com.cloud.dc.dao.DataCenterVnetDao;
 +import com.cloud.dc.dao.VlanDao;
 +import com.cloud.deploy.DeployDestination;
 +import com.cloud.domain.Domain;
 +import com.cloud.domain.DomainVO;
 +import com.cloud.domain.dao.DomainDao;
 +import com.cloud.event.ActionEvent;
 +import com.cloud.event.EventTypes;
 +import com.cloud.event.UsageEventUtils;
 +import com.cloud.exception.ConcurrentOperationException;
 +import com.cloud.exception.InsufficientAddressCapacityException;
 +import com.cloud.exception.InsufficientCapacityException;
 +import com.cloud.exception.InvalidParameterValueException;
 +import com.cloud.exception.PermissionDeniedException;
 +import com.cloud.exception.ResourceAllocationException;
 +import com.cloud.exception.ResourceUnavailableException;
 +import com.cloud.exception.UnsupportedServiceException;
 +import com.cloud.host.dao.HostDao;
 +import com.cloud.network.IpAddress.State;
 +import com.cloud.network.Network.Capability;
 +import com.cloud.network.Network.GuestType;
 +import com.cloud.network.Network.Provider;
 +import com.cloud.network.Network.Service;
 +import com.cloud.network.Networks.BroadcastDomainType;
 +import com.cloud.network.Networks.TrafficType;
 +import com.cloud.network.PhysicalNetwork.BroadcastDomainRange;
 +import com.cloud.network.VirtualRouterProvider.Type;
 +import com.cloud.network.addr.PublicIp;
 +import com.cloud.network.dao.AccountGuestVlanMapDao;
 +import com.cloud.network.dao.AccountGuestVlanMapVO;
 +import com.cloud.network.dao.FirewallRulesDao;
 +import com.cloud.network.dao.IPAddressDao;
 +import com.cloud.network.dao.IPAddressVO;
 +import com.cloud.network.dao.LoadBalancerDao;
 +import com.cloud.network.dao.NetworkDao;
 +import com.cloud.network.dao.NetworkDetailVO;
 +import com.cloud.network.dao.NetworkDetailsDao;
 +import com.cloud.network.dao.NetworkDomainDao;
 +import com.cloud.network.dao.NetworkDomainVO;
 +import com.cloud.network.dao.NetworkServiceMapDao;
 +import com.cloud.network.dao.NetworkVO;
 +import com.cloud.network.dao.OvsProviderDao;
 +import com.cloud.network.dao.PhysicalNetworkDao;
 +import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
 +import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
 +import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
 +import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
 +import com.cloud.network.dao.PhysicalNetworkVO;
 +import com.cloud.network.element.NetworkElement;
 +import com.cloud.network.element.OvsProviderVO;
 +import com.cloud.network.element.VirtualRouterElement;
 +import com.cloud.network.element.VpcVirtualRouterElement;
 +import com.cloud.network.guru.NetworkGuru;
 +import com.cloud.network.rules.FirewallRule.Purpose;
 +import com.cloud.network.rules.FirewallRuleVO;
 +import com.cloud.network.rules.RulesManager;
 +import com.cloud.network.rules.dao.PortForwardingRulesDao;
 +import com.cloud.network.security.SecurityGroupService;
 +import com.cloud.network.vpc.NetworkACL;
 +import com.cloud.network.vpc.PrivateIpVO;
 +import com.cloud.network.vpc.Vpc;
 +import com.cloud.network.vpc.VpcManager;
 +import com.cloud.network.vpc.dao.NetworkACLDao;
 +import com.cloud.network.vpc.dao.PrivateIpDao;
 +import com.cloud.network.vpc.dao.VpcDao;
 +import com.cloud.network.vpc.dao.VpcOfferingDao;
 +import com.cloud.offering.NetworkOffering;
 +import com.cloud.offerings.NetworkOfferingVO;
 +import com.cloud.offerings.dao.NetworkOfferingDao;
 +import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
 +import com.cloud.org.Grouping;
 +import com.cloud.projects.Project;
 +import com.cloud.projects.ProjectManager;
 +import com.cloud.server.ResourceTag;
 +import com.cloud.server.ResourceTag.ResourceObjectType;
 +import com.cloud.tags.ResourceTagVO;
 +import com.cloud.tags.dao.ResourceTagDao;
 +import com.cloud.user.Account;
 +import com.cloud.user.AccountManager;
 +import com.cloud.user.AccountService;
 +import com.cloud.user.AccountVO;
 +import com.cloud.user.DomainManager;
 +import com.cloud.user.ResourceLimitService;
 +import com.cloud.user.User;
 +import com.cloud.user.UserVO;
 +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.StringUtils;
 +import com.cloud.utils.component.ManagerBase;
 +import com.cloud.utils.db.DB;
 +import com.cloud.utils.db.EntityManager;
 +import com.cloud.utils.db.Filter;
 +import com.cloud.utils.db.JoinBuilder;
 +import com.cloud.utils.db.QueryBuilder;
 +import com.cloud.utils.db.SearchBuilder;
 +import com.cloud.utils.db.SearchCriteria;
 +import com.cloud.utils.db.SearchCriteria.Op;
 +import com.cloud.utils.db.Transaction;
 +import com.cloud.utils.db.TransactionCallback;
 +import com.cloud.utils.db.TransactionCallbackNoReturn;
 +import com.cloud.utils.db.TransactionCallbackWithException;
 +import com.cloud.utils.db.TransactionLegacy;
 +import com.cloud.utils.db.TransactionStatus;
 +import com.cloud.utils.exception.CloudRuntimeException;
 +import com.cloud.utils.exception.ExceptionUtil;
 +import com.cloud.utils.net.NetUtils;
 +import com.cloud.vm.Nic;
 +import com.cloud.vm.NicSecondaryIp;
 +import com.cloud.vm.NicVO;
 +import com.cloud.vm.ReservationContext;
 +import com.cloud.vm.ReservationContextImpl;
 +import com.cloud.vm.SecondaryStorageVmVO;
 +import com.cloud.vm.UserVmVO;
 +import com.cloud.vm.VMInstanceVO;
 +import com.cloud.vm.VirtualMachine;
 +import com.cloud.vm.dao.NicDao;
 +import com.cloud.vm.dao.NicSecondaryIpDao;
 +import com.cloud.vm.dao.NicSecondaryIpVO;
 +import com.cloud.vm.dao.UserVmDao;
 +import com.cloud.vm.dao.VMInstanceDao;
 +
 +/**
 + * NetworkServiceImpl implements NetworkService.
 + */
 +public class NetworkServiceImpl extends ManagerBase implements  NetworkService {
 +    private static final Logger s_logger = Logger.getLogger(NetworkServiceImpl.class);
 +
 +    private static final long MIN_VLAN_ID = 0L;
 +    private static final long MAX_VLAN_ID = 4095L; // 2^12 - 1
 +    private static final long MIN_GRE_KEY = 0L;
 +    private static final long MAX_GRE_KEY = 4294967295L; // 2^32 -1
 +    private static final long MIN_VXLAN_VNI = 0L;
 +    private static final long MAX_VXLAN_VNI = 16777214L; // 2^24 -2
 +    // MAX_VXLAN_VNI should be 16777215L (2^24-1), but Linux vxlan interface doesn't accept VNI:2^24-1 now.
 +    // It seems a bug.
 +
 +    @Inject
 +    DataCenterDao _dcDao = null;
 +    @Inject
 +    VlanDao _vlanDao = null;
 +    @Inject
 +    IPAddressDao _ipAddressDao = null;
 +    @Inject
 +    AccountDao _accountDao = null;
 +    @Inject
 +    DomainDao _domainDao = null;
 +    @Inject
 +    UserDao _userDao = null;
 +    @Inject
 +    ConfigurationDao _configDao;
 +    @Inject
 +    UserVmDao _userVmDao = null;
 +    @Inject
 +    AccountManager _accountMgr;
 +    @Inject
 +    ConfigurationManager _configMgr;
 +    @Inject
 +    NetworkOfferingDao _networkOfferingDao = null;
 +    @Inject
 +    NetworkDao _networksDao = null;
 +    @Inject
 +    NicDao _nicDao = null;
 +    @Inject
 +    RulesManager _rulesMgr;
 +    List<NetworkGuru> _networkGurus;
 +    @Inject
 +    NetworkDomainDao _networkDomainDao;
 +    @Inject
 +    VMInstanceDao _vmDao;
 +    @Inject
 +    FirewallRulesDao _firewallDao;
 +    @Inject
 +    ResourceLimitService _resourceLimitMgr;
 +    @Inject
 +    DomainManager _domainMgr;
 +    @Inject
 +    ProjectManager _projectMgr;
 +    @Inject
 +    NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
 +    @Inject
 +    PhysicalNetworkDao _physicalNetworkDao;
 +    @Inject
 +    PhysicalNetworkServiceProviderDao _pNSPDao;
 +    @Inject
 +    PhysicalNetworkTrafficTypeDao _pNTrafficTypeDao;
 +    @Inject
 +    NetworkServiceMapDao _ntwkSrvcDao;
 +    @Inject
 +    StorageNetworkManager _stnwMgr;
 +    @Inject
 +    VpcManager _vpcMgr;
 +    @Inject
 +    PrivateIpDao _privateIpDao;
 +    @Inject
 +    ResourceTagDao _resourceTagDao;
 +    @Inject
 +    NetworkOrchestrationService _networkMgr;
 +    @Inject
 +    NetworkModel _networkModel;
 +    @Inject
 +    NicSecondaryIpDao _nicSecondaryIpDao;
 +    @Inject
 +    PortForwardingRulesDao _portForwardingDao;
 +    @Inject
 +    HostDao _hostDao;
 +    @Inject
 +    InternalLoadBalancerElementService _internalLbElementSvc;
 +    @Inject
 +    DataCenterVnetDao _datacneterVnet;
 +    @Inject
 +    AccountGuestVlanMapDao _accountGuestVlanMapDao;
 +    @Inject
 +    VpcDao _vpcDao;
 +    @Inject
 +    NetworkACLDao _networkACLDao;
 +    @Inject
 +    OvsProviderDao _ovsProviderDao;
 +    @Inject
 +    IpAddressManager _ipAddrMgr;
 +    @Inject
 +    EntityManager _entityMgr;
 +    @Inject
 +    public SecurityGroupService _securityGroupService;
 +    @Inject
 +    MessageBus _messageBus;
 +    @Inject
 +    NetworkDetailsDao _networkDetailsDao;
 +    @Inject
 +    LoadBalancerDao _loadBalancerDao;
 +    @Inject
 +    NetworkMigrationManager _networkMigrationManager;
 +    @Inject
 +    VpcOfferingDao _vpcOfferingDao;
 +    @Inject
 +    AccountService _accountService;
 +
 +    int _cidrLimit;
 +    boolean _allowSubdomainNetworkAccess;
 +
 +    private Map<String, String> _configs;
 +
 +    /* Get a list of IPs, classify them by service */
 +    protected Map<PublicIp, Set<Service>> getIpToServices(List<PublicIp> publicIps, boolean rulesRevoked, boolean includingFirewall) {
 +        Map<PublicIp, Set<Service>> ipToServices = new HashMap<PublicIp, Set<Service>>();
 +
 +        if (publicIps != null && !publicIps.isEmpty()) {
 +            Set<Long> networkSNAT = new HashSet<Long>();
 +            for (PublicIp ip : publicIps) {
 +                Set<Service> services = ipToServices.get(ip);
 +                if (services == null) {
 +                    services = new HashSet<Service>();
 +                }
 +                if (ip.isSourceNat()) {
 +                    if (!networkSNAT.contains(ip.getAssociatedWithNetworkId())) {
 +                        services.add(Service.SourceNat);
 +                        networkSNAT.add(ip.getAssociatedWithNetworkId());
 +                    } else {
 +                        CloudRuntimeException ex = new CloudRuntimeException("Multiple generic source NAT IPs provided for network");
 +                        // see the IPAddressVO.java class.
 +                        IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ip.getAssociatedWithNetworkId());
 +                        String ipAddrUuid = ip.getAssociatedWithNetworkId().toString();
 +                        if (ipAddr != null) {
 +                            ipAddrUuid = ipAddr.getUuid();
 +                        }
 +                        ex.addProxyObject(ipAddrUuid, "networkId");
 +                        throw ex;
 +                    }
 +                }
 +                ipToServices.put(ip, services);
 +
 +                // if IP in allocating state then it will not have any rules attached so skip IPAssoc to network service
 +                // provider
 +                if (ip.getState() == State.Allocating) {
 +                    continue;
 +                }
 +
 +                // check if any active rules are applied on the public IP
 +                Set<Purpose> purposes = getPublicIpPurposeInRules(ip, false, includingFirewall);
 +                // Firewall rules didn't cover static NAT
 +                if (ip.isOneToOneNat() && ip.getAssociatedWithVmId() != null) {
 +                    if (purposes == null) {
 +                        purposes = new HashSet<Purpose>();
 +                    }
 +                    purposes.add(Purpose.StaticNat);
 +                }
 +                if (purposes == null || purposes.isEmpty()) {
 +                    // since no active rules are there check if any rules are applied on the public IP but are in
 +// revoking state
 +
 +                    purposes = getPublicIpPurposeInRules(ip, true, includingFirewall);
 +                    if (ip.isOneToOneNat()) {
 +                        if (purposes == null) {
 +                            purposes = new HashSet<Purpose>();
 +                        }
 +                        purposes.add(Purpose.StaticNat);
 +                    }
 +                    if (purposes == null || purposes.isEmpty()) {
 +                        // IP is not being used for any purpose so skip IPAssoc to network service provider
 +                        continue;
 +                    } else {
 +                        if (rulesRevoked) {
 +                            // no active rules/revoked rules are associated with this public IP, so remove the
 +// association with the provider
 +                            ip.setState(State.Releasing);
 +                        } else {
 +                            if (ip.getState() == State.Releasing) {
 +                                // rules are not revoked yet, so don't let the network service provider revoke the IP
 +// association
 +                                // mark IP is allocated so that IP association will not be removed from the provider
 +                                ip.setState(State.Allocated);
 +                            }
 +                        }
 +                    }
 +                }
 +                if (purposes.contains(Purpose.StaticNat)) {
 +                    services.add(Service.StaticNat);
 +                }
 +                if (purposes.contains(Purpose.LoadBalancing)) {
 +                    services.add(Service.Lb);
 +                }
 +                if (purposes.contains(Purpose.PortForwarding)) {
 +                    services.add(Service.PortForwarding);
 +                }
 +                if (purposes.contains(Purpose.Vpn)) {
 +                    services.add(Service.Vpn);
 +                }
 +                if (purposes.contains(Purpose.Firewall)) {
 +                    services.add(Service.Firewall);
 +                }
 +                if (services.isEmpty()) {
 +                    continue;
 +                }
 +                ipToServices.put(ip, services);
 +            }
 +        }
 +        return ipToServices;
 +    }
 +
 +    protected boolean canIpUsedForNonConserveService(PublicIp ip, Service service) {
 +        // If it's non-conserve mode, then the new ip should not be used by any other services
 +        List<PublicIp> ipList = new ArrayList<PublicIp>();
 +        ipList.add(ip);
 +        Map<PublicIp, Set<Service>> ipToServices = getIpToServices(ipList, false, false);
 +        Set<Service> services = ipToServices.get(ip);
 +        // Not used currently, safe
 +        if (services == null || services.isEmpty()) {
 +            return true;
 +        }
 +        // Since it's non-conserve mode, only one service should used for IP
 +        if (services.size() != 1) {
 +            throw new InvalidParameterException("There are multiple services used ip " + ip.getAddress() + ".");
 +        }
 +        if (service != null && !((Service)services.toArray()[0] == service || service.equals(Service.Firewall))) {
 +            throw new InvalidParameterException("The IP " + ip.getAddress() + " is already used as " + ((Service)services.toArray()[0]).getName() + " rather than "
 +                    + service.getName());
 +        }
 +        return true;
 +    }
 +
 +    protected boolean canIpsUsedForNonConserve(List<PublicIp> publicIps) {
 +        boolean result = true;
 +        for (PublicIp ip : publicIps) {
 +            result = canIpUsedForNonConserveService(ip, null);
 +            if (!result) {
 +                break;
 +            }
 +        }
 +        return result;
 +    }
 +
 +    private boolean canIpsUseOffering(List<PublicIp> publicIps, long offeringId) {
 +        Map<PublicIp, Set<Service>> ipToServices = getIpToServices(publicIps, false, true);
 +        Map<Service, Set<Provider>> serviceToProviders = _networkModel.getNetworkOfferingServiceProvidersMap(offeringId);
 +        NetworkOfferingVO offering = _networkOfferingDao.findById(offeringId);
 +        //For inline mode checking, using firewall provider for LB instead, because public ip would apply on firewall provider
 +        if (offering.isInline()) {
 +            Provider firewallProvider = null;
 +            if (serviceToProviders.containsKey(Service.Firewall)) {
 +                firewallProvider = (Provider)serviceToProviders.get(Service.Firewall).toArray()[0];
 +            }
 +            Set<Provider> p = new HashSet<Provider>();
 +            p.add(firewallProvider);
 +            serviceToProviders.remove(Service.Lb);
 +            serviceToProviders.put(Service.Lb, p);
 +        }
 +        for (PublicIp ip : ipToServices.keySet()) {
 +            Set<Service> services = ipToServices.get(ip);
 +            Provider provider = null;
 +            for (Service service : services) {
 +                Set<Provider> curProviders = serviceToProviders.get(service);
 +                if (curProviders == null || curProviders.isEmpty()) {
 +                    continue;
 +                }
 +                Provider curProvider = (Provider)curProviders.toArray()[0];
 +                if (provider == null) {
 +                    provider = curProvider;
 +                    continue;
 +                }
 +                // We don't support multiple providers for one service now
 +                if (!provider.equals(curProvider)) {
 +                    throw new InvalidParameterException("There would be multiple providers for IP " + ip.getAddress() + " with the new network offering!");
 +                }
 +            }
 +        }
 +        return true;
 +    }
 +
 +    private Set<Purpose> getPublicIpPurposeInRules(PublicIp ip, boolean includeRevoked, boolean includingFirewall) {
 +        Set<Purpose> result = new HashSet<Purpose>();
 +        List<FirewallRuleVO> rules = null;
 +        if (includeRevoked) {
 +            rules = _firewallDao.listByIp(ip.getId());
 +        } else {
 +            rules = _firewallDao.listByIpAndNotRevoked(ip.getId());
 +        }
 +
 +        if (rules == null || rules.isEmpty()) {
 +            return null;
 +        }
 +
 +        for (FirewallRuleVO rule : rules) {
 +            if (rule.getPurpose() != Purpose.Firewall || includingFirewall) {
 +                result.add(rule.getPurpose());
 +            }
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public List<? extends Network> getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner) {
 +
 +        return _networksDao.listByZoneAndGuestType(owner.getId(), zoneId, Network.GuestType.Isolated, false);
 +    }
 +
 +    @Override
 +    public List<? extends Network> getIsolatedNetworksWithSourceNATOwnedByAccountInZone(long zoneId, Account owner) {
 +
 +        return _networksDao.listSourceNATEnabledNetworks(owner.getId(), zoneId, Network.GuestType.Isolated);
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true)
 +    public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp) throws ResourceAllocationException, InsufficientAddressCapacityException,
 +            ConcurrentOperationException {
 +
 +        Account caller = CallContext.current().getCallingAccount();
 +        long callerUserId = CallContext.current().getCallingUserId();
 +        DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
 +
 +        if (networkId != null) {
 +            Network network = _networksDao.findById(networkId);
 +            if (network == null) {
 +                throw new InvalidParameterValueException("Invalid network id is given");
 +            }
 +
 +            if (network.getGuestType() == Network.GuestType.Shared) {
 +                if (zone == null) {
 +                    throw new InvalidParameterValueException("Invalid zone Id is given");
 +                }
 +                // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork'
 +                if (zone.getNetworkType() == NetworkType.Advanced) {
 +                    if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
 +                        _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network);
 +                        if (s_logger.isDebugEnabled()) {
 +                            s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
 +                        }
 +                        return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp);
 +                    } else {
 +                        throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone"
 +                                + " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled");
 +                    }
 +                }
 +            }
 +        } else {
 +            _accountMgr.checkAccess(caller, null, false, ipOwner);
 +        }
 +
 +        return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp);
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_ASSIGN, eventDescription = "allocating portable public Ip", create = true)
 +    public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException,
 +            InsufficientAddressCapacityException, ConcurrentOperationException {
 +        Account caller = CallContext.current().getCallingAccount();
 +        long callerUserId = CallContext.current().getCallingUserId();
 +        DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
 +
 +        if ((networkId == null && vpcId == null) || (networkId != null && vpcId != null)) {
 +            throw new InvalidParameterValueException("One of Network id or VPC is should be passed");
 +        }
 +
 +        if (networkId != null) {
 +            Network network = _networksDao.findById(networkId);
 +            if (network == null) {
 +                throw new InvalidParameterValueException("Invalid network id is given");
 +            }
 +
 +            if (network.getGuestType() == Network.GuestType.Shared) {
 +                if (zone == null) {
 +                    throw new InvalidParameterValueException("Invalid zone Id is given");
 +                }
 +                // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork'
 +                if (zone.getNetworkType() == NetworkType.Advanced) {
 +                    if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
 +                        _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network);
 +                        if (s_logger.isDebugEnabled()) {
 +                            s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
 +                        }
 +                        return _ipAddrMgr.allocatePortableIp(ipOwner, caller, zoneId, networkId, null);
 +                    } else {
 +                        throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone"
 +                                + " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled");
 +                    }
 +                }
 +            }
 +        }
 +
 +        if (vpcId != null) {
 +            Vpc vpc = _vpcDao.findById(vpcId);
 +            if (vpc == null) {
 +                throw new InvalidParameterValueException("Invalid vpc id is given");
 +            }
 +        }
 +
 +        _accountMgr.checkAccess(caller, null, false, ipOwner);
 +
 +        return _ipAddrMgr.allocatePortableIp(ipOwner, caller, zoneId, null, null);
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RELEASE, eventDescription = "disassociating portable Ip", async = true)
 +    public boolean releasePortableIpAddress(long ipAddressId) {
 +        try {
 +            return releaseIpAddressInternal(ipAddressId);
 +        } catch (Exception e) {
 +           return false;
 +        }
 +    }
 +
 +    @Override
 +    @DB
 +    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
 +        _configs = _configDao.getConfiguration("Network", params);
 +
 +        _cidrLimit = NumbersUtil.parseInt(_configs.get(Config.NetworkGuestCidrLimit.key()), 22);
 +
 +        _allowSubdomainNetworkAccess = Boolean.valueOf(_configs.get(Config.SubDomainNetworkAccess.key()));
 +
 +        s_logger.info("Network Service is configured.");
 +
 +        return true;
 +    }
 +
 +    @Override
 +    public boolean start() {
 +        return true;
 +    }
 +
 +    @Override
 +    public boolean stop() {
 +        return true;
 +    }
 +
 +    protected NetworkServiceImpl() {
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_CONFIGURE, eventDescription = "Configuring secondary ip " +
 +            "rules",  async = true)
 +    public boolean configureNicSecondaryIp(NicSecondaryIp secIp, boolean isZoneSgEnabled) {
 +        boolean success = false;
 +
 +        if (isZoneSgEnabled) {
 +            success = _securityGroupService.securityGroupRulesForVmSecIp(secIp.getNicId(), secIp.getIp4Address(), true);
 +            s_logger.info("Associated ip address to NIC : " + secIp.getIp4Address());
 +        } else {
 +            success = true;
 +        }
 +        return success;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_ASSIGN, eventDescription = "assigning secondary ip to nic", create = true)
 +    public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requestedIp) throws InsufficientAddressCapacityException {
 +
 +        Account caller = CallContext.current().getCallingAccount();
 +
 +        //check whether the nic belongs to user vm.
 +        final NicVO nicVO = _nicDao.findById(nicId);
 +        if (nicVO == null) {
 +            throw new InvalidParameterValueException("There is no nic for the " + nicId);
 +        }
 +
 +        if (nicVO.getVmType() != VirtualMachine.Type.User) {
 +            throw new InvalidParameterValueException("The nic is not belongs to user vm");
 +        }
 +
 +        VirtualMachine vm = _userVmDao.findById(nicVO.getInstanceId());
 +        if (vm == null) {
 +            throw new InvalidParameterValueException("There is no vm with the nic");
 +        }
 +
 +        final long networkId = nicVO.getNetworkId();
 +        final Account ipOwner = _accountMgr.getAccount(vm.getAccountId());
 +
 +        // verify permissions
 +        _accountMgr.checkAccess(caller, null, true, vm);
 +
 +        Network network = _networksDao.findById(networkId);
 +        if (network == null) {
 +            throw new InvalidParameterValueException("Invalid network id is given");
 +        }
 +
 +        int maxAllowedIpsPerNic = NumbersUtil.parseInt(_configDao.getValue(Config.MaxNumberOfSecondaryIPsPerNIC.key()), 10);
 +        Long nicWiseIpCount = _nicSecondaryIpDao.countByNicId(nicId);
 +        if(nicWiseIpCount.intValue() >= maxAllowedIpsPerNic) {
 +            s_logger.error("Maximum Number of Ips \"vm.network.nic.max.secondary.ipaddresses = \"" + maxAllowedIpsPerNic + " per Nic has been crossed for the nic " +  nicId + ".");
 +            throw new InsufficientAddressCapacityException("Maximum Number of Ips per Nic has been crossed.", Nic.class, nicId);
 +        }
 +
 +
 +        s_logger.debug("Calling the ip allocation ...");
 +        String ipaddr = null;
 +        //Isolated network can exist in Basic zone only, so no need to verify the zone type
 +        if (network.getGuestType() == Network.GuestType.Isolated) {
 +            try {
 +                ipaddr = _ipAddrMgr.allocateGuestIP(network, requestedIp);
 +            } catch (InsufficientAddressCapacityException e) {
 +                throw new InvalidParameterValueException("Allocating guest ip for nic failed");
 +            }
 +        } else if (network.getGuestType() == Network.GuestType.Shared) {
 +            //for basic zone, need to provide the podId to ensure proper ip alloation
 +            Long podId = null;
 +            DataCenter dc = _dcDao.findById(network.getDataCenterId());
 +
 +            if (dc.getNetworkType() == NetworkType.Basic) {
 +            VMInstanceVO vmi = (VMInstanceVO)vm;
 +                podId = vmi.getPodIdToDeployIn();
 +            if (podId == null) {
 +                    throw new InvalidParameterValueException("vm pod id is null in Basic zone; can't decide the range for ip allocation");
 +            }
 +            }
 +
 +            try {
 +                ipaddr = _ipAddrMgr.allocatePublicIpForGuestNic(network, podId, ipOwner, requestedIp);
 +                if (ipaddr == null) {
 +                    throw new InvalidParameterValueException("Allocating ip to guest nic " + nicId + " failed");
 +                }
 +            } catch (InsufficientAddressCapacityException e) {
 +                s_logger.error("Allocating ip to guest nic " + nicId + " failed");
 +                return null;
 +            }
 +        } else {
 +            s_logger.error("AddIpToVMNic is not supported in this network...");
 +            return null;
 +        }
 +
 +        if (ipaddr != null) {
 +            // we got the ip addr so up the nics table and secodary ip
 +            final String addrFinal = ipaddr;
 +            long id = Transaction.execute(new TransactionCallback<Long>() {
 +                @Override
 +                public Long doInTransaction(TransactionStatus status) {
 +            boolean nicSecondaryIpSet = nicVO.getSecondaryIp();
 +            if (!nicSecondaryIpSet) {
 +                nicVO.setSecondaryIp(true);
 +                // commit when previously set ??
 +                s_logger.debug("Setting nics table ...");
 +                _nicDao.update(nicId, nicVO);
 +            }
 +
 +            s_logger.debug("Setting nic_secondary_ip table ...");
 +                    Long vmId = nicVO.getInstanceId();
 +                    NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, addrFinal, vmId, ipOwner.getId(), ipOwner.getDomainId(), networkId);
 +            _nicSecondaryIpDao.persist(secondaryIpVO);
 +                    return secondaryIpVO.getId();
 +                }
 +            });
 +
 +           return getNicSecondaryIp(id);
 +        } else {
 +            return null;
 +        }
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_UNASSIGN, eventDescription = "Removing secondary ip " +
 +            "from nic", async = true)
 +    public boolean releaseSecondaryIpFromNic(long ipAddressId) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        boolean success = false;
 +
 +        // Verify input parameters
 +        NicSecondaryIpVO secIpVO = _nicSecondaryIpDao.findById(ipAddressId);
 +        if (secIpVO == null) {
 +            throw new InvalidParameterValueException("Unable to find secondary ip address by id");
 +        }
 +
 +        VirtualMachine vm = _userVmDao.findById(secIpVO.getVmId());
 +        if (vm == null) {
 +            throw new InvalidParameterValueException("There is no vm with the given secondary ip");
 +        }
 +        // verify permissions
 +        _accountMgr.checkAccess(caller, null, true, vm);
 +
 +        Network network = _networksDao.findById(secIpVO.getNetworkId());
 +
 +        if (network == null) {
 +            throw new InvalidParameterValueException("Invalid network id is given");
 +        }
 +
 +        // Validate network offering
 +        NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(network.getNetworkOfferingId());
 +
 +        Long nicId = secIpVO.getNicId();
 +        s_logger.debug("ip id = " + ipAddressId + " nic id = " + nicId);
 +        //check is this the last secondary ip for NIC
 +        List<NicSecondaryIpVO> ipList = _nicSecondaryIpDao.listByNicId(nicId);
 +        boolean lastIp = false;
 +        if (ipList.size() == 1) {
 +            // this is the last secondary ip to nic
 +            lastIp = true;
 +        }
 +
 +        DataCenter dc = _dcDao.findById(network.getDataCenterId());
 +        if (dc == null) {
 +            throw new InvalidParameterValueException("Invalid zone Id is given");
 +        }
 +
 +        s_logger.debug("Calling secondary ip " + secIpVO.getIp4Address() + " release ");
 +        if (dc.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Isolated) {
 +            //check PF or static NAT is configured on this ip address
 +            String secondaryIp = secIpVO.getIp4Address();
 +            List<FirewallRuleVO> fwRulesList =  _firewallDao.listByNetworkAndPurpose(network.getId(), Purpose.PortForwarding);
 +
 +            if (fwRulesList.size() != 0) {
 +                for (FirewallRuleVO rule : fwRulesList) {
 +                    if (_portForwardingDao.findByIdAndIp(rule.getId(), secondaryIp) != null) {
 +                        s_logger.debug("VM nic IP " + secondaryIp + " is associated with the port forwarding rule");
 +                        throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is associate with the port forwarding rule");
 +                    }
 +                }
 +            }
 +            //check if the secondary ip associated with any static nat rule
 +            IPAddressVO publicIpVO = _ipAddressDao.findByIpAndNetworkId(secIpVO.getNetworkId(), secondaryIp);
 +            if (publicIpVO != null) {
 +                s_logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId());
 +                throw new InvalidParameterValueException("Can' remove the ip " + secondaryIp + "is associate with static NAT rule public IP address id " + publicIpVO.getId());
 +            }
 +
 +            if (_loadBalancerDao.isLoadBalancerRulesMappedToVmGuestIp(vm.getId(), secondaryIp, network.getId())) {
 +                s_logger.debug("VM nic IP " + secondaryIp + " is mapped to load balancing rule");
 +                throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is mapped to load balancing rule");
 +            }
 +
 +        } else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
 +            final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(secIpVO.getNetworkId(), secIpVO.getIp4Address());
 +            if (ip != null) {
 +                Transaction.execute(new TransactionCallbackNoReturn() {
 +                    @Override
 +                    public void doInTransactionWithoutResult(TransactionStatus status) {
 +                _ipAddrMgr.markIpAsUnavailable(ip.getId());
 +                _ipAddressDao.unassignIpAddress(ip.getId());
 +                    }
 +                });
 +            }
 +        } else {
 +            throw new InvalidParameterValueException("Not supported for this network now");
 +        }
 +
 +        success = removeNicSecondaryIP(secIpVO, lastIp);
 +        return success;
 +    }
 +
 +    boolean removeNicSecondaryIP(final NicSecondaryIpVO ipVO, final boolean lastIp) {
 +        final long nicId = ipVO.getNicId();
 +        final NicVO nic = _nicDao.findById(nicId);
 +
 +        Transaction.execute(new TransactionCallbackNoReturn() {
 +            @Override
 +            public void doInTransactionWithoutResult(TransactionStatus status) {
 +        if (lastIp) {
 +            nic.setSecondaryIp(false);
 +            s_logger.debug("Setting nics secondary ip to false ...");
 +            _nicDao.update(nicId, nic);
 +        }
 +
 +        s_logger.debug("Revoving nic secondary ip entry ...");
 +        _nicSecondaryIpDao.remove(ipVO.getId());
 +            }
 +        });
 +
 +        return true;
 +    }
 +
 +    NicSecondaryIp getNicSecondaryIp(long id) {
 +        NicSecondaryIp nicSecIp = _nicSecondaryIpDao.findById(id);
 +        if (nicSecIp == null) {
 +            return null;
 +        }
 +        return nicSecIp;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NET_IP_RELEASE, eventDescription = "disassociating Ip", async = true)
 +    public boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException {
 +        return releaseIpAddressInternal(ipAddressId);
 +    }
 +
 +    @DB
 +    private boolean releaseIpAddressInternal(long ipAddressId) throws InsufficientAddressCapacityException {
 +        Long userId = CallContext.current().getCallingUserId();
 +        Account caller = CallContext.current().getCallingAccount();
 +
 +        // Verify input parameters
 +        IPAddressVO ipVO = _ipAddressDao.findById(ipAddressId);
 +        if (ipVO == null) {
 +            throw new InvalidParameterValueException("Unable to find ip address by id");
 +        }
 +
 +        if (ipVO.getAllocatedTime() == null) {
 +            s_logger.debug("Ip Address id= " + ipAddressId + " is not allocated, so do nothing.");
 +            return true;
 +        }
 +
 +        // verify permissions
 +        if (ipVO.getAllocatedToAccountId() != null) {
 +            _accountMgr.checkAccess(caller, null, true, ipVO);
 +        }
 +
 +        if (ipVO.isSourceNat()) {
 +            throw new IllegalArgumentException("ip address is used for source nat purposes and can not be disassociated.");
 +        }
 +
 +        VlanVO vlan = _vlanDao.findById(ipVO.getVlanId());
 +        if (!vlan.getVlanType().equals(VlanType.VirtualNetwork)) {
 +            throw new IllegalArgumentException("only ip addresses that belong to a virtual network may be disassociated.");
 +        }
 +
 +        // don't allow releasing system ip address
 +        if (ipVO.getSystem()) {
 +            throwInvalidIdException("Can't release system IP address with specified id", ipVO.getUuid(), "systemIpAddrId");
 +        }
 +
 +        boolean success = _ipAddrMgr.disassociatePublicIpAddress(ipAddressId, userId, caller);
 +
 +        if (success) {
 +            Long networkId = ipVO.getAssociatedWithNetworkId();
 +            if (networkId != null) {
 +                Network guestNetwork = getNetwork(networkId);
 +                NetworkOffering offering = _entityMgr.findById(NetworkOffering.class, guestNetwork.getNetworkOfferingId());
 +                Long vmId = ipVO.getAssociatedWithVmId();
 +                if (offering.getElasticIp() && vmId != null) {
 +                    _rulesMgr.getSystemIpAndEnableStaticNatForVm(_userVmDao.findById(vmId), true);
 +                    return true;
 +                }
 +            }
 +        } else {
 +            s_logger.warn("Failed to release public ip address id=" + ipAddressId);
 +        }
 +        return success;
 +    }
 +
 +    @Override
 +    @DB
 +    public Network getNetwork(long id) {
 +        return _networksDao.findById(id);
 +    }
 +
 +    private void checkSharedNetworkCidrOverlap(Long zoneId, long physicalNetworkId, String cidr) {
 +        if (zoneId == null || cidr == null) {
 +            return;
 +        }
 +
 +        DataCenter zone = _dcDao.findById(zoneId);
 +        List<NetworkVO> networks = _networksDao.listByZone(zoneId);
 +        Map<Long, String> networkToCidr = new HashMap<Long, String>();
 +
 +        // check for CIDR overlap with all possible CIDR for isolated guest networks
 +        // in the zone when using external networking
 +        PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId);
 +        if (pNetwork.getVnet() != null) {
 +            List<Pair<Integer, Integer>> vlanList = pNetwork.getVnet();
 +            for (Pair<Integer, Integer> vlanRange : vlanList) {
 +                Integer lowestVlanTag = vlanRange.first();
 +                Integer highestVlanTag = vlanRange.second();
 +                for (int vlan = lowestVlanTag; vlan <= highestVlanTag; ++vlan) {
 +                    int offset = vlan - lowestVlanTag;
 +                    String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key());
 +                    int cidrSize = 8 + Integer.parseInt(globalVlanBits);
 +                    String guestNetworkCidr = zone.getGuestNetworkCidr();
 +                    String[] cidrTuple = guestNetworkCidr.split("\\/");
 +                    long newCidrAddress = (NetUtils.ip2Long(cidrTuple[0]) & 0xff000000) | (offset << (32 - cidrSize));
 +                    if (NetUtils.isNetworksOverlap(NetUtils.long2Ip(newCidrAddress), cidr)) {
 +                        throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR that is reserved for zone vlan " + vlan);
 +                    }
 +                }
 +            }
 +        }
 +
 +        // check for CIDR overlap with all CIDR's of the shared networks in the zone
 +        for (NetworkVO network : networks) {
 +            if (network.getGuestType() == GuestType.Isolated) {
 +                continue;
 +            }
 +            if (network.getCidr() != null) {
 +                networkToCidr.put(network.getId(), network.getCidr());
 +            }
 +        }
 +        if (networkToCidr != null && !networkToCidr.isEmpty()) {
 +            for (long networkId : networkToCidr.keySet()) {
 +                String ntwkCidr = networkToCidr.get(networkId);
 +                if (NetUtils.isNetworksOverlap(ntwkCidr, cidr)) {
 +                    throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR of a shared network in the zone.");
 +                }
 +            }
 +        }
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_NETWORK_CREATE, eventDescription = "creating network")
 +    public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException {
 +        Long networkOfferingId = cmd.getNetworkOfferingId();
 +        String gateway = cmd.getGateway();
 +        String startIP = cmd.getStartIp();
 +        String endIP = cmd.getEndIp();
 +        String netmask = cmd.getNetmask();
 +        String networkDomain = cmd.getNetworkDomain();
 +        String vlanId = null;
 +        boolean bypassVlanOverlapCheck = false;
 +        if (cmd instanceof CreateNetworkCmdByAdmin) {
 +            vlanId = ((CreateNetworkCmdByAdmin)cmd).getVlan();
 +        }
 +        if (cmd instanceof CreateNetworkCmdByAdmin) {
 +            bypassVlanOverlapCheck = ((CreateNetworkCmdByAdmin)cmd).getBypassVlanOverlapCheck();
 +        }
 +
 +        String name = cmd.getNetworkName();
 +        String displayText = cmd.getDisplayText();
 +        Account caller = CallContext.current().getCallingAccount();
 +        Long physicalNetworkId = cmd.getPhysicalNetworkId();
 +        Long zoneId = cmd.getZoneId();
 +        String aclTypeStr = cmd.getAclType();
 +        Long domainId = cmd.getDomainId();
 +        boolean isDomainSpecific = false;
 +        Boolean subdomainAccess = cmd.getSubdomainAccess();
 +        Long vpcId = cmd.getVpcId();
 +        String startIPv6 = cmd.getStartIpv6();
 +        String endIPv6 = cmd.getEndIpv6();
 +        String ip6Gateway = cmd.getIp6Gateway();
 +        String ip6Cidr = cmd.getIp6Cidr();
 +        Boolean displayNetwork = cmd.getDisplayNetwork();
 +        Long aclId = cmd.getAclId();
 +        String isolatedPvlan = cmd.getIsolatedPvlan();
 +        String externalId = cmd.getExternalId();
 +
 +        // Validate network offering
 +        NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
 +        if (ntwkOff == null || ntwkOff.isSystemOnly()) {
 +            InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find network offering by specified id");
 +            if (ntwkOff != null) {
 +                ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId");
 +            }
 +            throw ex;
 +        }
 +        // validate physical network and zone
 +        // Check if physical network exists
 +        PhysicalNetwork pNtwk = null;
 +        if (physicalNetworkId != null) {
 +            pNtwk = _physicalNetworkDao.findById(physicalNetworkId);
 +            if (pNtwk == null) {
 +                throw new InvalidParameterValueException("Unable to find a physical network having the specified physical network id");
 +            }
 +        }
 +
 +        if (zoneId == null) {
 +            zoneId = pNtwk.getDataCenterId();
 +        }
 +
 +        if (displayNetwork == null) {
 +            displayNetwork = true;
 +        }
 +
 +        DataCenter zone = _dcDao.findById(zoneId);
 +        if (zone == null) {
 +            throw new InvalidParameterValueException("Specified zone id was not found");
 +        }
 +
 +        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
 +            // See DataCenterVO.java
 +            PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation since specified Zone is currently disabled");
 +            ex.addProxyObject(zone.getUuid(), "zoneId");
 +            throw ex;
 +        }
 +
 +        // Only domain and account ACL types are supported in Acton.
 +        ACLType aclType = null;
 +        if (aclTypeStr != null) {
 +            if (aclTypeStr.equalsIgnoreCase(ACLType.Account.toString())) {
 +                aclType = ACLType.Account;
 +            } else if (aclTypeStr.equalsIgnoreCase(ACLType.Domain.toString())) {
 +                aclType = ACLType.Domain;
 +            } else {
 +                throw new InvalidParameterValueException("Incorrect aclType specified. Check the API documentation for supported types");
 +            }
 +            // In 3.0 all Shared networks should have aclType == Domain, all Isolated networks aclType==Account
 +            if (ntwkOff.getGuestType() == GuestType.Isolated) {
 +                if (aclType != ACLType.Account) {
 +                    throw new InvalidParameterValueException("AclType should be " + ACLType.Account + " for network of type " + Network.GuestType.Isolated);
 +                }
 +            } else if (ntwkOff.getGuestType() == GuestType.Shared) {
 +                if (!(aclType == ACLType.Domain || aclType == ACLType.Account)) {
 +                    throw new InvalidParameterValueException("AclType should be " + ACLType.Domain + " or " + ACLType.Account + " for network of type " + Network.GuestType.Shared);
 +                }
 +            }
 +        } else {
 +            if (ntwkOff.getGuestType() == GuestType.Isolated || ntwkOff.getGuestType() == GuestType.L2) {
 +                aclType = ACLType.Account;
 +            } else if (ntwkOff.getGuestType() == GuestType.Shared) {
 +                aclType = ACLType.Domain;
 +            }
 +        }
 +
 +        // Only Admin can create Shared networks
 +        if ((ntwkOff.getGuestType() == GuestType.Shared || ntwkOff.getGuestType() == GuestType.L2) && !_accountMgr.isAdmin(caller.getId())) {
 +            throw new InvalidParameterValueException("Only Admins can create network with guest type " + GuestType.Shared + " or " + GuestType.L2);
 +        }
 +
 +        // Check if the network is domain specific
 +        if (aclType == ACLType.Domain) {
 +            // only Admin can create domain with aclType=Domain
 +            if (!_accountMgr.isAdmin(caller.getId())) {
 +                throw new PermissionDeniedException("Only admin can create networks with aclType=Domain");
 +            }
 +
 +            // only shared networks can be Domain specific
 +            if (ntwkOff.getGuestType() != GuestType.Shared) {
 +                throw new InvalidParameterValueException("Only " + GuestType.Shared + " networks can have aclType=" + ACLType.Domain);
 +            }
 +
 +            if (domainId != null) {
 +                if (ntwkOff.getTrafficType() != TrafficType.Guest || ntwkOff.getGuestType() != Network.GuestType.Shared) {
 +                    throw new InvalidParameterValueException("Domain level networks are supported just for traffic type " + TrafficType.Guest + " and guest type "
 +                            + Network.GuestType.Shared);
 +                }
 +
 +                DomainVO domain = _domainDao.findById(domainId);
 +                if (domain == null) {
 +                    throw new InvalidParameterValueException("Unable to find domain by specified id");
 +                }
 +                _accountMgr.checkAccess(caller, domain);
 +            }
 +            isDomainSpecific = true;
 +
 +        } else if (subdomainAccess != null) {
 +            throw new InvalidParameterValueException("Parameter subDomainAccess can be specified only with aclType=Domain");
 +        }
 +        Account owner = null;
 +        if ((cmd.getAccountName() != null && domainId != null) || cmd.getProjectId() != null) {
 +            owner = _accountMgr.finalizeOwner(caller, cmd.getAccountName(), domainId, cmd.getProjectId());
 +        } else {
 +            owner = caller;
 +        }
 +
 +        boolean ipv4 = true, ipv6 = false;
 +        if (startIP != null) {
 +            ipv4 = true;
 +        }
 +        if (startIPv6 != null) {
 +            ipv6 = true;
 +        }
 +
 +        if (gateway != null) {
 +            try {
 +                // getByName on a literal representation will only check validity of the address
 +                // http://docs.oracle.com/javase/6/docs/api/java/net/InetAddress.html#getByName(java.lang.String)
 +                InetAddress gatewayAddress = InetAddress.getByName(gateway);
 +                if (gatewayAddress instanceof Inet6Address) {
 +                    ipv6 = true;
 +                } else {
 +                    ipv4 = true;
 +                }
 +            } catch (UnknownHostException e) {
 +                s_logger.error("Unable to convert gateway IP to a InetAddress", e);
 +                throw new InvalidParameterValueException("Gateway parameter is invalid");
 +            }
 +        }
 +
 +        String cidr = null;
 +        if (ipv4) {
 +            // if end ip is not specified, default it to startIp
 +            if (startIP != null) {
 +                if (!NetUtils.isValidIp4(startIP)) {
 +                    throw new InvalidParameterValueException("Invalid format for the startIp parameter");
 +                }
 +                if (endIP == null) {
 +                    endIP = startIP;
 +                } else if (!NetUtils.isValidIp4(endIP)) {
 +                    throw new InvalidParameterValueException("Invalid format for the endIp parameter");
 +                }
 +            }
 +
 +            if (startIP != null && endIP != null) {
 +                if (!(gateway != null && netmask != null)) {
 +                    throw new InvalidParameterValueException("gateway and netmask should be defined when startIP/endIP are passed in");
 +                }
 +            }
 +
 +            if (gateway != null && netmask != null) {
 +                if(NetUtils.isNetworkorBroadcastIP(gateway,netmask)) {
 +                    if (s_logger.isDebugEnabled()) {
 +                        s_logger.debug("The gateway IP provided is " + gateway + " and netmask is " + netmask + ". The IP is either broadcast or network IP.");
 +                    }
 +                    throw new InvalidParameterValueException("Invalid gateway IP provided. Either the IP is broadcast or network IP.");
 +                }
 +
 +                if (!NetUtils.isValidIp4(gateway)) {
 +                    throw new InvalidParameterValueException("Invalid gateway");
 +                }
 +                if (!NetUtils.isValidIp4Netmask(netmask)) {
 +                    throw new InvalidParameterValueException("Invalid netmask");
 +                }
 +
 +                cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask);
 +            }
 +
 +        }
 +
 +        if (ipv6) {
 +            if (endIPv6 == null) {
 +                endIPv6 = startIPv6;
 +            }
 +            _networkModel.checkIp6Parameters(startIPv6, endIPv6, ip6Gateway, ip6Cidr);
 +
 +            if (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() != Network.GuestType.Shared) {
 +                throw new InvalidParameterValueException("Can only support create IPv6 network with advance shared network!");
 +            }
 +        }
 +
 +        if (isolatedPvlan != null && (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() != Network.GuestType.Shared)) {
 +            throw new InvalidParameterValueException("Can only support create Private VLAN network with advance shared network!");
 +        }
 +
 +        if (isolatedPvlan != null && ipv6) {
 +            throw new InvalidParameterValueException("Can only support create Private VLAN network with IPv4!");
 +        }
 +
 +        // Regular user can create Guest Isolated Source Nat enabled network only
 +        if (_accountMgr.isNormalUser(caller.getId())
 +                && (ntwkOff.getTrafficType() != TrafficType.Guest || ntwkOff.getGuestType() != Network.GuestType.Isolated
 +                        && areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) {
 +            throw new InvalidParameterValueException("Regular user can create a network only from the network" + " offering having traffic type " + TrafficType.Guest
 +                    + " and network type " + Network.GuestType.Isolated + " with a service " + Service.SourceNat.getName() + " enabled");
 +        }
 +
 +        // Don't allow to specify vlan if the caller is not ROOT admin
 +        if (!_accountMgr.isRootAdmin(caller.getId()) && (ntwkOff.getSpecifyVlan() || vlanId != null || bypassVlanOverlapCheck)) {
 +            throw new InvalidParameterValueException("Only ROOT admin is allowed to specify vlanId or bypass vlan overlap check");
 +        }
 +
 +        if (ipv4) {
 +            // For non-root admins check cidr limit - if it's allowed by global config value
 +            if (!_accountMgr.isRootAdmin(caller.getId()) && cidr != null) {
 +
 +                String[] cidrPair = cidr.split("\\/");
 +                int cidrSize = Integer.parseInt(cidrPair[1]);
 +
 +                if (cidrSize < _cidrLimit) {
 +                    throw new InvalidParameterValueException("Cidr size can't be less than " + _cidrLimit);
 +                }
 +            }
 +        }
 +
 +        Collection<String> ntwkProviders = _networkMgr.finalizeServicesAndProvidersForNetwork(ntwkOff, physicalNetworkId).values();
 +        if (ipv6 && providersConfiguredForExternalNetworking(ntwkProviders)) {
 +            throw new InvalidParameterValueException("Cannot support IPv6 on network offering with external devices!");
 +        }
 +
 +        if (isolatedPvlan != null && providersConfiguredForExternalNetworking(ntwkProviders)) {
 +            throw new InvalidParameterValueException("Cannot support private vlan on network offering with external devices!");
 +        }
 +
 +        if (cidr != null && providersConfiguredForExternalNetworking(ntwkProviders)) {
 +            if (ntwkOff.getGuestType() == GuestType.Shared && (zone.getNetworkType() == NetworkType.Advanced) && isSharedNetworkOfferingWithServices(networkOfferingId)) {
 +                // validate if CIDR specified overlaps with any of the CIDR's allocated for isolated networks and shared networks in the zone
 +                checkSharedNetworkCidrOverlap(zoneId, pNtwk.getId(), cidr);
 +            } else {
 +                // if the guest network is for the VPC, if any External Provider are supported in VPC
 +                // cidr will not be null as it is generated from the super cidr of vpc.
 +                // if cidr is not null and network is not part of vpc then throw the exception
 +                if (vpcId == null)
 +                    throw new InvalidParameterValueException("Cannot specify CIDR when using network offering with external devices!");
 +            }
 +        }
 +
 +        // Vlan is created in 1 cases - works in Advance zone only:
 +        // 1) GuestType is Shared
 +        boolean createVlan = (startIP != null && endIP != null && zone.getNetworkType() == NetworkType.Advanced
 +                && ((ntwkOff.getGuestType() == Network.GuestType.Shared)
 +                || (ntwkOff.getGuestType() == GuestType.Isolated &&
 +                !areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))));
 +
 +        if (!createVlan) {
 +            // Only support advance shared network in IPv6, which means createVlan is a must
 +            if (ipv6) {
 +                createVlan = true;
 +            }
 +        }
 +
 +        // Can add vlan range only to the network which allows it
 +        if (createVlan && !ntwkOff.getSpecifyIpRanges()) {
 +            throwInvalidIdException("Network offering with specified id doesn't support adding multiple ip ranges", ntwkOff.getUuid(), "networkOfferingId");
 +        }
 +
 +        Network network = commitNetwork(networkOfferingId, gateway, startIP, endIP, netmask, networkDomain, vlanId, bypassVlanOverlapCheck, name, displayText, caller, physicalNetworkId, zoneId, domainId,
 +                isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, isolatedPvlan, ntwkOff, pNtwk, aclType, owner, cidr,
 +                createVlan, externalId);
 +
 +        // if the network offering has persistent set to true, implement the network
 +        if (ntwkOff.getIsPersistent()) {
 +            try {
 +                if (network.getState() == Network.State.Setup) {
 +                    s_logger.debug("Network id=" + network.getId() + " is already provisioned");
 +                    return network;
 +                }
 +                DeployDestination dest = new DeployDestination(zone, null, null, null);
 +                UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId());
 +                Journal journal = new Journal.LogJournal("Implementing " + network, s_logger);
 +                ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), journal, callerUser, caller);
 +                s_logger.debug("Implementing network " + network + " as a part of network provision for persistent network");
 +                Pair<? extends NetworkGuru, ? extends Network> implementedNetwork = _networkMgr.implementNetwork(network.getId(), dest, context);
 +                if (implementedNetwork == null || implementedNetwork.first() == null) {
 +                    s_logger.warn("Failed to provision the network " + network);
 +                }
 +                network = implementedNetwork.second();
 +            } catch (ResourceUnavailableException ex) {
 +                s_logger.warn("Failed to implement persistent guest network " + network + "due to ", ex);
 +                CloudRuntimeException e = new CloudRuntimeException("Failed to implement persistent guest network");
 +                e.addProxyObject(network.getUuid(), "networkId");
 +                throw e;
 +            }
 +        }
 +        return network;
 +    }
 +
 +    private Network commitNetwork(final Long networkOfferingId, final String gateway, final String startIP, final String endIP, final String netmask, final String networkDomain,
 +                                  final String vlanId, final Boolean bypassVlanOverlapCheck, final String name, final String displayText, final Account caller, final Long physicalNetworkId, final Long zoneId, final Long domainId,
 +                                  final boolean isDomainSpecific, final Boolean subdomainAccessFinal, final Long vpcId, final String startIPv6, final String endIPv6, final String ip6Gateway,
 +                                  final String ip6Cidr, final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final NetworkOfferingVO ntwkOff, final PhysicalNetwork pNtwk,
 +                                  final ACLType aclType, final Account ownerFinal, final String cidr, final boolean createVlan, final String externalId) throws InsufficientCapacityException, ResourceAllocationException {
 +        try {
 +            Network network = Transaction.execute(new TransactionCallbackWithException<Network, Exception>() {
 +                @Override
 +                public Network doInTransaction(TransactionStatus status) throws InsufficientCapacityException, ResourceAllocationException {
 +                    Account owner = ownerFinal;
 +                    Boolean subdomainAccess = subdomainAccessFinal;
 +
 +                    Long sharedDomainId = null;
 +                    if (isDomainSpecific) {
 +                        if (domainId != null) {
 +                            sharedDomainId = domainId;
 +                        } else {
 +                            sharedDomainId = _domainMgr.getDomain(Domain.ROOT_DOMAIN).getId();
 +                            subdomainAccess = true;
 +                        }
 +                    }
 +
 +                    // default owner to system if network has aclType=Domain
 +                    if (aclType == ACLType.Domain) {
 +                        owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM);
 +                    }
 +
 +                    // Create guest network
 +                    Network network = null;
 +                    if (vpcId != null) {
 +                        if (!_configMgr.isOfferingForVpc(ntwkOff)) {
 +                            throw new InvalidParameterValueException("Network offering can't be used for VPC networks");
 +                        }
 +
 +                        if (aclId != null) {
 +                            NetworkACL acl = _networkACLDao.findById(aclId);
 +                            if (acl == null) {
 +                                throw new InvalidParameterValueException("Unable to find specified NetworkACL");
 +                            }
 +
 +                            if (aclId != NetworkACL.DEFAULT_DENY && aclId != NetworkACL.DEFAULT_ALLOW) {
 +                                // ACL is not default DENY/ALLOW
 +                                // ACL should be associated with a VPC
 +                                if (!vpcId.equals(acl.getVpcId())) {
 +                                    throw new InvalidParameterValueException("ACL: " + aclId + " do not belong to the VPC");
 +                                }
 +                            }
 +                        }
 +                        network = _vpcMgr.createVpcGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, networkDomain, owner, sharedDomainId, pNtwk, zoneId,
 +                                aclType, subdomainAccess, vpcId, aclId, caller, displayNetwork, externalId);
 +                    } else {
 +                        if (_configMgr.isOfferingForVpc(ntwkOff)) {
 +                            throw new InvalidParameterValueException("Network offering can be used for VPC networks only");
 +                        }
 +                        if (ntwkOff.getInternalLb()) {
 +                            throw new InvalidParameterValueException("Internal Lb can be enabled on vpc networks only");
 +                        }
 +
 +                        network = _networkMgr.createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, bypassVlanOverlapCheck, networkDomain, owner, sharedDomainId, pNtwk, zoneId,
 +                                aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan, externalId);
 +                    }
 +
 +                    if (_accountMgr.isRootAdmin(caller.getId()) && createVlan && network != null) {
 +                        // Create vlan ip range
 +                        _configMgr.createVlanAndPublicIpRange(pNtwk.getDataCenterId(), network.getId(), physicalNetworkId, false, false, null, startIP, endIP, gateway, netmask, vlanId,
 +                                bypassVlanOverlapCheck, null, null, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
 +                    }
 +                    return network;
 +                }
 +            });
 +            if (domainId != null && aclType == ACLType.Domain) {
 +                // send event for storing the domain wide resource access
 +                Map<String, Object> params = new HashMap<String, Object>();
 +                params.put(ApiConstants.ENTITY_TYPE, Network.class);
 +                params.put(ApiConstants.ENTITY_ID, network.getId());
 +                params.put(ApiConstants.DOMAIN_ID, domainId);
 +                params.put(ApiConstants.SUBDOMAIN_ACCESS, subdomainAccessFinal == null ? Boolean.TRUE : subdomainAccessFinal);
 +                _messageBus.publish(_name, EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, PublishScope.LOCAL, params);
 +            }
 +            return network;
 +        } catch (Exception e) {
 +            ExceptionUtil.rethrowRuntime(e);
 +            ExceptionUtil.rethrow(e, InsufficientCapacityException.class);
 +            ExceptionUtil.rethrow(e, ResourceAllocationException.class);
 +            throw new IllegalStateException(e);
 +        }
 +    }
 +
 +    @Override
 +    public Pair<List<? extends Network>, Integer> searchForNetworks(ListNetworksCmd cmd) {
 +        Long id = cmd.getId();
 +        String keyword = cmd.getKeyword();
 +        Long zoneId = cmd.getZoneId();
 +        Account caller = CallContext.current().getCallingAccount();
 +        Long domainId = cmd.getDomainId();
 +        String accountName = cmd.getAccountName();
 +        String guestIpType = cmd.getGuestIpType();
 +        String trafficType = cmd.getTrafficType();
 +        Boolean isSystem = cmd.getIsSystem();
 +        String aclType = cmd.getAclType();
 +        Long projectId = cmd.getProjectId();
 +        List<Long> permittedAccounts = new ArrayList<Long>();
 +        String path = null;
 +        Long physicalNetworkId = cmd.getPhysicalNetworkId();
 +        List<String> supportedServicesStr = cmd.getSupportedServices();
 +        Boolean restartRequired = cmd.isRestartRequired();
 +        boolean listAll = cmd.listAll();
 +        boolean isRecursive = cmd.isRecursive();
 +        Boolean specifyIpRanges = cmd.isSpecifyIpRanges();
 +        Long vpcId = cmd.getVpcId();
 +        Boolean canUseForDeploy = cmd.canUseForDeploy();
 +        Map<String, String> tags = cmd.getTags();
 +        Boolean forVpc = cmd.getForVpc();
 +        Boolean display = cmd.getDisplay();
 +
 +        // 1) default is system to false if not specified
 +        // 2) reset parameter to false if it's specified by the regular user
 +        if ((isSystem == null || _accountMgr.isNormalUser(caller.getId())) && id == null) {
 +            isSystem = false;
 +        }
 +
 +        // Account/domainId parameters and isSystem are mutually exclusive
 +        if (isSystem != null && isSystem && (accountName != null || domainId != null)) {
 +            throw new InvalidParameterValueException("System network belongs to system, account and domainId parameters can't be specified");
 +        }
 +
 +        if (domainId != null) {
 +            DomainVO domain = _domainDao.findById(domainId);
 +            if (domain == null) {
 +                // see DomainVO.java
 +                throw new InvalidParameterValueException("Specified domain id doesn't exist in the system");
 +            }
 +
 +            _accountMgr.checkAccess(caller, domain);
 +            if (accountName != null) {
 +                Account owner = _accountMgr.getActiveAccountByName(accountName, domainId);
 +                if (owner == null) {
 +                    // see DomainVO.java
 +                    throw new InvalidParameterValueException("Unable to find account " + accountName + " in specified domain");
 +                }
 +
 +                _accountMgr.checkAccess(caller, null, true, owner);
 +                permittedAccounts.add(owner.getId());
 +            }
 +        }
 +
 +        if (!_accountMgr.isAdmin(caller.getId()) || (projectId != null && projectId.longValue() != -1 && domainId == null)) {
 +            permittedAccounts.add(caller.getId());
 +            domainId = caller.getDomainId();
 +        }
 +
 +        // set project information
 +        boolean skipProjectNetworks = true;
 +        if (projectId != null) {
 +            if (projectId.longValue() == -1) {
 +                if (!_accountMgr.isAdmin(caller.getId())) {
 +                    permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId()));
 +                }
 +            } else {
 +                permittedAccounts.clear();
 +                Project project = _projectMgr.getProject(projectId);
 +                if (project == null) {
 +                    throw new InvalidParameterValueException("Unable to find project by specified id");
 +                }
 +                if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
 +                    // getProject() returns type ProjectVO.
 +                    throwInvalidIdException("Account " + caller + " cannot access specified project id", project.getUuid(), "projectId");
 +                }
 +
 +                //add project account
 +                permittedAccounts.add(project.getProjectAccountId());
 +                //add caller account (if admin)
 +                if (_accountMgr.isAdmin(caller.getId())) {
 +                    permittedAccounts.add(caller.getId());
 +                }
 +            }
 +            skipProjectNetworks = false;
 +        }
 +
 +        if (domainId != null) {
 +            path = _domainDao.findById(domainId).getPath();
 +        } else {
 +        path = _domainDao.findById(caller.getDomainId()).getPath();
 +        }
 +
 +        if (listAll && domainId == null) {
 +            isRecursive = true;
 +        }
 +
 +        Filter searchFilter = new Filter(NetworkVO.class, "id", false, null, null);
 +        SearchBuilder<NetworkVO> sb = _networksDao.createSearchBuilder();
 +
 +        if (forVpc != null) {
 +            if (forVpc) {
 +                sb.and("vpc", sb.entity().getVpcId(), Op.NNULL);
 +            } else {
 +                sb.and("vpc", sb.entity().getVpcId(), Op.NULL);
 +            }
 +        }
 +
 +        // Don't display networks created of system network offerings
 +        SearchBuilder<NetworkOfferingVO> networkOfferingSearch = _networkOfferingDao.createSearchBuilder();
 +        networkOfferingSearch.and("systemOnly", networkOfferingSearch.entity().isSystemOnly(), SearchCriteria.Op.EQ);
 +        if (isSystem != null && isSystem) {
 +            networkOfferingSearch.and("trafficType", networkOfferingSearch.entity().getTrafficType(), SearchCriteria.Op.EQ);
 +        }
 +        sb.join("networkOfferingSearch", networkOfferingSearch, sb.entity().getNetworkOfferingId(), networkOfferingSearch.entity().getId(), JoinBuilder.JoinType.INNER);
 +
 +        SearchBuilder<DataCenterVO> zoneSearch = _dcDao.createSearchBuilder();
 +        zoneSearch.and("networkType", zoneSearch.entity().getNetworkType(), SearchCriteria.Op.EQ);
 +        sb.join("zoneSearch", zoneSearch, sb.entity().getDataCenterId(), zoneSearch.entity().getId(), JoinBuilder.JoinType.INNER);
 +        sb.and("removed", sb.entity().getRemoved(), Op.NULL);
 +
 +        if (tags != null && !tags.isEmpty()) {
 +            SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
 +            for (int count = 0; count < tags.size(); count++) {
 +                tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
 +                tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
 +                tagSearch.cp();
 +            }
 +            tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
 +            sb.groupBy(sb.entity().getId());
 +            sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
 +        }
 +
 +        if (permittedAccounts.isEmpty()) {
 +            SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
 +            domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
 +            sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
 +        }
 +
 +            SearchBuilder<AccountVO> accountSearch = _accountDao.createSearchBuilder();
 +        accountSearch.and("typeNEQ", accountSearch.entity().getType(), SearchCriteria.Op.NEQ);
 +        accountSearch.and("typeEQ", accountSearch.entity().getType(), SearchCriteria.Op.EQ);
 +
 +            sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
 +
 +        List<NetworkVO> networksToReturn = new ArrayList<NetworkVO>();
 +
 +        if (isSystem == null || !isSystem) {
 +            if (!permittedAccounts.isEmpty()) {
 +                //get account level networks
 +                networksToReturn.addAll(listAccountSpecificNetworks(
 +                        buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired,
 +                                specifyIpRanges, vpcId, tags, display), searchFilter, permittedAccounts));
 +                //get domain level networks
 +                if (domainId != null) {
 +                    networksToReturn.addAll(listDomainLevelNetworks(
 +                            buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired,
 +                                    specifyIpRanges, vpcId, tags, display), searchFilter, domainId, false));
 +                }
 +            } else {
 +                //add account specific networks
 +                networksToReturn.addAll(listAccountSpecificNetworksByDomainPath(
 +                        buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired,
 +                                specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive));
 +                //add domain specific networks of domain + parent domains
 +                networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(
 +                        buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired,
 +                                specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive));
 +                //add networks of subdomains
 +                if (domainId == null) {
 +                    networksToReturn.addAll(listDomainLevelNetworks(
 +                            buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired,
 +                                    specifyIpRanges, vpcId, tags, display), searchFilter, caller.getDomainId(), true));
 +                }
 +            }
 +        } else {
 +            networksToReturn = _networksDao.search(
 +                    buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, null, skipProjectNetworks, restartRequired,
 +                            specifyIpRanges, vpcId, tags, display), searchFilter);
 +        }
 +
 +        if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) {
 +            List<NetworkVO> supportedNetworks = new ArrayList<NetworkVO>();
 +            Service[] suppportedServices = new Service[supportedServicesStr.size()];
 +            int i = 0;
 +            for (String supportedServiceStr : supportedServicesStr) {
 +                Service service = Service.getService(supportedServiceStr);
 +                if (service == null) {
 +                    throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr);
 +                } else {
 +                    suppportedServices[i] = service;
 +                }
 +                i++;
 +            }
 +
 +            for (NetworkVO network : networksToReturn) {
 +                if (areServicesSupportedInNetwork(network.getId(), suppportedServices)) {
 +                    supportedNetworks.add(network);
 +                }
 +            }
 +
 +            networksToReturn = supportedNetworks;
 +        }
 +
 +        if (canUseForDeploy != null) {
 +            List<NetworkVO> networksForDeploy = new ArrayList<NetworkVO>();
 +            for (NetworkVO network : networksToReturn) {
 +                if (_networkModel.canUseForDeploy(network) == canUseForDeploy) {
 +                    networksForDeploy.add(network);
 +                }
 +            }
 +
 +            networksToReturn = networksForDeploy;
 +        }
 +
 +        //Now apply pagination
 +        List<? extends Network> wPagination = StringUtils.applyPagination(networksToReturn, cmd.getStartIndex(), cmd.getPageSizeVal());
 +        if (wPagination != null) {
 +            Pair<List<? extends Network>, Integer> listWPagination = new Pair<List<? extends Network>, Integer>(wPagination, networksToReturn.size());
 +            return listWPagination;
 +        }
 +
 +        return new Pair<List<? extends Network>, Integer>(networksToReturn, networksToReturn.size());
 +    }
 +
 +    private SearchCriteria<NetworkVO> buildNetworkSearchCriteria(SearchBuilder<NetworkVO> sb, String keyword, Long id, Boolean isSystem, Long zoneId, String guestIpType,
 +            String trafficType, Long physicalNetworkId, String aclType, boolean skipProjectNetworks, Boolean restartRequired, Boolean specifyIpRanges, Long vpcId,
 +            Map<String, String> tags, Boolean display) {
 +
 +        SearchCriteria<NetworkVO> sc = sb.create();
 +
 +        if (isSystem != null) {
 +            sc.setJoinParameters("networkOfferingSearch", "systemOnly", isSystem);
 +        }
 +
 +        if (keyword != null) {
 +            SearchCriteria<NetworkVO> ssc = _networksDao.createSearchCriteria();
 +            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
 +            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
 +        }
 +
 +        if (display != null) {
 +            sc.addAnd("displayNetwork", SearchCriteria.Op.EQ, display);
 +        }
 +
 +        if (id != null) {
 +            sc.addAnd("id", SearchCriteria.Op.EQ, id);
 +        }
 +
 +        if (zoneId != null) {
 +            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
 +        }
 +
 +        if (guestIpType != null) {
 +            sc.addAnd("guestType", SearchCriteria.Op.EQ, guestIpType);
 +        }
 +
 +        if (trafficType != null) {
 +            sc.addAnd("trafficType", SearchCriteria.Op.EQ, trafficType);
 +        }
 +
 +        if (aclType != null) {
 +            sc.addAnd("aclType", SearchCriteria.Op.EQ, aclType.toString());
 +        }
 +
 +        if (physicalNetworkId != null) {
 +            sc.addAnd("physicalNetworkId", SearchCriteria.Op.EQ, physicalNetworkId);
 +        }
 +
 +        if (skipProjectNetworks) {
 +            sc.setJoinParameters("accountSearch", "typeNEQ", Account.ACCOUNT_TYPE_PROJECT);
 +        } else {
 +            sc.setJoinParameters("accountSearch", "typeEQ", Account.ACCOUNT_TYPE_PROJECT);
 +        }
 +
 +        if (restartRequired != null) {
 +            sc.addAnd("restartRequired", SearchCriteria.Op.EQ, restartRequired);
 +        }
 +
 +        if (specifyIpRanges != null) {
 +            sc.addAnd("specifyIpRanges", SearchCriteria.Op.EQ, specifyIpRanges);
 +        }
 +
 +        if (vpcId != null) {
 +            sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId);
 +        }
 +
 +        if (tags != null && !tags.isEmpty()) {
 +            int count = 0;
 +            sc.setJoinParameters("tagSearch", "resourceType", ResourceObjectType.Network.toString());
 +            for ( Map.Entry<String,String> entry: tags.entrySet()) {
 +                sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), entry.getKey());
 +                sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), entry.getValue());
 +                count++;
 +            }
 +        }
 +
 +        return sc;
 +    }
 +
 +    private List<NetworkVO> listDomainLevelNetworks(SearchCriteria<NetworkVO> sc, Filter searchFilter, long domainId, boolean parentDomainsOnly) {
 +        List<Long> networkIds = new ArrayList<Long>();
 +        Set<Long> allowedDomains = _domainMgr.getDomainParentIds(domainId);
 +        List<NetworkDomainVO> maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray());
 +
 +        for (NetworkDomainVO map : maps) {
 +            if (map.getDomainId() == domainId && parentDomainsOnly) {
 +                continue;
 +            }
 +            boolean subdomainAccess = (map.isSubdomainAccess() != null) ? map.isSubdomainAccess() : getAllowSubdomainAccessGlobal();
 +            if (map.getDomainId() == domainId || subdomainAccess) {
 +                networkIds.add(map.getNetworkId());
 +            }
 +        }
 +
 +        if (!networkIds.isEmpty()) {
 +            SearchCriteria<NetworkVO> domainSC = _networksDao.createSearchCriteria();
 +            domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray());
 +            domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString());
 +
 +            sc.addAnd("id", SearchCriteria.Op.SC, domainSC);
 +            return _networksDao.search(sc, searchFilter);
 +        } else {
 +            return new ArrayList<NetworkVO>();
 +        }
 +    }
 +
 +    private List<NetworkVO> listAccountSpecificNetworks(SearchCriteria<NetworkVO> sc, Filter searchFilter, List<Long> permittedAccounts) {
 +        SearchCriteria<NetworkVO> accountSC = _networksDao.createSearchCriteria();
 +        if (!permittedAccounts.isEmpty()) {
 +            accountSC.addAnd("accountId", SearchCriteria.Op.IN, permittedAccounts.toArray());
 +        }
 +
 +        accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString());
 +
 +        sc.addAnd("id", SearchCriteria.Op.SC, accountSC);
 +        return _networksDao.search(sc, searchFilter);
 +    }
 +
 +    private List<NetworkVO> listAccountSpecificNetworksByDomainPath(SearchCriteria<NetworkVO> sc, Filter searchFilter, String path, boolean isRecursive) {
 +        SearchCriteria<NetworkVO> accountSC = _networksDao.createSearchCriteria();
 +        accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString());
 +
 +        if (path != null) {
 +            if (isRecursive) {
 +                sc.setJoinParameters("domainSearch", "path", path + "%");
 +            } else {
 +                sc.setJoinParameters("domainSearch", "path", path);
 +            }
 +        }
 +
 +        sc.addAnd("id", SearchCriteria.Op.SC, accountSC);
 +        return _networksDao.search(sc, searchFilter);
 +    }
 +
 +    private List<NetworkVO> listDomainSpecificNetworksByDomainPath(SearchCriteria<NetworkVO> sc, Filter searchFilter, String path, boolean isRecursive) {
 +
 +        Set<Long> allowedDomains = new HashSet<Long>();
 +        if (path != null) {
 +            if (isRecursive) {
 +                allowedDomains = _domainMgr.getDomainChildrenIds(path);
 +            } else {
 +                Domain domain = _domainDao.findDomainByPath(path);
 +                allowedDomains.add(domain.getId());
 +            }
 +        }
 +
 +        List<Long> networkIds = new ArrayList<Long>();
 +
 +        List<NetworkDomainVO> maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray());
 +
 +        for (NetworkDomainVO map : maps) {
 +            networkIds.add(map.getNetworkId());
 +        }
 +
 +        if (!networkIds.isEmpty()) {
 +            SearchCriteria<NetworkVO> domainSC = _networksDao.createSearchCriteria();
 +            domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray());
 +            domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString());
 +
 +            sc.addAnd("id", SearchCriteria.Op.SC, domainSC);
 +        return _networksDao.search(sc, searchFilter);
 +        } else {
 +            return new ArrayList<NetworkVO>();
 +        }
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NETWORK_DELETE, eventDescription = "deleting network", async = true)
 +    public boolean deleteNetwork(long networkId, boolean forced) {
 +
 +        Account caller = CallContext.current().getCallingAccount();
 +
 +        // Verify network id
 +        NetworkVO network = _networksDao.findById(networkId);
 +        if (network == null) {
 +            // see NetworkVO.java
 +
 +            throwInvalidIdException("unable to find network with specified id", String.valueOf(networkId), "networkId");
 +        }
 +
 +        // don't allow to delete system network
 +        if (isNetworkSystem(network)) {
 +            throwInvalidIdException("Network with specified id is system and can't be removed", network.getUuid(), "networkId");
 +        }
 +
 +        Account owner = _accountMgr.getAccount(network.getAccountId());
 +
 +        // Only Admin can delete Shared and L2 networks
 +        if ((network.getGuestType() == GuestType.Shared || network.getGuestType() == GuestType.L2) && !_accountMgr.isAdmin(caller.getId())) {
 +            throw new InvalidParameterValueException("Only Admins can delete network with guest type " + network.getGuestType());
 +        }
 +
 +        // Perform permission check
 +        _accountMgr.checkAccess(caller, null, true, network);
 +
 +        if (forced && !_accountMgr.isRootAdmin(caller.getId())) {
 +            throw new InvalidParameterValueException("Delete network with 'forced' option can only be called by root admins");
 +        }
 +
 +        User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId());
 +        ReservationContext context = new ReservationContextImpl(null, null, callerUser, owner);
 +
 +        return _networkMgr.destroyNetwork(networkId, context, forced);
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true)
-     public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
++    public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup, boolean makeRedundant) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
 +        // This method restarts all network elements belonging to the network and re-applies all the rules
 +        Long networkId = cmd.getNetworkId();
 +
 +        User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId());
 +        Account callerAccount = _accountMgr.getActiveAccountById(callerUser.getAccountId());
 +
 +        // Check if network exists
 +        NetworkVO network = _networksDao.findById(networkId);
 +        if (network == null) {
 +            throwInvalidIdException("Network with specified id doesn't exist", networkId.toString(), "networkId");
 +        }
 +
 +        // Don't allow to restart network if it's not in Implemented/Setup state
 +        if (!(network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup)) {
 +            throw new InvalidParameterValueException("Network is not in the right state to be restarted. Correct states are: " + Network.State.Implemented + ", "
 +                    + Network.State.Setup);
 +        }
 +
 +        if (network.getBroadcastDomainType() == BroadcastDomainType.Lswitch) {
 +            /**
 +             * Unable to restart these networks now.
 +             * TODO Restarting a SDN based network requires updating the nics and the configuration
 +             * in the controller. This requires a non-trivial rewrite of the restart procedure.
 +             */
 +            throw new InvalidParameterException("Unable to restart a running SDN network.");
 +        }
 +
 +        _accountMgr.checkAccess(callerAccount, null, true, network);
 +
++        if (!network.isRedundant() && makeRedundant) {
++            network.setRedundant(true);
++            if (!_networksDao.update(network.getId(), network)) {
++                throw new CloudRuntimeException("Failed to update network into a redundant one, please try again");
++            }
++            cleanup = true;
++        }
++
 +        boolean success = _networkMgr.restartNetwork(networkId, callerAccount, callerUser, cleanup);
 +
 +        if (success) {
 +            s_logger.debug("Network id=" + networkId + " is restarted successfully.");
 +        } else {
 +            s_logger.warn("Network id=" + networkId + " failed to restart.");
 +        }
 +
 +        return success;
 +    }
 +
 +    @Override
 +    public int getActiveNicsInNetwork(long networkId) {
 +        return _networksDao.getActiveNicsIn(networkId);
 +    }
 +
 +    @Override
 +    public Map<Capability, String> getNetworkOfferingServiceCapabilities(NetworkOffering offering, Service service) {
 +
 +        if (!areServicesSupportedByNetworkOffering(offering.getId(), service)) {
 +            // TBD: We should be sending networkOfferingId and not the offering object itself.
 +            throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the network offering " + offering);
 +        }
 +
 +        Map<Capability, String> serviceCapabilities = new HashMap<Capability, String>();
 +
 +        // get the Provider for this Service for this offering
 +        List<String> providers = _ntwkOfferingSrvcDao.listProvidersForServiceForNetworkOffering(offering.getId(), service);
 +        if (providers.isEmpty()) {
 +            // TBD: We should be sending networkOfferingId and not the offering object itself.
 +            throw new InvalidParameterValueException("Service " + service.getName() + " is not supported by the network offering " + offering);
 +        }
 +
 +        // FIXME - in post 3.0 we are going to support multiple providers for the same service per network offering, so
 +        // we have to calculate capabilities for all of them
 +        String provider = providers.get(0);
 +
 +        // FIXME we return the capabilities of the first provider of the service - what if we have multiple providers
 +        // for same Service?
 +        NetworkElement element = _networkModel.getElementImplementingProvider(provider);
 +        if (element != null) {
 +            Map<Service, Map<Capability, String>> elementCapabilities = element.getCapabilities();
 +            ;
 +
 +            if (elementCapabilities == null || !elementCapabilities.containsKey(service)) {
 +                // TBD: We should be sending providerId and not the offering object itself.
 +                throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the element=" + element.getName() + " implementing Provider="
 +                        + provider);
 +            }
 +            serviceCapabilities = elementCapabilities.get(service);
 +        }
 +
 +        return serviceCapabilities;
 +    }
 +
 +    @Override
 +    public IpAddress getIp(long ipAddressId) {
 +        return _ipAddressDao.findById(ipAddressId);
 +    }
 +
 +    protected boolean providersConfiguredForExternalNetworking(Collection<String> providers) {
 +        for (String providerStr : providers) {
 +            Provider provider = Network.Provider.getProvider(providerStr);
 +            if (provider.isExternal()) {
 +                return true;
 +            }
 +        }
 +        return false;
 +    }
 +
 +    protected boolean isSharedNetworkOfferingWithServices(long networkOfferingId) {
 +        NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId);
 +        if ((networkOffering.getGuestType() == Network.GuestType.Shared)
 +                && (areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) || areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat)
 +                        || areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall)
 +                        || areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || areServicesSupportedByNetworkOffering(networkOfferingId, Service.Lb))) {
 +            return true;
 +        }
 +        return false;
 +    }
 +
 +    protected boolean areServicesSupportedByNetworkOffering(long networkOfferingId, Service... services) {
 +        return (_ntwkOfferingSrvcDao.areServicesSupportedByNetworkOffering(networkOfferingId, services));
 +    }
 +
 +    protected boolean areServicesSupportedInNetwork(long networkId, Service... services) {
 +        return (_ntwkSrvcDao.areServicesSupportedInNetwork(networkId, services));
 +    }
 +
 +    private boolean checkForNonStoppedVmInNetwork(long networkId) {
 +        List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(networkId, VirtualMachine.State.Starting, VirtualMachine.State.Running, VirtualMachine.State.Migrating,
 +                VirtualMachine.State.Stopping);
 +        return vms.isEmpty();
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription = "updating network", async = true)
 +    public Network updateGuestNetwork(final long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix,
 +            final Long networkOfferingId, Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String customId, boolean updateInSequence, boolean forced) {
 +        boolean restartNetwork = false;
 +
 +        // verify input parameters
 +        final NetworkVO network = _networksDao.findById(networkId);
 +        if (network == null) {
 +            // see NetworkVO.java
 +            throwInvalidIdException("Specified network id doesn't exist in the system", String.valueOf(networkId), "networkId");
 +        }
 +
 +        //perform below validation if the network is vpc network
 +        if (network.getVpcId() != null && networkOfferingId != null) {
 +            Vpc vpc = _entityMgr.findById(Vpc.class, network.getVpcId());
 +            _vpcMgr.validateNtwkOffForNtwkInVpc(networkId, networkOfferingId, null, null, vpc, null, _accountMgr.getAccount(network.getAccountId()), network.getNetworkACLId());
 +        }
 +
 +        // don't allow to update network in Destroy state
 +        if (network.getState() == Network.State.Destroy) {
 +            throw new InvalidParameterValueException("Don't allow to update network in state " + Network.State.Destroy);
 +        }
 +
 +        // Don't allow to update system network
 +        NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());
 +        if (offering.isSystemOnly()) {
 +            throw new InvalidParameterValueException("Can't update system networks");
 +        }
 +
 +        // allow to upgrade only Guest networks
 +        if (network.getTrafficType() != Networks.TrafficType.Guest) {
 +            throw new InvalidParameterValueException("Can't allow networks which traffic type is not " + TrafficType.Guest);
 +        }
 +
 +        _accountMgr.checkAccess(callerAccount, null, true, network);
 +
 +        if (name != null) {
 +            network.setName(name);
 +        }
 +
 +        if (displayText != null) {
 +            network.setDisplayText(displayText);
 +        }
 +
 +        if (customId != null) {
 +            network.setUuid(customId);
 +        }
 +
 +        // display flag is not null and has changed
 +        if (displayNetwork != null && displayNetwork != network.getDisplayNetwork()) {
 +            // Update resource count if it needs to be updated
 +            NetworkOffering networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
 +            if (_networkMgr.resourceCountNeedsUpdate(networkOffering, network.getAclType())) {
 +                _resourceLimitMgr.changeResourceCount(network.getAccountId(), Resource.ResourceType.network, displayNetwork);
 +            }
 +
 +            network.setDisplayNetwork(displayNetwork);
 +        }
 +
 +        // network offering and domain suffix can be updated for Isolated networks only in 3.0
 +        if ((networkOfferingId != null || domainSuffix != null) && network.getGuestType() != GuestType.Isolated) {
 +            throw new InvalidParameterValueException("NetworkOffering and domain suffix upgrade can be perfomed for Isolated networks only");
 +        }
 +
 +        boolean networkOfferingChanged = false;
 +
 +        final long oldNetworkOfferingId = network.getNetworkOfferingId();
 +        NetworkOffering oldNtwkOff = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId);
 +        NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId);
 +        if (networkOfferingId != null) {
 +            if (networkOffering == null || networkOffering.isSystemOnly()) {
 +                throwInvalidIdException("Unable to find network offering with specified id", networkOfferingId.toString(), "networkOfferingId");
 +            }
 +
 +            // network offering should be in Enabled state
 +            if (networkOffering.getState() != NetworkOffering.State.Enabled) {
 +                throwInvalidIdException("Network offering with specified id is not in " + NetworkOffering.State.Enabled
 +                        + " state, can't upgrade to it", networkOffering.getUuid(), "networkOfferingId");
 +            }
 +            //can't update from vpc to non-vpc network offering
 +            boolean forVpcNew = _configMgr.isOfferingForVpc(networkOffering);
 +            boolean vorVpcOriginal = _configMgr.isOfferingForVpc(_entityMgr.findById(NetworkOffering.class, oldNetworkOfferingId));
 +            if (forVpcNew != vorVpcOriginal) {
 +                String errMsg = forVpcNew ? "a vpc offering " : "not a vpc offering";
 +                throw new InvalidParameterValueException("Can't update as the new offering is " + errMsg);
 +            }
 +
 +            if (networkOfferingId != oldNetworkOfferingId) {
 +                Collection<String> newProviders = _networkMgr.finalizeServicesAndProvidersForNetwork(networkOffering, network.getPhysicalNetworkId()).values();
 +                Collection<String> oldProviders = _networkMgr.finalizeServicesAndProvidersForNetwork(oldNtwkOff, network.getPhysicalNetworkId()).values();
 +
 +                if (providersConfiguredForExternalNetworking(newProviders) != providersConfiguredForExternalNetworking(oldProviders) && !changeCidr) {
 +                    throw new InvalidParameterValueException("Updating network failed since guest CIDR needs to be changed!");
 +                }
 +                if (changeCidr) {
 +                    if (!checkForNonStoppedVmInNetwork(network.getId())) {
 +                        throwInvalidIdException("All user vm of network of specified id should be stopped before changing CIDR!", network.getUuid(), "networkId");
 +                    }
 +                }
 +                // check if the network is upgradable
 +                if (!canUpgrade(network, oldNetworkOfferingId, networkOfferingId)) {
 +                    throw new InvalidParameterValueException("Can't upgrade from network offering " + oldNtwkOff.getUuid() + " to " + networkOffering.getUuid()
 +                            + "; check logs for more information");
 +                }
 +                restartNetwork = true;
 +                networkOfferingChanged = true;
 +
 +                //Setting the new network's isReduntant to the new network offering's RedundantRouter.
 +                network.setRedundant(_networkOfferingDao.findById(networkOfferingId).getRedundantRouter());
 +            }
 +        }
 +
 +        final Map<String, String> newSvcProviders = networkOfferingChanged ? _networkMgr.finalizeServicesAndProvidersForNetwork(
 +                _entityMgr.findById(NetworkOffering.class, networkOfferingId), network.getPhysicalNetworkId()) : new HashMap<String, String>();
 +
 +        // don't allow to modify network domain if the service is not supported
 +        if (domainSuffix != null) {
 +            // validate network domain
 +            if (!NetUtils.verifyDomainName(domainSuffix)) {
 +                throw new InvalidParameterValueException(
 +                        "Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
 +                                + "and the hyphen ('-'); can't start or end with \"-\"");
 +            }
 +
 +            long offeringId = oldNetworkOfferingId;
 +            if (networkOfferingId != null) {
 +                offeringId = networkOfferingId;
 +            }
 +
 +            Map<Network.Capability, String> dnsCapabilities = getNetworkOfferingServiceCapabilities(_entityMgr.findById(NetworkOffering.class, offeringId), Service.Dns);
 +            String isUpdateDnsSupported = dnsCapabilities.get(Capability.AllowDnsSuffixModification);
 +            if (isUpdateDnsSupported == null || !Boolean.valueOf(isUpdateDnsSupported)) {
 +                // TBD: use uuid instead of networkOfferingId. May need to hardcode tablename in call to addProxyObject().
 +                throw new InvalidParameterValueException("Domain name change is not supported by the network offering id=" + networkOfferingId);
 +            }
 +
 +            network.setNetworkDomain(domainSuffix);
 +            // have to restart the network
 +            restartNetwork = true;
 +        }
 +
 +        //IP reservation checks
 +        // allow reservation only to Isolated Guest networks
 +        DataCenter dc = _dcDao.findById(network.getDataCenterId());
 +        String networkCidr = network.getNetworkCidr();
 +
 +        if (guestVmCidr != null) {
 +            if (dc.getNetworkType() == NetworkType.Basic) {
 +                throw new InvalidParameterValueException("Guest VM CIDR can't be specified for zone with " + NetworkType.Basic  + " networking");
 +            }
 +            if (network.getGuestType() != GuestType.Isolated) {
 +                throw new InvalidParameterValueException("Can only allow IP Reservation in networks with guest type " + GuestType.Isolated);
 +            }
 +            if (networkOfferingChanged) {
 +                throw new InvalidParameterValueException("Cannot specify this nework offering change and guestVmCidr at same time. Specify only one.");
 +            }
 +            if (!(network.getState() == Network.State.Implemented)) {
 +                throw new InvalidParameterValueException("The network must be in " + Network.State.Implemented + " state. IP Reservation cannot be applied in "
 +                        + network.getState() + " state");
 +            }
 +            if (!NetUtils.isValidIp4Cidr(guestVmCidr)) {
 +                throw new InvalidParameterValueException("Invalid format of Guest VM CIDR.");
 +            }
 +            if (!NetUtils.validateGuestCidr(guestVmCidr)) {
 +                throw new InvalidParameterValueException("Invalid format of Guest VM CIDR. Make sure it is RFC1918 compliant. ");
 +            }
 +
 +            // If networkCidr is null it implies that there was no prior IP reservation, so the network cidr is network.getCidr()
 +            // But in case networkCidr is a non null value (IP reservation already exists), it implies network cidr is networkCidr
 +            if (networkCidr != null) {
 +                if (!NetUtils.isNetworkAWithinNetworkB(guestVmCidr, networkCidr)) {
 +                    throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR  should be a subset of network CIDR : "
 +                            + networkCidr);
 +                }
 +            } else {
 +                if (!NetUtils.isNetworkAWithinNetworkB(guestVmCidr, network.getCidr())) {
 +                    throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR  should be a subset of network CIDR :  "
 +                            + network.getCidr());
 +                }
 +            }
 +
 +            // This check makes sure there are no active IPs existing outside the guestVmCidr in the network
 +                String[] guestVmCidrPair = guestVmCidr.split("\\/");
 +                Long size = Long.valueOf(guestVmCidrPair[1]);
 +                List<NicVO> nicsPresent = _nicDao.listByNetworkId(networkId);
 +
 +                String cidrIpRange[] = NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], size);
 +            s_logger.info("The start IP of the specified guest vm cidr is: " + cidrIpRange[0] + " and end IP is: " + cidrIpRange[1]);
 +                long startIp = NetUtils.ip2Long(cidrIpRange[0]);
 +                long endIp = NetUtils.ip2Long(cidrIpRange[1]);
 +                long range =  endIp - startIp + 1;
 +                s_logger.info("The specified guest vm cidr has " +  range + " IPs");
 +
 +                for (NicVO nic : nicsPresent) {
 +                    long nicIp = NetUtils.ip2Long(nic.getIPv4Address());
 +                    //check if nic IP is outside the guest vm cidr
 +                    if ((nicIp < startIp || nicIp > endIp) && nic.getState() != Nic.State.Deallocating) {
 +                            throw new InvalidParameterValueException("Active IPs like " + nic.getIPv4Address() + " exist outside the Guest VM CIDR. Cannot apply reservation ");
 +                    }
 +                }
 +
 +                // In some scenarios even though guesVmCidr and network CIDR do not appear similar but
 +                // the IP ranges exactly matches, in these special cases make sure no Reservation gets applied
 +                if (network.getNetworkCidr() == null) {
 +                    if (NetUtils.isSameIpRange(guestVmCidr, network.getCidr()) && !guestVmCidr.equals(network.getCidr())) {
 +                    throw new InvalidParameterValueException("The Start IP and End IP of guestvmcidr: " + guestVmCidr + " and CIDR: " + network.getCidr() + " are same, "
 +                            + "even though both the cidrs appear to be different. As a precaution no IP Reservation will be applied.");
 +                    }
 +                } else {
 +                if (NetUtils.isSameIpRange(guestVmCidr, network.getNetworkCidr()) && !guestVmCidr.equals(network.getNetworkCidr())) {
 +                    throw new InvalidParameterValueException("The Start IP and End IP of guestvmcidr: " + guestVmCidr + " and Network CIDR: " + network.getNetworkCidr()
 +                            + " are same, "
 +                            + "even though both the cidrs appear to be different. As a precaution IP Reservation will not be affected. If you want to reset IP Reservation, "
 +                            + "specify guestVmCidr to be: " + network.getNetworkCidr());
 +                    }
 +                }
 +
 +                // When reservation is applied for the first time, network_cidr will be null
 +                // Populate it with the actual network cidr
 +                if (network.getNetworkCidr() == null) {
 +                    network.setNetworkCidr(network.getCidr());
 +                }
 +
 +                // Condition for IP Reservation reset : guestVmCidr and network CIDR are same
 +                if (network.getNetworkCidr().equals(guestVmCidr)) {
 +                    s_logger.warn("Guest VM CIDR and Network CIDR both are same, reservation will reset.");
 +                    network.setNetworkCidr(null);
 +                }
 +                // Finally update "cidr" with the guestVmCidr
 +                // which becomes the effective address space for CloudStack guest VMs
 +                network.setCidr(guestVmCidr);
 +                _networksDao.update(networkId, network);
 +                s_logger.info("IP Reservation has been applied. The new CIDR for Guests Vms is " + guestVmCidr);
 +            }
 +
 +        ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount);
 +        // 1) Shutdown all the elements and cleanup all the rules. Don't allow to shutdown network in intermediate
 +        // states - Shutdown and Implementing
 +        int resourceCount=1;
 +        if (updateInSequence && restartNetwork && _networkOfferingDao.findById(network.getNetworkOfferingId()).getRedundantRouter()
 +                && (networkOfferingId==null || _networkOfferingDao.findById(networkOfferingId).getRedundantRouter()) && network.getVpcId()==null) {
 +            _networkMgr.canUpdateInSequence(network, forced);
 +            NetworkDetailVO networkDetail =new NetworkDetailVO(network.getId(),Network.updatingInSequence,"true",true);
 +            _networkDetailsDao.persist(networkDetail);
 +            _networkMgr.configureUpdateInSequence(network);
 +            resourceCount=_networkMgr.getResourceCount(network);
 +        }
 +        List<String > servicesNotInNewOffering = null;
 +        if (networkOfferingId != null) {
 +            servicesNotInNewOffering = _networkMgr.getServicesNotSupportedInNewOffering(network, networkOfferingId);
 +        }
 +        if (!forced && servicesNotInNewOffering != null && !servicesNotInNewOffering.isEmpty()) {
 +            NetworkOfferingVO newOffering = _networkOfferingDao.findById(networkOfferingId);
 +            throw new CloudRuntimeException("The new offering:"+newOffering.getUniqueName()
 +                    +" will remove the following services "+servicesNotInNewOffering +"along with all the related configuration currently in use. will not proceed with the network update." +
 +                    "set forced parameter to true for forcing an update.");
 +        }
 +        try {
 +            if (servicesNotInNewOffering!=null && !servicesNotInNewOffering.isEmpty()) {
 +                _networkMgr.cleanupConfigForServicesInNetwork(servicesNotInNewOffering,network);
 +            }
 +        } catch (Throwable e) {
 +            s_logger.debug("failed to cleanup config related to unused services error:"+e.getMessage());
 +        }
 +
 +        boolean validStateToShutdown = (network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup || network.getState() == Network.State.Allocated);
 +        try {
 +
 +            do {
 +                if (restartNetwork) {
 +                    if (validStateToShutdown) {
 +                        if (!changeCidr) {
 +                            s_logger.debug("Shutting down elements and resources for network id=" + networkId + " as a part of network update");
 +
 +                            if (!_networkMgr.shutdownNetworkElementsAndResources(context, true, network)) {
 +                                s_logger.warn("Failed to shutdown the network elements and resources as a part of network restart: " + network);
 +                                CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network of specified id");
 +                                ex.addProxyObject(network.getUuid(), "networkId");
 +                                throw ex;
 +                            }
 +                        } else {
 +                            // We need to shutdown the network, since we want to re-implement the network.
 +                            s_logger.debug("Shutting down network id=" + networkId + " as a part of network update");
 +
 +                            //check if network has reservation
 +                            if (NetUtils.isNetworkAWithinNetworkB(network.getCidr(), network.getNetworkCidr())) {
 +                                s_logger.warn("Existing IP reservation will become ineffective for the network with id =  " + networkId
 +                                        + " You need to reapply reservation after network reimplementation.");
 +                                //set cidr to the newtork cidr
 +                                network.setCidr(network.getNetworkCidr());
 +                                //set networkCidr to null to bring network back to no IP reservation state
 +                                network.setNetworkCidr(null);
 +                            }
 +
 +                            if (!_networkMgr.shutdownNetwork(network.getId(), context, true)) {
 +                                s_logger.warn("Failed to shutdown the network as a part of update to network with specified id");
 +                                CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network as a part of update of specified network id");
 +                                ex.addProxyObject(network.getUuid(), "networkId");
 +                                throw ex;
 +                            }
 +                        }
 +                    } else {
 +                        CloudRuntimeException ex = new CloudRuntimeException(
 +                                "Failed to shutdown the network elements and resources as a part of update to network with specified id; network is in wrong state: " + network.getState());
 +                        ex.addProxyObject(network.getUuid(), "networkId");
 +                        throw ex;
 +                    }
 +                }
 +
 +                // 2) Only after all the elements and rules are shutdown properly, update the network VO
 +                // get updated network
 +                Network.State networkState = _networksDao.findById(networkId).getState();
 +                boolean validStateToImplement = (networkState == Network.State.Implemented || networkState == Network.State.Setup || networkState == Network.State.Allocated);
 +                if (restartNetwork && !validStateToImplement) {
 +                    CloudRuntimeException ex = new CloudRuntimeException(
 +                            "Failed to implement the network elements and resources as a part of update to network with specified id; network is in wrong state: " + networkState);
 +                    ex.addProxyObject(network.getUuid(), "networkId");
 +                    throw ex;
 +                }
 +
 +                if (networkOfferingId != null) {
 +                    if (networkOfferingChanged) {
 +                        Transaction.execute(new TransactionCallbackNoReturn() {
 +                            @Override
 +                            public void doInTransactionWithoutResult(TransactionStatus status) {
 +                                network.setNetworkOfferingId(networkOfferingId);
 +                                _networksDao.update(networkId, network, newSvcProviders);
 +                                // get all nics using this network
 +                                // log remove usage events for old offering
 +                                // log assign usage events for new offering
 +                                List<NicVO> nics = _nicDao.listByNetworkId(networkId);
 +                                for (NicVO nic : nics) {
 +                                    long vmId = nic.getInstanceId();
 +                                    VMInstanceVO vm = _vmDao.findById(vmId);
 +                                    if (vm == null) {
 +                                        s_logger.error("Vm for nic " + nic.getId() + " not found with Vm Id:" + vmId);
 +                                        continue;
 +                                    }
 +                                    long isDefault = (nic.isDefaultNic()) ? 1 : 0;
 +                                    String nicIdString = Long.toString(nic.getId());
 +                                    UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString,
 +                                            oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay());
 +                                    UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString,
 +                                            networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay());
 +                                }
 +                            }
 +                        });
 +                    } else {
 +                        network.setNetworkOfferingId(networkOfferingId);
 +                        _networksDao.update(networkId, network,
 +                                _networkMgr.finalizeServicesAndProvidersForNetwork(_entityMgr.findById(NetworkOffering.class, networkOfferingId), network.getPhysicalNetworkId()));
 +                    }
 +                } else {
 +                    _networksDao.update(networkId, network);
 +                }
 +
 +                // 3) Implement the elements and rules again
 +                if (restartNetwork) {
 +                    if (network.getState() != Network.State.Allocated) {
 +                        DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
 +                        s_logger.debug("Implementing the network " + network + " elements and resources as a part of network update");
 +                        try {
 +                            if (!changeCidr) {
 +                                _networkMgr.implementNetworkElementsAndResources(dest, context, network, _networkOfferingDao.findById(network.getNetworkOfferingId()));
 +                            } else {
 +                                _networkMgr.implementNetwork(network.getId(), dest, context);
 +                            }
 +                        } catch (Exception ex) {
 +                            s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network update due to ", ex);
 +                            CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id) elements and resources as a part of network update");
 +                            e.addProxyObject(network.getUuid(), "networkId");
 +                            throw e;
 +                        }
 +                    }
 +                }
 +
 +                // 4) if network has been upgraded from a non persistent ntwk offering to a persistent ntwk offering,
 +                // implement the network if its not already
 +                if (networkOfferingChanged && !oldNtwkOff.getIsPersistent() && networkOffering.getIsPersistent()) {
 +                    if (network.getState() == Network.State.Allocated) {
 +                        try {
 +                            DeployDestination dest = new DeployDestination(_dcDao.findById(network.getDataCenterId()), null, null, null);
 +                            _networkMgr.implementNetwork(network.getId(), dest, context);
 +                        } catch (Exception ex) {
 +                            s_logger.warn("Failed to implement network " + network + " elements and resources as a part o" + "f network update due to ", ex);
 +                            CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified" + " id) elements and resources as a part of network update");
 +                            e.addProxyObject(network.getUuid(), "networkId");
 +                            throw e;
 +                        }
 +                    }
 +                }
 +                resourceCount--;
 +            } while (updateInSequence && resourceCount>0);
 +        } catch (Exception exception) {
 +             if (updateInSequence) {
 +                 _networkMgr.finalizeUpdateInSequence(network, false);
 +             }
 +             throw new CloudRuntimeException("failed to update network "+network.getUuid()+" due to "+exception.getMessage());
 +        } finally {
 +            if (updateInSequence) {
 +                if( _networkDetailsDao.findDetail(networkId,Network.updatingInSequence)!=null){
 +                    _networkDetailsDao.removeDetail(networkId,Network.updatingInSequence);
 +                }
 +            }
 +        }
 +        return getNetwork(network.getId());
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NETWORK_MIGRATE, eventDescription = "migrating network", async = true)
 +    public Network migrateGuestNetwork(long networkId, long networkOfferingId, Account callerAccount, User callerUser, boolean resume) {
 +        NetworkVO network = _networksDao.findById(networkId);
 +        NetworkOffering newNtwkOff = _networkOfferingDao.findById(networkOfferingId);
 +
 +        //perform below validation if the network is vpc network
 +        if (network.getVpcId() != null) {
 +            s_logger.warn("Failed to migrate network as the specified network is a vpc tier. Use migrateVpc.");
 +            throw new InvalidParameterValueException("Failed to migrate network as the specified network is a vpc tier. Use migrateVpc.");
 +        }
 +
 +        if (_configMgr.isOfferingForVpc(newNtwkOff)) {
 +            s_logger.warn("Failed to migrate network as the specified network offering is a VPC offering");
 +            throw new InvalidParameterValueException("Failed to migrate network as the specified network offering is a VPC offering");
 +        }
 +
 +        verifyNetworkCanBeMigrated(callerAccount, network);
 +
 +        //Retrieve new Physical NetworkId
 +        long newPhysicalNetworkId = findPhysicalNetworkId(network.getDataCenterId(), newNtwkOff.getTags(), newNtwkOff.getTrafficType());
 +
 +        final long oldNetworkOfferingId = network.getNetworkOfferingId();
 +        NetworkOffering oldNtwkOff = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId);
 +
 +        if (!resume && network.getRelated() != network.getId()) {
 +            s_logger.warn("Related network is not equal to network id. You might want to re-run migration with resume = true command.");
 +            throw new CloudRuntimeException("Failed to migrate network as previous migration left this network in transient condition. Specify resume as true.");
 +        }
 +
 +        if (networkNeedsMigration(network, newPhysicalNetworkId, oldNtwkOff, newNtwkOff)) {
 +            return migrateNetworkToPhysicalNetwork(network, oldNtwkOff, newNtwkOff, null, null, newPhysicalNetworkId, callerAccount, callerUser);
 +        } else {
 +            s_logger.info("Network does not need migration.");
 +            return network;
 +        }
 +    }
 +
 +    private class NetworkCopy {
 +        private Long networkIdInOldPhysicalNet;
 +        private Network networkInNewPhysicalNet;
 +
 +        public NetworkCopy(Long networkIdInOldPhysicalNet, Network networkInNewPhysicalNet) {
 +            this.networkIdInOldPhysicalNet = networkIdInOldPhysicalNet;
 +            this.networkInNewPhysicalNet = networkInNewPhysicalNet;
 +        }
 +
 +        public Long getNetworkIdInOldPhysicalNet() {
 +            return networkIdInOldPhysicalNet;
 +        }
 +
 +        public Network getNetworkInNewPhysicalNet() {
 +            return networkInNewPhysicalNet;
 +        }
 +    }
 +
 +    private Network migrateNetworkToPhysicalNetwork(Network network, NetworkOffering oldNtwkOff, NetworkOffering newNtwkOff, Long oldVpcId, Long newVpcId, long newPhysicalNetworkId, Account callerAccount, User callerUser) {
 +        boolean resume = network.getRelated() != network.getId();
 +
 +        NetworkCopy networkCopy;
 +
 +        // Resume is only true when there is already a copy of the network created
 +        if (resume) {
 +            Network networkInNewPhysicalNet = network;
 +            networkCopy = new NetworkCopy(network.getRelated(), networkInNewPhysicalNet);
 +
 +            //the new network could already be implemented, check if the already partially upgrade networks has the same network offering as before or check if it still has the original network offering
 +            //the old network offering uuid should be the one of the already created copy
 +            if (networkInNewPhysicalNet.getNetworkOfferingId() != newNtwkOff.getId()) {
 +                throw new InvalidParameterValueException("Failed to resume migrating network as network offering does not match previously specified network offering (" + newNtwkOff.getUuid() + ")");
 +            }
 +        } else {
 +            networkCopy = Transaction.execute(
 +                    (TransactionCallback<NetworkCopy>)
 +                            (status) -> migrateNetworkInDb(network, oldNtwkOff, newNtwkOff, oldVpcId, newVpcId, newPhysicalNetworkId));
 +        }
 +
 +        Long networkIdInOldPhysicalNet = networkCopy.getNetworkIdInOldPhysicalNet();
 +        Network networkInNewPhysicalNet = networkCopy.getNetworkInNewPhysicalNet();
 +
 +        ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount);
 +        DataCenter zone = _dcDao.findById(network.getDataCenterId());
 +        NetworkVO networkInOldPhysNet = _networksDao.findById(networkIdInOldPhysicalNet);
 +
 +        boolean shouldImplement = (newNtwkOff.getIsPersistent()
 +                    || networkInOldPhysNet.getState() == Network.State.Implemented)
 +                && networkInNewPhysicalNet.getState() != Network.State.Implemented;
 +
 +        if (shouldImplement) {
 +            DeployDestination dest = new DeployDestination(zone, null, null, null);
 +            s_logger.debug("Implementing the network " + network + " elements and resources as a part of network update");
 +            try {
 +                networkInNewPhysicalNet = _networkMgr.implementNetwork(networkInNewPhysicalNet.getId(), dest, context)
 +                                                     .second();
 +            } catch (Exception ex) {
 +                s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network update due to ", ex);
 +                CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id) elements and resources as a part of network update");
 +                e.addProxyObject(network.getUuid(), "networkId");
 +                throw e;
 +            }
 +        }
 +
 +        _networkMigrationManager.assignNicsToNewPhysicalNetwork(networkInOldPhysNet, networkInNewPhysicalNet);
 +        //clean up the old copy of the network
 +        _networkMigrationManager.deleteCopyOfNetwork(networkIdInOldPhysicalNet, networkInNewPhysicalNet.getId());
 +
 +        return getNetwork(network.getId());
 +    }
 +
 +    private NetworkCopy migrateNetworkInDb(Network network, NetworkOffering oldNtwkOff, NetworkOffering newNtwkOff, Long oldVpcId, Long newVpcId, long newPhysicalNetworkId) {
 +        //The copy will be the network in the old physical network
 +        //And we will use it to store tmp data while we upgrade or original network to the new physical network
 +        Long networkIdInOldPhysicalNet = _networkMigrationManager.makeCopyOfNetwork(network, oldNtwkOff, oldVpcId);
 +        Network networkInNewPhysicalNet = _networkMigrationManager.upgradeNetworkToNewNetworkOffering(network.getId(), newPhysicalNetworkId,newNtwkOff.getId(), newVpcId);
 +        return new NetworkCopy(networkIdInOldPhysicalNet, networkInNewPhysicalNet);
 +    }
 +
 +    @Override
 +    public Vpc migrateVpcNetwork(long vpcId, long vpcOfferingId, Map<String, String> networkToOffering, Account account, User callerUser, boolean resume) {
 +        //Check if a previous migration run failed and try to resume if resume = true
 +        ResourceTag relatedVpc = _resourceTagDao.findByKey(vpcId, ResourceObjectType.Vpc, NetworkMigrationManager.MIGRATION);
 +        long vpcCopyId = 0;
 +
 +        /*
 +         * In the vpc migration process the newly created Vpc will be used as the new VPC (opposed to network tier migration).
 +         * In case the copy of the vpc was already created. The uuid where already swapped and the id we receive here is the id of the Copy!
 +         * The id stored in the resource tag table under the key "migration" is the id of the ORIGINAL vpc!
 +         */
 +        if (relatedVpc != null) {
 +            if (resume) {
 +                vpcCopyId = vpcId;
 +                vpcId = Long.parseLong(relatedVpc.getValue());
 +                //let's check if the user did not change the vpcoffering opposed to the last failed run.
 +                verifyAlreadyMigratedTiers(vpcCopyId, vpcOfferingId, networkToOffering);
 +            } else {
 +                s_logger.warn("This vpc has a migration row in the resource details table. You might want to re-run migration with resume = true command.");
 +                throw new CloudRuntimeException("Failed to migrate VPC as previous migration left this VPC in transient condition. Specify resume as true.");
 +            }
 +        }
 +
 +        Vpc vpc = _vpcDao.findById(vpcId);
 +        _accountMgr.checkAccess(account, null, true, vpc);
 +
 +        if (vpc.getVpcOfferingId() == vpcOfferingId) {
 +            return vpc;
 +        }
 +        //Try to fail fast, check networks in the VPC and if we can migrate them before proceeding.
 +        List<NetworkVO> tiersInVpc = _networksDao.listByVpc(vpcId);
 +        vpcTiersCanBeMigrated(tiersInVpc, account, networkToOffering, resume);
 +
 +        //In case this is the first time we try to migrate this vpc
 +        if (relatedVpc == null) {
 +            final long vpcIdFinal = vpcId;
 +            vpcCopyId = Transaction.execute((TransactionCallback<Long>)(status) -> _networkMigrationManager.makeCopyOfVpc(vpcIdFinal, vpcOfferingId));
 +        }
 +
 +        Vpc copyOfVpc = _vpcDao.findById(vpcCopyId);
 +        _networkMigrationManager.startVpc(copyOfVpc);
 +
 +        for (Network tier : tiersInVpc) {
 +            String networkOfferingUuid = networkToOffering.get(tier.getUuid());
 +            //UUID may be swapped already with a new uuid due to previous migration failure.
 +            //So we check the related network also in case we don't find the network offering
 +            Long networkId = null;
 +            if (resume && networkOfferingUuid == null) {
 +                tier = _networksDao.findById(tier.getRelated());
 +                networkOfferingUuid = networkToOffering.get(tier.getUuid());
 +                //In this case the tier already exists so we need to get the id of the tier so we can validate correctly
 +                networkId = tier.getId();
 +            }
 +            NetworkOfferingVO newNtwkOff = _networkOfferingDao.findByUuid(networkOfferingUuid);
 +
 +            Account networkAccount = _accountService.getActiveAccountById(tier.getAccountId());
 +            try {
 +                _vpcMgr.validateNtwkOffForNtwkInVpc(networkId, newNtwkOff.getId(), tier.getCidr(), tier.getNetworkDomain(), copyOfVpc, tier.getGateway(), networkAccount, tier.getNetworkACLId());
 +            } catch (InvalidParameterValueException e) {
 +                s_logger.error("Specified network offering can not be used in combination with specified vpc offering. Aborting migration. You can re-run with resume = true and the correct uuid.");
 +                throw e;
 +            }
 +
 +            long newPhysicalNetworkId = findPhysicalNetworkId(tier.getDataCenterId(), newNtwkOff.getTags(), newNtwkOff.getTrafficType());
 +
 +            final long oldNetworkOfferingId = tier.getNetworkOfferingId();
 +            NetworkOffering oldNtwkOff = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId);
 +
 +            if (networkNeedsMigration(tier, newPhysicalNetworkId, oldNtwkOff, newNtwkOff) || (resume && tier.getRelated() != tier.getId())) {
 +                migrateNetworkToPhysicalNetwork(tier, oldNtwkOff, newNtwkOff, vpcId, vpcCopyId, newPhysicalNetworkId, account, callerUser);
 +            }
 +        }
 +        _networkMigrationManager.deleteCopyOfVpc(vpcId, vpcCopyId);
 +        return _vpcDao.findById(vpcCopyId);
 +    }
 +
 +    private void vpcTiersCanBeMigrated(List<? extends Network> tiersInVpc, Account account, Map<String, String> networkToOffering, boolean resume) {
 +        for (Network network : tiersInVpc) {
 +            String networkOfferingUuid = networkToOffering.get(network.getUuid());
 +
 +            //offering uuid can be a tier where the uuid is previously already swapped in a previous migration
 +            if (resume && networkOfferingUuid == null) {
 +                NetworkVO oldVPCtier = _networksDao.findById(network.getRelated());
 +                networkOfferingUuid = networkToOffering.get(oldVPCtier.getUuid());
 +            }
 +
 +            if (networkOfferingUuid == null) {
 +                throwInvalidIdException("Failed to migrate VPC as the specified tierNetworkOfferings is not complete",
 +                                        String.valueOf(network.getUuid()), "networkUuid");
 +            }
 +
 +            NetworkOfferingVO newNtwkOff = _networkOfferingDao.findByUuid(networkOfferingUuid);
 +
 +            if (newNtwkOff == null) {
 +                throwInvalidIdException("Failed to migrate VPC as at least one network offering in tierNetworkOfferings does not exist", networkOfferingUuid, "networkOfferingUuid");
 +            }
 +
 +            if (!_configMgr.isOfferingForVpc(newNtwkOff)) {
 +                throw new InvalidParameterValueException("Network offering " + newNtwkOff.getName() + " ("+ newNtwkOff.getUuid() +") can't be used for VPC networks for network " + network.getName() + "(" + network.getUuid() + ")");
 +            }
 +
 +            verifyNetworkCanBeMigrated(account, network);
 +            long newPhysicalNetworkId = findPhysicalNetworkId(network.getDataCenterId(), newNtwkOff.getTags(), newNtwkOff.getTrafficType());
 +
 +            final long oldNetworkOfferingId = network.getNetworkOfferingId();
 +            NetworkOffering oldNtwkOff = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId);
 +            networkNeedsMigration(network, newPhysicalNetworkId, oldNtwkOff, newNtwkOff);
 +        }
 +    }
 +
 +    private void verifyAlreadyMigratedTiers(long migratedVpcId, long vpcOfferingId, Map<String, String> networkToOffering) {
 +        Vpc migratedVpc = _vpcDao.findById(migratedVpcId);
 +        if (migratedVpc.getVpcOfferingId() != vpcOfferingId) {
 +            s_logger.error("The vpc is already partially migrated in a previous run. The provided vpc offering is not the same as the one used during the first migration process.");
 +            throw new InvalidParameterValueException("Failed to resume migrating VPC as VPC offering does not match previously specified VPC offering (" + migratedVpc.getVpcOfferingId() + ")");
 +        }
 +
 +        List<NetworkVO> migratedTiers = _networksDao.listByVpc(migratedVpcId);
 +        for (Network tier : migratedTiers) {
 +            String tierNetworkOfferingUuid = networkToOffering.get(tier.getUuid());
 +
 +            if (!StringUtils.isNotBlank(tierNetworkOfferingUuid)) {
 +                throwInvalidIdException("Failed to resume migrating VPC as the specified tierNetworkOfferings is not complete",
 +                                        String.valueOf(tier.getUuid()), "networkUuid");
 +            }
 +
 +            NetworkOfferingVO newNetworkOffering = _networkOfferingDao.findByUuid(tierNetworkOfferingUuid);
 +            if (newNetworkOffering == null) {
 +                throw new InvalidParameterValueException("Failed to migrate VPC as at least one tier offering in tierNetworkOfferings does not exist.");
 +            }
 +
 +            if (newNetworkOffering.getId() != tier.getNetworkOfferingId()) {
 +                NetworkOfferingVO tierNetworkOffering = _networkOfferingDao.findById(tier.getNetworkOfferingId());
 +                throw new InvalidParameterValueException("Failed to resume migrating VPC as at least one network offering in tierNetworkOfferings does not match previously specified network offering (network uuid=" + tier.getUuid() + " was previously specified with offering uuid=" + tierNetworkOffering.getUuid() + ")");
 +            }
 +        }
 +    }
 +
 +
 +    private void throwInvalidIdException(String message, String uuid, String description) {
 +        InvalidParameterValueException ex = new InvalidParameterValueException(message);
 +        ex.addProxyObject(uuid, description);
 +        throw ex;
 +    }
 +
 +    private boolean networkNeedsMigration(Network network, long newPhysicalNetworkId, NetworkOffering oldNtwkOff, NetworkOffering newNtwkOff) {
 +
 +        if (newNtwkOff == null || newNtwkOff.isSystemOnly()) {
 +            InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find network offering.");
 +            if (newNtwkOff != null) {
 +                ex.addProxyObject(String.valueOf(newNtwkOff.getId()), "networkOfferingId");
 +            }
 +            throw ex;
 +        }
 +
 +        if (newNtwkOff.getId() != oldNtwkOff.getId() || network.getId() != network.getRelated()) {
 +            Collection<String> newProviders = _networkMgr.finalizeServicesAndProvidersForNetwork(newNtwkOff, newPhysicalNetworkId)
 +                                                         .values();
 +            Collection<String> oldProviders = _networkMgr.finalizeServicesAndProvidersForNetwork(oldNtwkOff, network.getPhysicalNetworkId())
 +                                                         .values();
 +
 +            if (providersConfiguredForExternalNetworking(newProviders) != providersConfiguredForExternalNetworking(oldProviders)) {
 +                throw new InvalidParameterValueException("Updating network failed since guest CIDR needs to be changed!");
 +            }
 +
 +            // check if the network is moveable
 +            if (!canMoveToPhysicalNetwork(network, oldNtwkOff.getId(), newNtwkOff.getId())) {
 +                throw new InvalidParameterValueException(
 +                        "Can't upgrade from network offering " + oldNtwkOff.getUuid() + " to " + newNtwkOff.getUuid() + "; check logs for more information");
 +            }
 +
 +            List<VMInstanceVO> vmInstances = _vmDao.listNonRemovedVmsByTypeAndNetwork(network.getId(), null);
 +            boolean vmStateIsNotTransitioning = vmInstances.stream()
 +                                   .anyMatch(vm -> vm.getState() != VirtualMachine.State.Stopped && vm.getState() != VirtualMachine.State.Running);
 +            if (vmStateIsNotTransitioning) {
 +                throw new CloudRuntimeException("Failed to migrate network as at least one VM is not in running or stopped state.");
 +            }
 +        } else {
 +            return false;
 +        }
 +
 +        // network offering should be in Enabled state
 +        if (newNtwkOff.getState() != NetworkOffering.State.Enabled) {
 +            throw new InvalidParameterValueException("Failed to migrate network as the specified network offering is not enabled.");
 +        }
 +        return true;
 +    }
 +
 +    private void verifyNetworkCanBeMigrated(Account callerAccount, Network network) {
 +        // Don't allow to update system network
 +        NetworkOffering oldOffering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());
 +        if (oldOffering.isSystemOnly()) {
 +            throw new InvalidParameterValueException("Failed to migrate network as the specified network is a system network.");
 +        }
 +
 +        // allow to upgrade only Guest networks
 +        if (network.getTrafficType() != TrafficType.Guest) {
 +            throw new InvalidParameterValueException("Can't allow networks which traffic type is not " + TrafficType.Guest);
 +        }
 +
 +        _accountMgr.checkAccess(callerAccount, null, true, network);
 +
 +        boolean validateNetworkReadyToMigrate = (network.getState() == Network.State.Implemented
 +                || network.getState() == Network.State.Setup
 +                || network.getState() == Network.State.Allocated);
 +        if (!validateNetworkReadyToMigrate) {
 +            s_logger.error("Failed to migrate network as it is in invalid state.");
 +            CloudRuntimeException ex = new CloudRuntimeException("Failed to migrate network as it is in invalid state.");
 +            ex.addProxyObject(network.getUuid(), "networkId");
 +            throw ex;
 +        }
 +    }
 +
 +    private boolean canMoveToPhysicalNetwork(Network network, long oldNetworkOfferingId, long newNetworkOfferingId) {
 +        NetworkOffering oldNetworkOffering = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId);
 +        NetworkOffering newNetworkOffering = _networkOfferingDao.findById(newNetworkOfferingId);
 +
 +        // can move only Isolated networks for now
 +        if (oldNetworkOffering.getGuestType() != GuestType.Isolated) {
 +            throw new InvalidParameterValueException("NetworkOfferingId can be upgraded only for the network of type " + GuestType.Isolated);
 +        }
 +
 +        // Type of the network should be the same
 +        if (oldNetworkOffering.getGuestType() != newNetworkOffering.getGuestType()) {
 +            s_logger.debug("Network offerings " + newNetworkOfferingId + " and " + oldNetworkOfferingId + " are of different types, can't upgrade");
 +            return false;
 +        }
 +
 +        // Traffic types should be the same
 +        if (oldNetworkOffering.getTrafficType() != newNetworkOffering.getTrafficType()) {
 +            s_logger.debug("Network offerings " + newNetworkOfferingId + " and " + oldNetworkOfferingId + " have different traffic types, can't upgrade");
 +            return false;
 +        }
 +
 +        // specify ipRanges should be the same
 +        if (oldNetworkOffering.getSpecifyIpRanges() != newNetworkOffering.getSpecifyIpRanges()) {
 +            s_logger.debug("Network offerings " + newNetworkOfferingId + " and " + oldNetworkOfferingId + " have different values for specifyIpRangess, can't upgrade");
 +            return false;
 +        }
 +
 +        // Check all ips
 +        List<IPAddressVO> userIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null);
 +        List<PublicIp> publicIps = new ArrayList<PublicIp>();
 +        if (userIps != null && !userIps.isEmpty()) {
 +            for (IPAddressVO userIp : userIps) {
 +                PublicIp publicIp = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId()));
 +                publicIps.add(publicIp);
 +            }
 +        }
 +        if (oldNetworkOffering.isConserveMode() && !newNetworkOffering.isConserveMode()) {
 +            if (!canIpsUsedForNonConserve(publicIps)) {
 +                return false;
 +            }
 +        }
 +
 +        //can't update from internal LB to public LB
 +        if (areServicesSupportedByNetworkOffering(oldNetworkOfferingId, Service.Lb) && areServicesSupportedByNetworkOffering(newNetworkOfferingId, Service.Lb)) {
 +            if (oldNetworkOffering.getPublicLb() != newNetworkOffering.getPublicLb() || oldNetworkOffering.getInternalLb() != newNetworkOffering.getInternalLb()) {
 +                throw new InvalidParameterValueException("Original and new offerings support different types of LB - Internal vs Public," + " can't upgrade");
 +            }
 +        }
 +
 +        return canIpsUseOffering(publicIps, newNetworkOfferingId);
 +    }
 +
 +    protected boolean canUpgrade(Network network, long oldNetworkOfferingId, long newNetworkOfferingId) {
 +        NetworkOffering oldNetworkOffering = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId);
 +        NetworkOffering newNetworkOffering = _networkOfferingDao.findById(newNetworkOfferingId);
 +
 +        // security group service should be the same
 +        if (areServicesSupportedByNetworkOffering(oldNetworkOfferingId, Service.SecurityGroup) != areServicesSupportedByNetworkOffering(newNetworkOfferingId, Service.SecurityGroup)) {
 +            s_logger.debug("Offerings " + newNetworkOfferingId + " and " + oldNetworkOfferingId + " have different securityGroupProperty, can't upgrade");
 +            return false;
 +        }
 +
 +        // tags should be the same
 +        if (newNetworkOffering.getTags() != null) {
 +            if (oldNetworkOffering.getTags() == null) {
 +                s_logger.debug("New network offering id=" + newNetworkOfferingId + " has tags and old network offering id=" + oldNetworkOfferingId + " doesn't, can't upgrade");
 +                return false;
 +            }
 +
 +            if (!StringUtils.areTagsEqual(oldNetworkOffering.getTags(), newNetworkOffering.getTags())) {
 +                s_logger.debug("Network offerings " + newNetworkOffering.getUuid() + " and " + oldNetworkOffering.getUuid() + " have different tags, can't upgrade");
 +                return false;
 +            }
 +        }
 +
 +        // specify vlan should be the same
 +        if (oldNetworkOffering.getSpecifyVlan() != newNetworkOffering.getSpecifyVlan()) {
 +            s_logger.debug("Network offerings " + newNetworkOfferingId + " and " + oldNetworkOfferingId + " have different values for specifyVlan, can't upgrade");
 +            return false;
 +        }
 +
 +        return  canMoveToPhysicalNetwork(network, oldNetworkOfferingId, newNetworkOfferingId);
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_CREATE, eventDescription = "Creating Physical Network", create = true)
 +    public PhysicalNetwork createPhysicalNetwork(final Long zoneId, final String vnetRange, final String networkSpeed, final List<String> isolationMethods,
 +            String broadcastDomainRangeStr, final Long domainId, final List<String> tags, final String name) {
 +
 +        // Check if zone exists
 +        if (zoneId == null) {
 +            throw new InvalidParameterValueException("Please specify a valid zone.");
 +        }
 +
 +        DataCenterVO zone = _dcDao.findById(zoneId);
 +        if (zone == null) {
 +            throw new InvalidParameterValueException("Please specify a valid zone.");
 +        }
 +
 +        if (Grouping.AllocationState.Enabled == zone.getAllocationState()) {
 +            // TBD: Send uuid instead of zoneId; may have to hardcode tablename in call to addProxyObject().
 +            throw new PermissionDeniedException("Cannot create PhysicalNetwork since the Zone is currently enabled, zone Id: " + zoneId);
 +        }
 +
 +        NetworkType zoneType = zone.getNetworkType();
 +
 +        if (zoneType == NetworkType.Basic) {
 +            if (!_physicalNetworkDao.listByZone(zoneId).isEmpty()) {
 +                // TBD: Send uuid instead of zoneId; may have to hardcode tablename in call to addProxyObject().
 +                throw new CloudRuntimeException("Cannot add the physical network to basic zone id: " + zoneId + ", there is a physical network already existing in this basic Zone");
 +            }
 +        }
 +        if (tags != null && tags.size() > 1) {
 +            throw new InvalidParameterException("Only one tag can be specified for a physical network at this time");
 +        }
 +
 +        if (isolationMethods != null && isolationMethods.size() > 1) {
 +            throw new InvalidParameterException("Only one isolationMethod can be specified for a physical network at this time");
 +        }
 +
 +        if (vnetRange != null) {
 +            // Verify zone type
 +            if (zoneType == NetworkType.Basic || (zoneType == NetworkType.Advanced && zone.isSecurityGroupEnabled())) {
 +                throw new InvalidParameterValueException("Can't add vnet range to the physical network in the zone that supports " + zoneType
 +                        + " network, Security Group enabled: " + zone.isSecurityGroupEnabled());
 +            }
 +        }
 +
 +        BroadcastDomainRange broadcastDomainRange = null;
 +        if (broadcastDomainRangeStr != null && !broadcastDomainRangeStr.isEmpty()) {
 +            try {
 +                broadcastDomainRange = PhysicalNetwork.BroadcastDomainRange.valueOf(broadcastDomainRangeStr.toUpperCase());
 +            } catch (IllegalArgumentException ex) {
 +                throw new InvalidParameterValueException("Unable to resolve broadcastDomainRange '" + broadcastDomainRangeStr + "' to a supported value {Pod or Zone}");
 +            }
 +
 +            // in Acton release you can specify only Zone broadcastdomain type in Advance zone, and Pod in Basic
 +            if (zoneType == NetworkType.Basic && broadcastDomainRange != null && broadcastDomainRange != BroadcastDomainRange.POD) {
 +                throw new InvalidParameterValueException("Basic zone can have broadcast domain type of value " + BroadcastDomainRange.POD + " only");
 +            } else if (zoneType == NetworkType.Advanced && broadcastDomainRange != null && broadcastDomainRange != BroadcastDomainRange.ZONE) {
 +                throw new InvalidParameterValueException("Advance zone can have broadcast domain type of value " + BroadcastDomainRange.ZONE + " only");
 +            }
 +        }
 +
 +        if (broadcastDomainRange == null) {
 +            if (zoneType == NetworkType.Basic) {
 +                broadcastDomainRange = PhysicalNetwork.BroadcastDomainRange.POD;
 +            } else {
 +                broadcastDomainRange = PhysicalNetwork.BroadcastDomainRange.ZONE;
 +            }
 +        }
 +
 +        try {
 +            final BroadcastDomainRange broadcastDomainRangeFinal = broadcastDomainRange;
 +            return Transaction.execute(new TransactionCallback<PhysicalNetworkVO>() {
 +                @Override
 +                public PhysicalNetworkVO doInTransaction(TransactionStatus status) {
 +            // Create the new physical network in the database
 +            long id = _physicalNetworkDao.getNextInSequence(Long.class, "id");
 +                    PhysicalNetworkVO pNetwork = new PhysicalNetworkVO(id, zoneId, vnetRange, networkSpeed, domainId, broadcastDomainRangeFinal, name);
 +            pNetwork.setTags(tags);
 +            pNetwork.setIsolationMethods(isolationMethods);
 +
 +            pNetwork = _physicalNetworkDao.persist(pNetwork);
 +
 +            // Add vnet entries for the new zone if zone type is Advanced
 +            if (vnetRange != null) {
 +                addOrRemoveVnets(vnetRange.split(","), pNetwork);
 +            }
 +
 +            // add VirtualRouter as the default network service provider
 +            addDefaultVirtualRouterToPhysicalNetwork(pNetwork.getId());
 +
 +                    if (pNetwork.getIsolationMethods().contains("GRE"))
 +                        addDefaultOvsToPhysicalNetwork(pNetwork.getId());
 +
 +            // add security group provider to the physical network
 +            addDefaultSecurityGroupProviderToPhysicalNetwork(pNetwork.getId());
 +
 +            // add VPCVirtualRouter as the defualt network service provider
 +            addDefaultVpcVirtualRouterToPhysicalNetwork(pNetwork.getId());
 +
 +            // add baremetal as the defualt network service provider
 +            addDefaultBaremetalProvidersToPhysicalNetwork(pNetwork.getId());
 +
 +            //Add Internal Load Balancer element as a default network service provider
 +            addDefaultInternalLbProviderToPhysicalNetwork(pNetwork.getId());
 +
 +            // Add the config drive provider
 +            addConfigDriveToPhysicalNetwork(pNetwork.getId());
 +
 +            return pNetwork;
 +                }
 +            });
 +        } catch (Exception ex) {
 +            s_logger.warn("Exception: ", ex);
 +            throw new CloudRuntimeException("Fail to create a physical network");
 +        }
 +    }
 +
 +    @Override
 +    public Pair<List<? extends PhysicalNetwork>, Integer> searchPhysicalNetworks(Long id, Long zoneId, String keyword, Long startIndex, Long pageSize, String name) {
 +        Filter searchFilter = new Filter(PhysicalNetworkVO.class, "id", Boolean.TRUE, startIndex, pageSize);
 +        SearchCriteria<PhysicalNetworkVO> sc = _physicalNetworkDao.createSearchCriteria();
 +
 +        if (id != null) {
 +            sc.addAnd("id", SearchCriteria.Op.EQ, id);
 +        }
 +
 +        if (zoneId != null) {
 +            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
 +        }
 +
 +        if (name != null) {
 +            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
 +        }
 +
 +        Pair<List<PhysicalNetworkVO>, Integer> result =  _physicalNetworkDao.searchAndCount(sc, searchFilter);
 +        return new Pair<List<? extends PhysicalNetwork>, Integer>(result.first(), result.second());
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_UPDATE, eventDescription = "updating physical network", async = true)
 +    public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List<String> tags, String newVnetRange, String state) {
 +
 +        // verify input parameters
 +        PhysicalNetworkVO network = _physicalNetworkDao.findById(id);
 +        if (network == null) {
 +            throwInvalidIdException("Physical Network with specified id doesn't exist in the system", id.toString(), "physicalNetworkId");
 +        }
 +
 +        // if zone is of Basic type, don't allow to add vnet range
 +        DataCenter zone = _dcDao.findById(network.getDataCenterId());
 +        if (zone == null) {
 +            throwInvalidIdException("Zone with id=" + network.getDataCenterId() + " doesn't exist in the system", String.valueOf(network.getDataCenterId()), "dataCenterId");
 +        }
 +        if (newVnetRange != null) {
 +            if (zone.getNetworkType() == NetworkType.Basic || (zone.getNetworkType() == NetworkType.Advanced && zone.isSecurityGroupEnabled())) {
 +                throw new InvalidParameterValueException("Can't add vnet range to the physical network in the zone that supports " + zone.getNetworkType()
 +                        + " network, Security Group enabled: " + zone.isSecurityGroupEnabled());
 +            }
 +        }
 +
 +        if (tags != null && tags.size() > 1) {
 +            throw new InvalidParameterException("Unable to support more than one tag on network yet");
 +        }
 +
 +        PhysicalNetwork.State networkState = null;
 +        if (state != null && !state.isEmpty()) {
 +            try {
 +                networkState = PhysicalNetwork.State.valueOf(state);
 +            } catch (IllegalArgumentException ex) {
 +                throw new InvalidParameterValueException("Unable to resolve state '" + state + "' to a supported value {Enabled or Disabled}");
 +            }
 +        }
 +
 +        if (state != null) {
 +            network.setState(networkState);
 +        }
 +
 +        if (tags != null) {
 +            network.setTags(tags);
 +        }
 +
 +        if (networkSpeed != null) {
 +            network.setSpeed(networkSpeed);
 +        }
 +
 +        if (newVnetRange != null) {
 +            String[] listOfRanges = newVnetRange.split(",");
 +            addOrRemoveVnets(listOfRanges, network);
 +        }
 +        _physicalNetworkDao.update(id, network);
 +        return network;
 +
 +    }
 +
 +    @DB
 +    public void addOrRemoveVnets(String[] listOfRanges, final PhysicalNetworkVO network) {
 +        List<String>  addVnets = null;
 +        List<String> removeVnets = null;
 +        HashSet<String> tempVnets = new HashSet<String>();
 +        HashSet<String> vnetsInDb = new HashSet<String>();
 +        List<Pair<Integer, Integer>> vnetranges = null;
 +        String comaSeperatedStingOfVnetRanges = null;
 +        int i = 0;
 +        if (listOfRanges.length != 0) {
 +            _physicalNetworkDao.acquireInLockTable(network.getId(), 10);
 +            vnetranges = validateVlanRange(network, listOfRanges);
 +
 +            //computing vnets to be removed.
 +            removeVnets = getVnetsToremove(network, vnetranges);
 +
 +            //computing vnets to add
 +            vnetsInDb.addAll(_datacneterVnet.listVnetsByPhysicalNetworkAndDataCenter(network.getDataCenterId(), network.getId()));
 +            tempVnets.addAll(vnetsInDb);
 +            for (Pair<Integer, Integer> vlan : vnetranges) {
 +                for (i = vlan.first(); i <= vlan.second(); i++) {
 +                    tempVnets.add(Integer.toString(i));
 +                }
 +            }
 +            tempVnets.removeAll(vnetsInDb);
 +
 +            //vnets to add in tempVnets.
 +            //adding and removing vnets from vnetsInDb
 +            if (removeVnets != null && removeVnets.size() != 0) {
 +                vnetsInDb.removeAll(removeVnets);
 +            }
 +
 +            if (tempVnets.size() != 0) {
 +                addVnets = new ArrayList<String>();
 +                addVnets.addAll(tempVnets);
 +                vnetsInDb.addAll(tempVnets);
 +            }
 +
 +            //sorting the vnets in Db to generate a coma seperated list of  the vnet string.
 +            if (vnetsInDb.size() != 0) {
 +                comaSeperatedStingOfVnetRanges = generateVnetString(new ArrayList<String>(vnetsInDb));
 +            }
 +            network.setVnet(comaSeperatedStingOfVnetRanges);
 +
 +            final List<String> addVnetsFinal = addVnets;
 +            final List<String> removeVnetsFinal = removeVnets;
 +            Transaction.execute(new TransactionCallbackNoReturn() {
 +                @Override
 +                public void doInTransactionWithoutResult(TransactionStatus status) {
 +                    if (addVnetsFinal != null) {
 +                        s_logger.debug("Adding vnet range " + addVnetsFinal.toString() + " for the physicalNetwork id= " + network.getId() + " and zone id="
 +                                + network.getDataCenterId() + " as a part of updatePhysicalNetwork call");
 +                //add vnet takes a list of strings to be added. each string is a vnet.
 +                        _dcDao.addVnet(network.getDataCenterId(), network.getId(), addVnetsFinal);
 +            }
 +                    if (removeVnetsFinal != null) {
 +                        s_logger.debug("removing vnet range " + removeVnetsFinal.toString() + " for the physicalNetwork id= " + network.getId() + " and zone id="
 +                                + network.getDataCenterId() + " as a part of updatePhysicalNetwork call");
 +                //deleteVnets  takes a list of strings to be removed. each string is a vnet.
 +                        _datacneterVnet.deleteVnets(TransactionLegacy.currentTxn(), network.getDataCenterId(), network.getId(), removeVnetsFinal);
 +            }
 +            _physicalNetworkDao.update(network.getId(), network);
 +                }
 +            });
 +
 +            _physicalNetworkDao.releaseFromLockTable(network.getId());
 +        }
 +    }
 +
 +    private List<Pair<Integer, Integer>> validateVlanRange(PhysicalNetworkVO network, String[] listOfRanges) {
 +        Integer StartVnet;
 +        Integer EndVnet;
 +        List<Pair<Integer, Integer>> vlanTokens = new ArrayList<Pair<Integer, Integer>>();
 +        for (String vlanRange : listOfRanges) {
 +            String[] VnetRange = vlanRange.split("-");
 +
 +            // Init with [min,max] of VLAN. Actually 0x000 and 0xFFF are reserved by IEEE, shoudn't be used.
 +            long minVnet = MIN_VLAN_ID;
 +            long maxVnet = MAX_VLAN_ID;
 +
 +            // for GRE phynets allow up to 32bits
 +            // TODO: Not happy about this test.
 +            // What about guru-like objects for physical networs?
 +            s_logger.debug("ISOLATION METHODS:" + network.getIsolationMethods());
 +            // Java does not have unsigned types...
 +            if (network.getIsolationMethods().contains("GRE")) {
 +                minVnet = MIN_GRE_KEY;
 +                maxVnet = MAX_GRE_KEY;
 +            } else if (network.getIsolationMethods().contains("VXLAN")) {
 +                minVnet = MIN_VXLAN_VNI;
 +                maxVnet = MAX_VXLAN_VNI;
 +                // fail if zone already contains VNI, need to be unique per zone.
 +                // since adding a range adds each VNI to the database, need only check min/max
 +                for (String vnet : VnetRange) {
 +                    s_logger.debug("Looking to see if VNI " + vnet + " already exists on another network in zone " + network.getDataCenterId());
 +                    List<DataCenterVnetVO> vnis = _datacneterVnet.findVnet(network.getDataCenterId(), vnet);
 +                    if (vnis != null && !vnis.isEmpty()) {
 +                        for (DataCenterVnetVO vni : vnis) {
 +                            if (vni.getPhysicalNetworkId() != network.getId()) {
 +                                s_logger.debug("VNI " + vnet + " already exists on another network in zone, please specify a unique range");
 +                                throw new InvalidParameterValueException("VNI " + vnet + " already exists on another network in zone, please specify a unique range");
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +            String rangeMessage = " between " + minVnet + " and " + maxVnet;
 +            if (VnetRange.length == 1 && VnetRange[0].equals("")) {
 +                return vlanTokens;
 +            }
 +            if (VnetRange.length < 2) {
 +                throw new InvalidParameterValueException("Please provide valid vnet range. vnet range should be a coma seperated list of vlan ranges. example 500-500,600-601"
 +                        + rangeMessage);
 +            }
 +
 +            if (VnetRange[0] == null || VnetRange[1] == null) {
 +                throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage);
 +            }
 +
 +            try {
 +                StartVnet = Integer.parseInt(VnetRange[0]);
 +                EndVnet = Integer.parseInt(VnetRange[1]);
 +            } catch (NumberFormatException e) {
 +                s_logger.warn("Unable to parse vnet range:", e);
 +                throw new InvalidParameterValueException("Please provide valid vnet range. The vnet range should be a coma seperated list example 2001-2012,3000-3005."
 +                        + rangeMessage);
 +            }
 +            if (StartVnet < minVnet || EndVnet > maxVnet) {
 +                throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage);
 +            }
 +
 +            if (StartVnet > EndVnet) {
 +                throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage + " and start range should be lesser than or equal to stop range");
 +            }
 +            vlanTokens.add(new Pair<Integer, Integer>(StartVnet, EndVnet));
 +        }
 +        return vlanTokens;
 +
 +    }
 +
 +    public  String generateVnetString(List<String> vnetList) {
 +        Collections.sort(vnetList, new Comparator<String>() {
 +            @Override
 +            public int compare(String s1, String s2) {
 +                return Integer.valueOf(s1).compareTo(Integer.valueOf(s2));
 +            }
 +        });
 +        int i;
 +        //build the vlan string form the sorted list.
 +        String vnetRange = "";
 +        String startvnet = vnetList.get(0);
 +        String endvnet = "";
 +        for (i = 0; i < vnetList.size() - 1; i++) {
 +            if (Integer.parseInt(vnetList.get(i + 1)) - Integer.parseInt(vnetList.get(i)) > 1) {
 +                endvnet = vnetList.get(i);
 +                vnetRange = vnetRange + startvnet + "-" + endvnet + ",";
 +                startvnet = vnetList.get(i + 1);
 +            }
 +        }
 +        endvnet = vnetList.get(vnetList.size() - 1);
 +        vnetRange = vnetRange + startvnet + "-" + endvnet + ",";
 +        vnetRange = vnetRange.substring(0, vnetRange.length() - 1);
 +        return vnetRange;
 +    }
 +
 +    private List<String> getVnetsToremove(PhysicalNetworkVO network, List<Pair<Integer, Integer>> vnetRanges) {
 +        int i;
 +        List<String> removeVnets = new ArrayList<String>();
 +        HashSet<String> vnetsInDb = new HashSet<String>();
 +        vnetsInDb.addAll(_datacneterVnet.listVnetsByPhysicalNetworkAndDataCenter(network.getDataCenterId(), network.getId()));
 +        //remove all the vnets from vnets in db to check if there are any vnets that are not there in given list.
 +        //remove all the vnets not in the list of vnets passed by the user.
 +        if (vnetRanges.size() == 0) {
 +            //this implies remove all vlans.
 +            removeVnets.addAll(vnetsInDb);
 +            int allocated_vnets = _datacneterVnet.countAllocatedVnets(network.getId());
 +            if (allocated_vnets > 0) {
 +                throw new InvalidParameterValueException("physicalnetwork " + network.getId() + " has " + allocated_vnets + " vnets in use");
 +            }
 +            return removeVnets;
 +        }
 +        for (Pair<Integer, Integer> vlan : vnetRanges) {
 +            for (i = vlan.first(); i <= vlan.second(); i++) {
 +                vnetsInDb.remove(Integer.toString(i));
 +            }
 +        }
 +        String vnetRange = null;
 +        if (vnetsInDb.size() != 0) {
 +            removeVnets.addAll(vnetsInDb);
 +            vnetRange = generateVnetString(removeVnets);
 +        } else {
 +            return removeVnets;
 +        }
 +
 +        for (String vnet : vnetRange.split(",")) {
 +            String[] range = vnet.split("-");
 +            Integer start = Integer.parseInt(range[0]);
 +            Integer end = Integer.parseInt(range[1]);
 +            _datacneterVnet.lockRange(network.getDataCenterId(), network.getId(), start, end);
 +            List<DataCenterVnetVO> result = _datacneterVnet.listAllocatedVnetsInRange(network.getDataCenterId(), network.getId(), start, end);
 +            if (!result.isEmpty()) {
 +                throw new InvalidParameterValueException("physicalnetwork " + network.getId() + " has allocated vnets in the range " + start + "-" + end);
 +
 +            }
 +            // If the range is partially dedicated to an account fail the request
 +            List<AccountGuestVlanMapVO> maps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByPhysicalNetwork(network.getId());
 +            for (AccountGuestVlanMapVO map : maps) {
 +                String[] vlans = map.getGuestVlanRange().split("-");
 +                Integer dedicatedStartVlan = Integer.parseInt(vlans[0]);
 +                Integer dedicatedEndVlan = Integer.parseInt(vlans[1]);
 +                if ((start >= dedicatedStartVlan && start <= dedicatedEndVlan) || (end >= dedicatedStartVlan && end <= dedicatedEndVlan)) {
 +                    throw new InvalidParameterValueException("Vnet range " + map.getGuestVlanRange() + " is dedicated" + " to an account. The specified range " + start + "-" + end
 +                            + " overlaps with the dedicated range " + " Please release the overlapping dedicated range before deleting the range");
 +                }
 +            }
 +        }
 +        return  removeVnets;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_DELETE, eventDescription = "deleting physical network", async = true)
 +    @DB
 +    public boolean deletePhysicalNetwork(final Long physicalNetworkId) {
 +
 +        // verify input parameters
 +        PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId);
 +        if (pNetwork == null) {
 +            throwInvalidIdException("Physical Network with specified id doesn't exist in the system", physicalNetworkId.toString(), "physicalNetworkId");
 +        }
 +
 +        checkIfPhysicalNetworkIsDeletable(physicalNetworkId);
 +
 +        return Transaction.execute(new TransactionCallback<Boolean>() {
 +            @Override
 +            public Boolean doInTransaction(TransactionStatus status) {
 +        // delete vlans for this zone
 +        List<VlanVO> vlans = _vlanDao.listVlansByPhysicalNetworkId(physicalNetworkId);
 +        for (VlanVO vlan : vlans) {
 +            _vlanDao.remove(vlan.getId());
 +        }
 +
 +        // Delete networks
 +        List<NetworkVO> networks = _networksDao.listByPhysicalNetwork(physicalNetworkId);
 +        if (networks != null && !networks.isEmpty()) {
 +            for (NetworkVO network : networks) {
 +                _networksDao.remove(network.getId());
 +            }
 +        }
 +
 +        // delete vnets
 +        _dcDao.deleteVnet(physicalNetworkId);
 +
 +        // delete service providers
 +        List<PhysicalNetworkServiceProviderVO> providers = _pNSPDao.listBy(physicalNetworkId);
 +
 +                for (PhysicalNetworkServiceProviderVO provider : providers) {
 +            try {
 +                deleteNetworkServiceProvider(provider.getId());
 +                    } catch (ResourceUnavailableException e) {
 +                        s_logger.warn("Unable to complete destroy of the physical network provider: " + provider.getProviderName() + ", id: " + provider.getId(), e);
 +                return false;
 +            } catch (ConcurrentOperationException e) {
 +                        s_logger.warn("Unable to complete destroy of the physical network provider: " + provider.getProviderName() + ", id: " + provider.getId(), e);
 +                return false;
 +            }
 +        }
 +
 +        // delete traffic types
 +        _pNTrafficTypeDao.deleteTrafficTypes(physicalNetworkId);
 +
 +                return _physicalNetworkDao.remove(physicalNetworkId);
 +            }
 +        });
 +    }
 +
 +    @DB
 +    protected void checkIfPhysicalNetworkIsDeletable(Long physicalNetworkId) {
 +        List<List<String>> tablesToCheck = new ArrayList<List<String>>();
 +
 +        List<String> vnet = new ArrayList<String>();
 +        vnet.add(0, "op_dc_vnet_alloc");
 +        vnet.add(1, "physical_network_id");
 +        vnet.add(2, "there are allocated vnets for this physical network");
 +        tablesToCheck.add(vnet);
 +
 +        List<String> networks = new ArrayList<String>();
 +        networks.add(0, "networks");
 +        networks.add(1, "physical_network_id");
 +        networks.add(2, "there are networks associated to this physical network");
 +        tablesToCheck.add(networks);
 +
 +        /*
 +         * List<String> privateIP = new ArrayList<String>();
 +         * privateIP.add(0, "op_dc_ip_address_alloc");
 +         * privateIP.add(1, "data_center_id");
 +         * privateIP.add(2, "there are private IP addresses allocated for this zone");
 +         * tablesToCheck.add(privateIP);
 +         */
 +
 +        List<String> publicIP = new ArrayList<String>();
 +        publicIP.add(0, "user_ip_address");
 +        publicIP.add(1, "physical_network_id");
 +        publicIP.add(2, "there are public IP addresses allocated for this physical network");
 +        tablesToCheck.add(publicIP);
 +
 +        for (List<String> table : tablesToCheck) {
 +            String tableName = table.get(0);
 +            String column = table.get(1);
 +            String errorMsg = table.get(2);
 +
 +            String dbName = "cloud";
 +
 +            String selectSql = "SELECT * FROM `" + dbName + "`.`" + tableName + "` WHERE " + column + " = ?";
 +
 +            if (tableName.equals("networks")) {
 +                selectSql += " AND removed is NULL";
 +            }
 +
 +            if (tableName.equals("op_dc_vnet_alloc")) {
 +                selectSql += " AND taken IS NOT NULL";
 +            }
 +
 +            if (tableName.equals("user_ip_address")) {
 +                selectSql += " AND state!='Free'";
 +            }
 +
 +            if (tableName.equals("op_dc_ip_address_alloc")) {
 +                selectSql += " AND taken IS NOT NULL";
 +            }
 +
 +            TransactionLegacy txn = TransactionLegacy.currentTxn();
 +            try {
 +                PreparedStatement stmt = txn.prepareAutoCloseStatement(selectSql);
 +                stmt.setLong(1, physicalNetworkId);
 +                ResultSet rs = stmt.executeQuery();
 +                if (rs != null && rs.next()) {
 +                    throw new CloudRuntimeException("The Physical Network is not deletable because " + errorMsg);
 +                }
 +            } catch (SQLException ex) {
 +                throw new CloudRuntimeException("The Management Server failed to detect if physical network is deletable. Please contact Cloud Support.");
 +            }
 +        }
 +
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_GUEST_VLAN_RANGE_DEDICATE, eventDescription = "dedicating guest vlan range", async = false)
 +    public GuestVlan dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) {
 +        String vlan = cmd.getVlan();
 +        String accountName = cmd.getAccountName();
 +        Long domainId = cmd.getDomainId();
 +        Long physicalNetworkId = cmd.getPhysicalNetworkId();
 +        Long projectId = cmd.getProjectId();
 +
 +        int startVlan, endVlan;
 +        String updatedVlanRange = null;
 +        long guestVlanMapId = 0;
 +        long guestVlanMapAccountId = 0;
 +        long vlanOwnerId = 0;
 +
 +        // Verify account is valid
 +        Account vlanOwner = null;
 +        if (projectId != null) {
 +            if (accountName != null) {
 +                throw new InvalidParameterValueException("accountName and projectId are mutually exclusive");
 +            }
 +            Project project = _projectMgr.getProject(projectId);
 +            if (project == null) {
 +                throw new InvalidParameterValueException("Unable to find project by id " + projectId);
 +            }
 +            vlanOwner = _accountMgr.getAccount(project.getProjectAccountId());
 +        }
 +
 +        if ((accountName != null) && (domainId != null)) {
 +            vlanOwner = _accountDao.findActiveAccount(accountName, domainId);
 +        }
 +        if (vlanOwner == null) {
 +            throw new InvalidParameterValueException("Unable to find account by name " + accountName);
 +        }
 +        vlanOwnerId = vlanOwner.getAccountId();
 +
 +        // Verify physical network isolation type is VLAN
 +        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
 +        if (physicalNetwork == null) {
 +            throw new InvalidParameterValueException("Unable to find physical network by id " + physicalNetworkId);
 +        } else if (!physicalNetwork.getIsolationMethods().isEmpty() && !physicalNetwork.getIsolationMethods().contains("VLAN")) {
 +            throw new InvalidParameterValueException("Cannot dedicate guest vlan range. " + "Physical isolation type of network " + physicalNetworkId + " is not VLAN");
 +        }
 +
 +        // Get the start and end vlan
 +        String[] vlanRange = vlan.split("-");
 +        if (vlanRange.length != 2) {
 +            throw new InvalidParameterValueException("Invalid format for parameter value vlan " + vlan + " .Vlan should be specified as 'startvlan-endvlan'");
 +        }
 +
 +        try {
 +            startVlan = Integer.parseInt(vlanRange[0]);
 +            endVlan = Integer.parseInt(vlanRange[1]);
 +        } catch (NumberFormatException e) {
 +            s_logger.warn("Unable to parse guest vlan range:", e);
 +            throw new InvalidParameterValueException("Please provide valid guest vlan range");
 +        }
 +
 +        // Verify guest vlan range exists in the system
 +        List<Pair<Integer, Integer>> existingRanges = physicalNetwork.getVnet();
 +        Boolean exists = false;
 +        if (!existingRanges.isEmpty()) {
 +            for (int i = 0; i < existingRanges.size(); i++) {
 +                int existingStartVlan = existingRanges.get(i).first();
 +                int existingEndVlan = existingRanges.get(i).second();
 +                if (startVlan <= endVlan && startVlan >= existingStartVlan && endVlan <= existingEndVlan) {
 +                        exists = true;
 +                        break;
 +                    }
 +            }
 +            if (!exists) {
 +                throw new InvalidParameterValueException("Unable to find guest vlan by range " + vlan);
 +            }
 +        }
 +
 +        // Verify guest vlans in the range don't belong to a network of a different account
 +        for (int i = startVlan; i <= endVlan; i++) {
 +            List<DataCenterVnetVO> allocatedVlans = _datacneterVnet.listAllocatedVnetsInRange(physicalNetwork.getDataCenterId(), physicalNetwork.getId(), startVlan, endVlan);
 +            if (allocatedVlans != null && !allocatedVlans.isEmpty()) {
 +                for (DataCenterVnetVO allocatedVlan : allocatedVlans) {
 +                    if (allocatedVlan.getAccountId() !=  vlanOwner.getAccountId()) {
 +                        throw new InvalidParameterValueException("Guest vlan from this range " + allocatedVlan.getVnet() + " is allocated to a different account."
 +                                + " Can only dedicate a range which has no allocated vlans or has vlans allocated to the same account ");
 +                    }
 +                }
 +            }
 +        }
 +
 +        List<AccountGuestVlanMapVO> guestVlanMaps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByPhysicalNetwork(physicalNetworkId);
 +        // Verify if vlan range is already dedicated
 +        for (AccountGuestVlanMapVO guestVlanMap : guestVlanMaps) {
 +            List<Integer> vlanTokens = getVlanFromRange(guestVlanMap.getGuestVlanRange());
 +            int dedicatedStartVlan = vlanTokens.get(0).intValue();
 +            int dedicatedEndVlan = vlanTokens.get(1).intValue();
 +            if ((startVlan < dedicatedStartVlan & endVlan >= dedicatedStartVlan) || (startVlan >= dedicatedStartVlan & startVlan <= dedicatedEndVlan)) {
 +                throw new InvalidParameterValueException("Vlan range is already dedicated. Cannot" + " dedicate guest vlan range " + vlan);
 +            }
 +        }
 +
 +        // Sort the existing dedicated vlan ranges
 +        Collections.sort(guestVlanMaps, new Comparator<AccountGuestVlanMapVO>() {
 +            @Override
 +            public int compare(AccountGuestVlanMapVO obj1, AccountGuestVlanMapVO obj2) {
 +                List<Integer> vlanTokens1 = getVlanFromRange(obj1.getGuestVlanRange());
 +                List<Integer> vlanTokens2 = getVlanFromRange(obj2.getGuestVlanRange());
 +                return vlanTokens1.get(0).compareTo(vlanTokens2.get(0));
 +            }
 +        });
 +
 +        // Verify if vlan range extends an already dedicated range
 +        for (int i = 0; i < guestVlanMaps.size(); i++) {
 +            guestVlanMapId = guestVlanMaps.get(i).getId();
 +            guestVlanMapAccountId = guestVlanMaps.get(i).getAccountId();
 +            List<Integer> vlanTokens1 = getVlanFromRange(guestVlanMaps.get(i).getGuestVlanRange());
 +            // Range extends a dedicated vlan range to the left
 +            if (endVlan == (vlanTokens1.get(0).intValue() - 1)) {
 +                if (guestVlanMapAccountId == vlanOwnerId) {
 +                    updatedVlanRange = startVlan + "-" + vlanTokens1.get(1).intValue();
 +                }
 +                break;
 +            }
 +            // Range extends a dedicated vlan range to the right
 +            if (startVlan == (vlanTokens1.get(1).intValue() + 1) & guestVlanMapAccountId == vlanOwnerId) {
 +                if (i != (guestVlanMaps.size() - 1)) {
 +                    List<Integer> vlanTokens2 = getVlanFromRange(guestVlanMaps.get(i + 1).getGuestVlanRange());
 +                    // Range extends 2 vlan ranges, both to the right and left
 +                    if (endVlan == (vlanTokens2.get(0).intValue() - 1) && guestVlanMaps.get(i + 1).getAccountId() == vlanOwnerId) {
 +                        _datacneterVnet.releaseDedicatedGuestVlans(guestVlanMaps.get(i + 1).getId());
 +                        _accountGuestVlanMapDao.remove(guestVlanMaps.get(i + 1).getId());
 +                        updatedVlanRange = vlanTokens1.get(0).intValue() + "-" + vlanTokens2.get(1).intValue();
 +                        break;
 +                    }
 +                }
 +                updatedVlanRange = vlanTokens1.get(0).intValue() + "-" + endVlan;
 +                break;
 +            }
 +        }
 +        // Dedicate vlan range
 +        AccountGuestVlanMapVO accountGuestVlanMapVO;
 +        if (updatedVlanRange != null) {
 +            accountGuestVlanMapVO = _accountGuestVlanMapDao.findById(guestVlanMapId);
 +            accountGuestVlanMapVO.setGuestVlanRange(updatedVlanRange);
 +            _accountGuestVlanMapDao.update(guestVlanMapId, accountGuestVlanMapVO);
 +        } else {
 +            accountGuestVlanMapVO = new AccountGuestVlanMapVO(vlanOwner.getAccountId(), physicalNetworkId);
 +            accountGuestVlanMapVO.setGuestVlanRange(startVlan + "-" +  endVlan);
 +            _accountGuestVlanMapDao.persist(accountGuestVlanMapVO);
 +        }
 +        // For every guest vlan set the corresponding account guest vlan map id
 +        List<Integer> finaVlanTokens = getVlanFromRange(accountGuestVlanMapVO.getGuestVlanRange());
 +        for (int i = finaVlanTokens.get(0).intValue(); i <= finaVlanTokens.get(1).intValue(); i++) {
 +            List<DataCenterVnetVO> dataCenterVnet = _datacneterVnet.findVnet(physicalNetwork.getDataCenterId(), physicalNetworkId, Integer.toString(i));
 +            dataCenterVnet.get(0).setAccountGuestVlanMapId(accountGuestVlanMapVO.getId());
 +            _datacneterVnet.update(dataCenterVnet.get(0).getId(), dataCenterVnet.get(0));
 +        }
 +        return accountGuestVlanMapVO;
 +    }
 +
 +    private List<Integer> getVlanFromRange(String vlanRange) {
 +        // Get the start and end vlan
 +        String[] vlanTokens = vlanRange.split("-");
 +        List<Integer> tokens = new ArrayList<Integer>();
 +        try {
 +            int startVlan = Integer.parseInt(vlanTokens[0]);
 +            int endVlan = Integer.parseInt(vlanTokens[1]);
 +            tokens.add(startVlan);
 +            tokens.add(endVlan);
 +        } catch (NumberFormatException e) {
 +            s_logger.warn("Unable to parse guest vlan range:", e);
 +            throw new InvalidParameterValueException("Please provide valid guest vlan range");
 +        }
 +        return tokens;
 +    }
 +
 +    @Override
 +    public Pair<List<? extends GuestVlan>, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd) {
 +        Long id = cmd.getId();
 +        String accountName = cmd.getAccountName();
 +        Long domainId = cmd.getDomainId();
 +        Long projectId = cmd.getProjectId();
 +        String guestVlanRange = cmd.getGuestVlanRange();
 +        Long physicalNetworkId = cmd.getPhysicalNetworkId();
 +        Long zoneId = cmd.getZoneId();
 +
 +        Long accountId = null;
 +        if (accountName != null && domainId != null) {
 +            if (projectId != null) {
 +                throw new InvalidParameterValueException("Account and projectId can't be specified together");
 +            }
 +            Account account = _accountDao.findActiveAccount(accountName, domainId);
 +            if (account == null) {
 +                InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find account " + accountName);
 +                DomainVO domain = ApiDBUtils.findDomainById(domainId);
 +                String domainUuid = domainId.toString();
 +                if (domain != null) {
 +                    domainUuid = domain.getUuid();
 +                }
 +                ex.addProxyObject(domainUuid, "domainId");
 +                throw ex;
 +            } else {
 +                accountId = account.getId();
 +            }
 +        }
 +
 +        // set project information
 +        if (projectId != null) {
 +            Project project = _projectMgr.getProject(projectId);
 +            if (project == null) {
 +                throwInvalidIdException("Unable to find project by id " + projectId, projectId.toString(), "projectId");
 +            }
 +            accountId = project.getProjectAccountId();
 +        }
 +
 +        SearchBuilder<AccountGuestVlanMapVO> sb = _accountGuestVlanMapDao.createSearchBuilder();
 +        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
 +        sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
 +        sb.and("guestVlanRange", sb.entity().getGuestVlanRange(), SearchCriteria.Op.EQ);
 +        sb.and("physicalNetworkId", sb.entity().getPhysicalNetworkId(), SearchCriteria.Op.EQ);
 +
 +        if (zoneId != null) {
 +            SearchBuilder<PhysicalNetworkVO> physicalnetworkSearch = _physicalNetworkDao.createSearchBuilder();
 +            physicalnetworkSearch.and("zoneId", physicalnetworkSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
 +            sb.join("physicalnetworkSearch", physicalnetworkSearch, sb.entity().getPhysicalNetworkId(), physicalnetworkSearch.entity().getId(), JoinBuilder.JoinType.INNER);
 +        }
 +
 +        SearchCriteria<AccountGuestVlanMapVO> sc = sb.create();
 +        if (id != null) {
 +            sc.setParameters("id", id);
 +        }
 +
 +        if (accountId != null) {
 +            sc.setParameters("accountId", accountId);
 +        }
 +
 +        if (guestVlanRange != null) {
 +            sc.setParameters("guestVlanRange", guestVlanRange);
 +        }
 +
 +        if (physicalNetworkId != null) {
 +            sc.setParameters("physicalNetworkId", physicalNetworkId);
 +        }
 +
 +        if (zoneId != null) {
 +            sc.setJoinParameters("physicalnetworkSearch", "zoneId", zoneId);
 +        }
 +
 +        Filter searchFilter = new Filter(AccountGuestVlanMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
 +        Pair<List<AccountGuestVlanMapVO>, Integer> result = _accountGuestVlanMapDao.searchAndCount(sc, searchFilter);
 +        return new Pair<List<? extends GuestVlan>, Integer>(result.first(), result.second());
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_DEDICATED_GUEST_VLAN_RANGE_RELEASE, eventDescription = "releasing" + " dedicated guest vlan range", async = true)
 +    @DB
 +    public boolean releaseDedicatedGuestVlanRange(Long dedicatedGuestVlanRangeId) {
 +        // Verify dedicated range exists
 +        AccountGuestVlanMapVO dedicatedGuestVlan = _accountGuestVlanMapDao.findById(dedicatedGuestVlanRangeId);
 +        if (dedicatedGuestVlan == null) {
 +            throw new InvalidParameterValueException("Dedicated guest vlan with specified" + " id doesn't exist in the system");
 +        }
 +
 +        // Remove dedication for the guest vlan
 +        _datacneterVnet.releaseDedicatedGuestVlans(dedicatedGuestVlan.getId());
 +        if (_accountGuestVlanMapDao.remove(dedicatedGuestVlanRangeId)) {
 +            return true;
 +        } else {
 +            return false;
 +        }
 +    }
 +
 +    @Override
 +    public List<? extends Service> listNetworkServices(String providerName) {
 +
 +        Provider provider = null;
 +        if (providerName != null) {
 +            provider = Network.Provider.getProvider(providerName);
 +            if (provider == null) {
 +                throw new InvalidParameterValueException("Invalid Network Service Provider=" + providerName);
 +            }
 +        }
 +
 +        if (provider != null) {
 +            NetworkElement element = _networkModel.getElementImplementingProvider(providerName);
 +            if (element == null) {
 +                throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + providerName + "'");
 +            }
 +            return new ArrayList<Service>(element.getCapabilities().keySet());
 +        } else {
 +            return Service.listAllServices();
 +        }
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_SERVICE_PROVIDER_CREATE, eventDescription = "Creating Physical Network ServiceProvider", create = true)
 +    public PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId, List<String> enabledServices) {
 +
 +        // verify input parameters
 +        PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId);
 +        if (network == null) {
 +            throwInvalidIdException("Physical Network with specified id doesn't exist in the system", physicalNetworkId.toString(), "physicalNetworkId");
 +        }
 +
 +        // verify input parameters
 +        if (destinationPhysicalNetworkId != null) {
 +            PhysicalNetworkVO destNetwork = _physicalNetworkDao.findById(destinationPhysicalNetworkId);
 +            if (destNetwork == null) {
 +                throwInvalidIdException("Destination Physical Network with specified id doesn't exist in the system", destinationPhysicalNetworkId.toString(),
 +                                        "destinationPhysicalNetworkId");
 +            }
 +        }
 +
 +        if (providerName != null) {
 +            Provider provider = Network.Provider.getProvider(providerName);
 +            if (provider == null) {
 +                throw new InvalidParameterValueException("Invalid Network Service Provider=" + providerName);
 +            }
 +        }
 +
 +        if (_pNSPDao.findByServiceProvider(physicalNetworkId, providerName) != null) {
 +            // TBD: send uuid instead of physicalNetworkId.
 +            throw new CloudRuntimeException("The '" + providerName + "' provider already exists on physical network : " + physicalNetworkId);
 +        }
 +
 +        // check if services can be turned off
 +        NetworkElement element = _networkModel.getElementImplementingProvider(providerName);
 +        if (element == null) {
 +            throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + providerName + "'");
 +        }
 +        List<Service> services = new ArrayList<Service>();
 +
 +        if (enabledServices != null) {
 +            if (!element.canEnableIndividualServices()) {
 +                if (enabledServices.size() != element.getCapabilities().keySet().size()) {
 +                    throw new InvalidParameterValueException("Cannot enable subset of Services, Please specify the complete list of Services for this Service Provider '"
 +                            + providerName + "'");
 +                }
 +            }
 +
 +            // validate Services
 +            boolean addGatewayService = false;
 +            for (String serviceName : enabledServices) {
 +                Network.Service service = Network.Service.getService(serviceName);
 +                if (service == null || service == Service.Gateway) {
 +                    throw new InvalidParameterValueException("Invalid Network Service specified=" + serviceName);
 +                } else if (service == Service.SourceNat) {
 +                    addGatewayService = true;
 +                }
 +
 +                // check if the service is provided by this Provider
 +                if (!element.getCapabilities().containsKey(service)) {
 +                    throw new InvalidParameterValueException(providerName + " Provider cannot provide this Service specified=" + serviceName);
 +                }
 +                services.add(service);
 +            }
 +
 +            if (addGatewayService) {
 +                services.add(Service.Gateway);
 +            }
 +        } else {
 +            // enable all the default services supported by this element.
 +            services = new ArrayList<Service>(element.getCapabilities().keySet());
 +        }
 +
 +        try {
 +            // Create the new physical network in the database
 +            PhysicalNetworkServiceProviderVO nsp = new PhysicalNetworkServiceProviderVO(physicalNetworkId, providerName);
 +            // set enabled services
 +            nsp.setEnabledServices(services);
 +
 +            if (destinationPhysicalNetworkId != null) {
 +                nsp.setDestinationPhysicalNetworkId(destinationPhysicalNetworkId);
 +            }
 +            nsp = _pNSPDao.persist(nsp);
 +
 +            return nsp;
 +        } catch (Exception ex) {
 +            s_logger.warn("Exception: ", ex);
 +            throw new CloudRuntimeException("Fail to add a provider to physical network");
 +        }
 +
 +    }
 +
 +    @Override
 +    public Pair<List<? extends PhysicalNetworkServiceProvider>, Integer> listNetworkServiceProviders(Long physicalNetworkId, String name, String state, Long startIndex,
 +            Long pageSize) {
 +
 +        Filter searchFilter = new Filter(PhysicalNetworkServiceProviderVO.class, "id", false, startIndex, pageSize);
 +        SearchBuilder<PhysicalNetworkServiceProviderVO> sb = _pNSPDao.createSearchBuilder();
 +        SearchCriteria<PhysicalNetworkServiceProviderVO> sc = sb.create();
 +
 +        if (physicalNetworkId != null) {
 +            sc.addAnd("physicalNetworkId", Op.EQ, physicalNetworkId);
 +        }
 +
 +        if (name != null) {
 +            sc.addAnd("providerName", Op.EQ, name);
 +        }
 +
 +        if (state != null) {
 +            sc.addAnd("state", Op.EQ, state);
 +        }
 +
 +        Pair<List<PhysicalNetworkServiceProviderVO>, Integer> result =  _pNSPDao.searchAndCount(sc, searchFilter);
 +        return new Pair<List<? extends PhysicalNetworkServiceProvider>, Integer>(result.first(), result.second());
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_SERVICE_PROVIDER_UPDATE, eventDescription = "Updating physical network ServiceProvider", async = true)
 +    public PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, String stateStr, List<String> enabledServices) {
 +
 +        PhysicalNetworkServiceProviderVO provider = _pNSPDao.findById(id);
 +        if (provider == null) {
 +            throw new InvalidParameterValueException("Network Service Provider id=" + id + "doesn't exist in the system");
 +        }
 +
 +        NetworkElement element = _networkModel.getElementImplementingProvider(provider.getProviderName());
 +        if (element == null) {
 +            throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getProviderName() + "'");
 +        }
 +
 +        PhysicalNetworkServiceProvider.State state = null;
 +        if (stateStr != null && !stateStr.isEmpty()) {
 +            try {
 +                state = PhysicalNetworkServiceProvider.State.valueOf(stateStr);
 +            } catch (IllegalArgumentException ex) {
 +                throw new InvalidParameterValueException("Unable to resolve state '" + stateStr + "' to a supported value {Enabled or Disabled}");
 +            }
 +        }
 +
 +        boolean update = false;
 +
 +        if (state != null) {
 +            if (s_logger.isDebugEnabled()) {
 +                s_logger.debug("trying to update the state of the service provider id=" + id + " on physical network: " + provider.getPhysicalNetworkId() + " to state: "
 +                        + stateStr);
 +            }
 +            switch (state) {
 +            case Enabled:
 +                if (element != null && element.isReady(provider)) {
 +                    provider.setState(PhysicalNetworkServiceProvider.State.Enabled);
 +                    update = true;
 +                } else {
 +                    throw new CloudRuntimeException("Provider is not ready, cannot Enable the provider, please configure the provider first");
 +                }
 +                break;
 +            case Disabled:
 +                // do we need to do anything for the provider instances before disabling?
 +                provider.setState(PhysicalNetworkServiceProvider.State.Disabled);
 +                update = true;
 +                break;
 +            case Shutdown:
 +                throw new  InvalidParameterValueException("Updating the provider state to 'Shutdown' is not supported");
 +            }
 +        }
 +
 +        if (enabledServices != null) {
 +            // check if services can be turned of
 +            if (!element.canEnableIndividualServices()) {
 +                throw new InvalidParameterValueException("Cannot update set of Services for this Service Provider '" + provider.getProviderName() + "'");
 +            }
 +
 +            // validate Services
 +            List<Service> services = new ArrayList<Service>();
 +            for (String serviceName : enabledServices) {
 +                Network.Service service = Network.Service.getService(serviceName);
 +                if (service == null) {
 +                    throw new InvalidParameterValueException("Invalid Network Service specified=" + serviceName);
 +                }
 +                services.add(service);
 +            }
 +            // set enabled services
 +            provider.setEnabledServices(services);
 +            update = true;
 +        }
 +
 +        if (update) {
 +            _pNSPDao.update(id, provider);
 +        }
 +        return provider;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_SERVICE_PROVIDER_DELETE, eventDescription = "Deleting physical network ServiceProvider", async = true)
 +    public boolean deleteNetworkServiceProvider(Long id) throws ConcurrentOperationException, ResourceUnavailableException {
 +        PhysicalNetworkServiceProviderVO provider = _pNSPDao.findById(id);
 +
 +        if (provider == null) {
 +            throw new InvalidParameterValueException("Network Service Provider id=" + id + "doesn't exist in the system");
 +        }
 +
 +        // check if there are networks using this provider
 +        List<NetworkVO> networks = _networksDao.listByPhysicalNetworkAndProvider(provider.getPhysicalNetworkId(), provider.getProviderName());
 +        if (networks != null && !networks.isEmpty()) {
 +            throw new CloudRuntimeException(
 +                    "Provider is not deletable because there are active networks using this provider, please upgrade these networks to new network offerings");
 +        }
 +
 +        User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId());
 +        Account callerAccount = _accountMgr.getActiveAccountById(callerUser.getAccountId());
 +        // shutdown the provider instances
 +        ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount);
 +        if (s_logger.isDebugEnabled()) {
 +            s_logger.debug("Shutting down the service provider id=" + id + " on physical network: " + provider.getPhysicalNetworkId());
 +        }
 +        NetworkElement element = _networkModel.getElementImplementingProvider(provider.getProviderName());
 +        if (element == null) {
 +            throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getProviderName() + "'");
 +        }
 +
 +        if (element != null && element.shutdownProviderInstances(provider, context)) {
 +            provider.setState(PhysicalNetworkServiceProvider.State.Shutdown);
 +        }
 +
 +        return _pNSPDao.remove(id);
 +    }
 +
 +    @Override
 +    public PhysicalNetwork getPhysicalNetwork(Long physicalNetworkId) {
 +        return _physicalNetworkDao.findById(physicalNetworkId);
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_CREATE, eventDescription = "Creating Physical Network", async = true)
 +    public PhysicalNetwork getCreatedPhysicalNetwork(Long physicalNetworkId) {
 +        return getPhysicalNetwork(physicalNetworkId);
 +    }
 +
 +    @Override
 +    public PhysicalNetworkServiceProvider getPhysicalNetworkServiceProvider(Long providerId) {
 +        return _pNSPDao.findById(providerId);
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_SERVICE_PROVIDER_CREATE, eventDescription = "Creating Physical Network ServiceProvider", async = true)
 +    public PhysicalNetworkServiceProvider getCreatedPhysicalNetworkServiceProvider(Long providerId) {
 +        return getPhysicalNetworkServiceProvider(providerId);
 +    }
 +
 +    @Override
 +    public long findPhysicalNetworkId(long zoneId, String tag, TrafficType trafficType) {
 +        List<PhysicalNetworkVO> pNtwks = new ArrayList<PhysicalNetworkVO>();
 +        if (trafficType != null) {
 +            pNtwks = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, trafficType);
 +        } else {
 +            pNtwks = _physicalNetworkDao.listByZone(zoneId);
 +        }
 +
 +        if (pNtwks.isEmpty()) {
 +            throw new InvalidParameterValueException("Unable to find physical network in zone id=" + zoneId);
 +        }
 +
 +        if (pNtwks.size() > 1) {
 +            if (tag == null) {
 +                throw new InvalidParameterValueException("More than one physical networks exist in zone id=" + zoneId + " and no tags are specified in order to make a choice");
 +            }
 +
 +            Long pNtwkId = null;
 +            for (PhysicalNetwork pNtwk : pNtwks) {
 +                if (pNtwk.getTags().contains(tag)) {
 +                    s_logger.debug("Found physical network id=" + pNtwk.getId() + " based on requested tags " + tag);
 +                    pNtwkId = pNtwk.getId();
 +                    break;
 +                }
 +            }
 +            if (pNtwkId == null) {
 +                throw new InvalidParameterValueException("Unable to find physical network which match the tags " + tag);
 +            }
 +            return pNtwkId;
 +        } else {
 +            return pNtwks.get(0).getId();
 +        }
 +    }
 +
 +    @Override
 +    @DB
 +    @ActionEvent(eventType = EventTypes.EVENT_TRAFFIC_TYPE_CREATE, eventDescription = "Creating Physical Network TrafficType", create = true)
 +    public PhysicalNetworkTrafficType addTrafficTypeToPhysicalNetwork(Long physicalNetworkId, String trafficTypeStr, String isolationMethod, String xenLabel, String kvmLabel, String vmwareLabel,
 +            String simulatorLabel, String vlan, String hypervLabel, String ovm3Label) {
 +
 +        // verify input parameters
 +        PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId);
 +        if (network == null) {
 +            throw new InvalidParameterValueException("Physical Network id=" + physicalNetworkId + "doesn't exist in the system");
 +        }
 +
 +        Networks.TrafficType trafficType = null;
 +        if (trafficTypeStr != null && !trafficTypeStr.isEmpty()) {
 +            try {
 +                trafficType = Networks.TrafficType.valueOf(trafficTypeStr);
 +            } catch (IllegalArgumentException ex) {
 +                throw new InvalidParameterValueException("Unable to resolve trafficType '" + trafficTypeStr + "' to a supported value");
 +            }
 +        }
 +
 +        if (_pNTrafficTypeDao.isTrafficTypeSupported(physicalNetworkId, trafficType)) {
 +            throw new CloudRuntimeException("This physical network already supports the traffic type: " + trafficType);
 +        }
 +        // For Storage, Control, Management, Public check if the zone has any other physical network with this
 +        // traffictype already present
 +        // If yes, we cant add these traffics to one more physical network in the zone.
 +
 +        if (TrafficType.isSystemNetwork(trafficType) || TrafficType.Public.equals(trafficType) || TrafficType.Storage.equals(trafficType)) {
 +            if (!_physicalNetworkDao.listByZoneAndTrafficType(network.getDataCenterId(), trafficType).isEmpty()) {
 +                throw new CloudRuntimeException("Fail to add the traffic type to physical network because Zone already has a physical network with this traffic type: "
 +                        + trafficType);
 +            }
 +        }
 +
 +        if (TrafficType.Storage.equals(trafficType)) {
 +            List<SecondaryStorageVmVO> ssvms = _stnwMgr.getSSVMWithNoStorageNetwork(network.getDataCenterId());
 +            if (!ssvms.isEmpty()) {
 +                StringBuilder sb = new StringBuilder(
 +                        "Cannot add "
 +                                + trafficType
 +                                + " traffic type as there are below secondary storage vm still running. Please stop them all and add Storage traffic type again, then destory them all to allow CloudStack recreate them with storage network(If you have added storage network ip range)");
 +                sb.append("SSVMs:");
 +                for (SecondaryStorageVmVO ssvm : ssvms) {
 +                    sb.append(ssvm.getInstanceName()).append(":").append(ssvm.getState());
 +                }
 +                throw new CloudRuntimeException(sb.toString());
 +            }
 +        }
 +
 +        try {
 +            // Create the new traffic type in the database
 +            if (xenLabel == null) {
 +                xenLabel = getDefaultXenNetworkLabel(trafficType);
 +            }
 +            PhysicalNetworkTrafficTypeVO pNetworktrafficType = new PhysicalNetworkTrafficTypeVO(physicalNetworkId, trafficType, xenLabel, kvmLabel, vmwareLabel, simulatorLabel,
 +                    vlan, hypervLabel, ovm3Label);
 +            pNetworktrafficType = _pNTrafficTypeDao.persist(pNetworktrafficType);
 +
 +            // For public traffic, get isolation method of physical network and update the public network accordingly
 +            // each broadcast type will individually need to be qualified for support of public traffic
 +            if (TrafficType.Public.equals(trafficType)){
 +            List<String> isolationMethods = network.getIsolationMethods();
 +            if ((isolationMethods.size() == 1 && isolationMethods.get(0).toLowerCase().equals("vxlan"))
 +                || (isolationMethod != null && isolationMethods.contains(isolationMethod) && isolationMethod.toLowerCase().equals("vxlan"))) {
 +                // find row in networks table that is defined as 'Public', created when zone was deployed
 +                NetworkVO publicNetwork = _networksDao.listByZoneAndTrafficType(network.getDataCenterId(),TrafficType.Public).get(0);
 +                if (publicNetwork != null) {
 +                    s_logger.debug("setting public network " + publicNetwork + " to broadcast type vxlan");
 +                    publicNetwork.setBroadcastDomainType(BroadcastDomainType.Vxlan);
 +                    _networksDao.persist(publicNetwork);
 +                }
 +            }
 +            }
 +
 +            return pNetworktrafficType;
 +        } catch (Exception ex) {
 +            s_logger.warn("Exception: ", ex);
 +            throw new CloudRuntimeException("Fail to add a traffic type to physical network");
 +        }
 +
 +    }
 +
 +    private String getDefaultXenNetworkLabel(TrafficType trafficType) {
 +        String xenLabel = null;
 +        switch (trafficType) {
 +        case Public:
 +            xenLabel = _configDao.getValue(Config.XenServerPublicNetwork.key());
 +            break;
 +        case Guest:
 +            xenLabel = _configDao.getValue(Config.XenServerGuestNetwork.key());
 +            break;
 +        case Storage:
 +            xenLabel = _configDao.getValue(Config.XenServerStorageNetwork1.key());
 +            break;
 +        case Management:
 +            xenLabel = _configDao.getValue(Config.XenServerPrivateNetwork.key());
 +            break;
 +        case Control:
 +            xenLabel = "cloud_link_local_network";
 +            break;
 +        case Vpn:
 +        case None:
 +            break;
 +        }
 +        return xenLabel;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_TRAFFIC_TYPE_CREATE, eventDescription = "Creating Physical Network TrafficType", async = true)
 +    public PhysicalNetworkTrafficType getPhysicalNetworkTrafficType(Long id) {
 +        return _pNTrafficTypeDao.findById(id);
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_TRAFFIC_TYPE_UPDATE, eventDescription = "Updating physical network TrafficType", async = true)
 +    public PhysicalNetworkTrafficType updatePhysicalNetworkTrafficType(Long id, String xenLabel, String kvmLabel, String vmwareLabel, String hypervLabel, String ovm3Label) {
 +
 +        PhysicalNetworkTrafficTypeVO trafficType = _pNTrafficTypeDao.findById(id);
 +
 +        if (trafficType == null) {
 +            throw new InvalidParameterValueException("Traffic Type with id=" + id + "doesn't exist in the system");
 +        }
 +
 +        if (xenLabel != null) {
 +            if ("".equals(xenLabel)) {
 +                xenLabel = null;
 +            }
 +            trafficType.setXenNetworkLabel(xenLabel);
 +        }
 +        if (kvmLabel != null) {
 +            if ("".equals(kvmLabel)) {
 +                kvmLabel = null;
 +            }
 +            trafficType.setKvmNetworkLabel(kvmLabel);
 +        }
 +        if (vmwareLabel != null) {
 +            if ("".equals(vmwareLabel)) {
 +                vmwareLabel = null;
 +            }
 +            trafficType.setVmwareNetworkLabel(vmwareLabel);
 +        }
 +
 +        if (hypervLabel != null) {
 +            if ("".equals(hypervLabel)) {
 +                hypervLabel = null;
 +            }
 +            trafficType.setHypervNetworkLabel(hypervLabel);
 +        }
 +
 +        if (ovm3Label != null) {
 +            if ("".equals(ovm3Label)) {
 +                ovm3Label = null;
 +            }
 +            trafficType.setOvm3NetworkLabel(ovm3Label);
 +        }
 +        _pNTrafficTypeDao.update(id, trafficType);
 +        return trafficType;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_TRAFFIC_TYPE_DELETE, eventDescription = "Deleting physical network TrafficType", async = true)
 +    public boolean deletePhysicalNetworkTrafficType(Long id) {
 +        PhysicalNetworkTrafficTypeVO trafficType = _pNTrafficTypeDao.findById(id);
 +
 +        if (trafficType == null) {
 +            throw new InvalidParameterValueException("Traffic Type with id=" + id + "doesn't exist in the system");
 +        }
 +
 +        // check if there are any networks associated to this physical network with this traffic type
 +        if (TrafficType.Guest.equals(trafficType.getTrafficType())) {
 +            if (!_networksDao.listByPhysicalNetworkTrafficType(trafficType.getPhysicalNetworkId(), trafficType.getTrafficType()).isEmpty()) {
 +                throw new CloudRuntimeException("The Traffic Type is not deletable because there are existing networks with this traffic type:" + trafficType.getTrafficType());
 +            }
 +        } else if (TrafficType.Storage.equals(trafficType.getTrafficType())) {
 +            PhysicalNetworkVO pn = _physicalNetworkDao.findById(trafficType.getPhysicalNetworkId());
 +            if (_stnwMgr.isAnyStorageIpInUseInZone(pn.getDataCenterId())) {
 +                throw new CloudRuntimeException("The Traffic Type is not deletable because there are still some storage network ip addresses in use:"
 +                        + trafficType.getTrafficType());
 +            }
 +        }
 +        return _pNTrafficTypeDao.remove(id);
 +    }
 +
 +    @Override
 +    public Pair<List<? extends PhysicalNetworkTrafficType>, Integer> listTrafficTypes(Long physicalNetworkId) {
 +        PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId);
 +        if (network == null) {
 +            throwInvalidIdException("Physical Network with specified id doesn't exist in the system", physicalNetworkId.toString(), "physicalNetworkId");
 +        }
 +
 +        Pair<List<PhysicalNetworkTrafficTypeVO>, Integer> result = _pNTrafficTypeDao.listAndCountBy(physicalNetworkId);
 +        return new Pair<List<? extends PhysicalNetworkTrafficType>, Integer>(result.first(), result.second());
 +    }
 +
 +    @Override
 +    //TODO: duplicated in NetworkModel
 +    public NetworkVO getExclusiveGuestNetwork(long zoneId) {
 +        List<NetworkVO> networks = _networksDao.listBy(Account.ACCOUNT_ID_SYSTEM, zoneId, GuestType.Shared, TrafficType.Guest);
 +        if (networks == null || networks.isEmpty()) {
 +            throw new InvalidParameterValueException("Unable to find network with trafficType " + TrafficType.Guest + " and guestType " + GuestType.Shared + " in zone " + zoneId);
 +        }
 +
 +        if (networks.size() > 1) {
 +            throw new InvalidParameterValueException("Found more than 1 network with trafficType " + TrafficType.Guest + " and guestType " + GuestType.Shared + " in zone "
 +                    + zoneId);
 +
 +        }
 +
 +        return networks.get(0);
 +    }
 +
 +    protected PhysicalNetworkServiceProvider addDefaultVirtualRouterToPhysicalNetwork(long physicalNetworkId) {
 +
 +        PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.VirtualRouter.getName(), null, null);
 +        // add instance of the provider
 +        NetworkElement networkElement = _networkModel.getElementImplementingProvider(Network.Provider.VirtualRouter.getName());
 +        if (networkElement == null) {
 +            throw new CloudRuntimeException("Unable to find the Network Element implementing the VirtualRouter Provider");
 +        }
 +
 +        VirtualRouterElement element = (VirtualRouterElement)networkElement;
 +        element.addElement(nsp.getId(), Type.VirtualRouter);
 +
 +        return nsp;
 +    }
 +
 +    private PhysicalNetworkServiceProvider addDefaultOvsToPhysicalNetwork(long physicalNetworkId) {
 +        PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.Ovs.getName(), null, null);
 +        NetworkElement networkElement = _networkModel.getElementImplementingProvider(Network.Provider.Ovs.getName());
 +        if (networkElement == null) {
 +            throw new CloudRuntimeException("Unable to find the Network Element implementing the Ovs Provider");
 +        }
 +        OvsProviderVO element = _ovsProviderDao.findByNspId(nsp.getId());
 +        if (element != null) {
 +            s_logger.debug("There is already a Ovs element with service provider id " + nsp.getId());
 +            return nsp;
 +        }
 +        element = new OvsProviderVO(nsp.getId());
 +        _ovsProviderDao.persist(element);
 +        return nsp;
 +    }
 +
 +    protected PhysicalNetworkServiceProvider addDefaultVpcVirtualRouterToPhysicalNetwork(long physicalNetworkId) {
 +
 +        PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.VPCVirtualRouter.getName(), null, null);
 +
 +        NetworkElement networkElement =  _networkModel.getElementImplementingProvider(Network.Provider.VPCVirtualRouter.getName());
 +        if (networkElement == null) {
 +            throw new CloudRuntimeException("Unable to find the Network Element implementing the VPCVirtualRouter Provider");
 +        }
 +
 +        VpcVirtualRouterElement element = (VpcVirtualRouterElement)networkElement;
 +        element.addElement(nsp.getId(), Type.VPCVirtualRouter);
 +
 +        return nsp;
 +    }
 +
 +    protected PhysicalNetworkServiceProvider addDefaultInternalLbProviderToPhysicalNetwork(long physicalNetworkId) {
 +
 +        PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.InternalLbVm.getName(), null, null);
 +
 +        NetworkElement networkElement =  _networkModel.getElementImplementingProvider(Network.Provider.InternalLbVm.getName());
 +        if (networkElement == null) {
 +            throw new CloudRuntimeException("Unable to find the Network Element implementing the " + Network.Provider.InternalLbVm.getName() + " Provider");
 +        }
 +
 +        _internalLbElementSvc.addInternalLoadBalancerElement(nsp.getId());
 +
 +        return nsp;
 +    }
 +
 +    protected PhysicalNetworkServiceProvider addDefaultSecurityGroupProviderToPhysicalNetwork(long physicalNetworkId) {
 +
 +        PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.SecurityGroupProvider.getName(), null, null);
 +
 +        return nsp;
 +    }
 +
 +    private PhysicalNetworkServiceProvider addDefaultBaremetalProvidersToPhysicalNetwork(long physicalNetworkId) {
 +        PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId);
 +        DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId());
 +        if (dvo.getNetworkType() == NetworkType.Basic) {
 +
 +            Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider");
 +            if (provider == null) {
 +                // baremetal is not loaded
 +                return null;
 +            }
 +
 +            addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalDhcpProvider", null, null);
 +            addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null);
 +            addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalUserdataProvider", null, null);
 +        } else if (dvo.getNetworkType() == NetworkType.Advanced) {
 +            addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null);
 +            enableProvider("BaremetalPxeProvider");
 +        }
 +
 +        return null;
 +    }
 +
 +    private void enableProvider(String providerName) {
 +        QueryBuilder<PhysicalNetworkServiceProviderVO> q = QueryBuilder.create(PhysicalNetworkServiceProviderVO.class);
 +        q.and(q.entity().getProviderName(), SearchCriteria.Op.EQ, providerName);
 +        PhysicalNetworkServiceProviderVO provider = q.find();
 +        provider.setState(PhysicalNetworkServiceProvider.State.Enabled);
 +        _pNSPDao.update(provider.getId(), provider);
 +    }
 +
 +    private PhysicalNetworkServiceProvider addConfigDriveToPhysicalNetwork(long physicalNetworkId) {
 +        PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId);
 +        DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId());
 +        if (dvo.getNetworkType() == NetworkType.Advanced) {
 +
 +            Provider provider = Network.Provider.getProvider("ConfigDrive");
 +            if (provider == null) {
 +                return null;
 +            }
 +
 +            addProviderToPhysicalNetwork(physicalNetworkId, Provider.ConfigDrive.getName(), null, null);
 +            enableProvider(Provider.ConfigDrive.getName());
 +        }
 +        return null;
 +
 +    }
 +    protected boolean isNetworkSystem(Network network) {
 +        NetworkOffering no = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());
 +        if (no.isSystemOnly()) {
 +            return true;
 +        } else {
 +            return false;
 +        }
 +    }
 +
 +    private boolean getAllowSubdomainAccessGlobal() {
 +        return _allowSubdomainNetworkAccess;
 +    }
 +
 +    @Override
 +    public List<Pair<TrafficType, String>> listTrafficTypeImplementor(ListTrafficTypeImplementorsCmd cmd) {
 +        String type = cmd.getTrafficType();
 +        List<Pair<TrafficType, String>> results = new ArrayList<Pair<TrafficType, String>>();
 +        if (type != null) {
 +            for (NetworkGuru guru : _networkGurus) {
 +                if (guru.isMyTrafficType(TrafficType.getTrafficType(type))) {
 +                    results.add(new Pair<TrafficType, String>(TrafficType.getTrafficType(type), guru.getName()));
 +                    break;
 +                }
 +            }
 +        } else {
 +            for (NetworkGuru guru : _networkGurus) {
 +                TrafficType[] allTypes = guru.getSupportedTrafficType();
 +                for (TrafficType t : allTypes) {
 +                    results.add(new Pair<TrafficType, String>(t, guru.getName()));
 +                }
 +            }
 +        }
 +
 +        return results;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "associating Ip", async = true)
 +    public IpAddress associateIPToNetwork(long ipId, long networkId) throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException,
 +            ConcurrentOperationException {
 +
 +        Network network = _networksDao.findById(networkId);
 +        if (network == null) {
 +            // release the acquired IP addrress before throwing the exception
 +            // else it will always be in allocating state
 +            releaseIpAddress(ipId);
 +            throw new InvalidParameterValueException("Invalid network id is given");
 +        }
 +
 +        if (network.getVpcId() != null) {
 +            // release the acquired IP addrress before throwing the exception
 +            // else it will always be in allocating state
 +            releaseIpAddress(ipId);
 +            throw new InvalidParameterValueException("Can't assign ip to the network directly when network belongs" + " to VPC.Specify vpcId to associate ip address to VPC");
 +        }
 +        return _ipAddrMgr.associateIPToGuestNetwork(ipId, networkId, true);
 +
 +    }
 +
 +    @Override
 +    @DB
 +    public Network createPrivateNetwork(final String networkName, final String displayText, long physicalNetworkId, String broadcastUriString, final String startIp, String endIp,
 +            final String gateway, String netmask, final long networkOwnerId, final Long vpcId, final Boolean sourceNat, final Long networkOfferingId)
 +                    throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException {
 +
 +        final Account owner = _accountMgr.getAccount(networkOwnerId);
 +
 +        // Get system network offering
 +        NetworkOfferingVO ntwkOff = null;
 +        if (networkOfferingId != null) {
 +            ntwkOff = _networkOfferingDao.findById(networkOfferingId);
 +        }
 +        if (ntwkOff == null) {
 +            ntwkOff = findSystemNetworkOffering(NetworkOffering.SystemPrivateGatewayNetworkOffering);
 +        }
 +
 +        // Validate physical network
 +        final PhysicalNetwork pNtwk = _physicalNetworkDao.findById(physicalNetworkId);
 +        if (pNtwk == null) {
 +            throwInvalidIdException("Unable to find a physical network" + " having the given id", String.valueOf(physicalNetworkId), "physicalNetworkId");
 +        }
 +
 +        // VALIDATE IP INFO
 +        // if end ip is not specified, default it to startIp
 +        if (!NetUtils.isValidIp4(startIp)) {
 +            throw new InvalidParameterValueException("Invalid format for the ip address parameter");
 +        }
 +        if (endIp == null) {
 +            endIp = startIp;
 +        } else if (!NetUtils.isValidIp4(endIp)) {
 +            throw new InvalidParameterValueException("Invalid format for the endIp address parameter");
 +        }
 +
 +        if (!NetUtils.isValidIp4(gateway)) {
 +            throw new InvalidParameterValueException("Invalid gateway");
 +        }
 +        if (!NetUtils.isValidIp4Netmask(netmask)) {
 +            throw new InvalidParameterValueException("Invalid netmask");
 +        }
 +
 +        final String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask);
 +
 +        URI uri = BroadcastDomainType.fromString(broadcastUriString);
 +        final String uriString = uri.toString();
 +        BroadcastDomainType tiep = BroadcastDomainType.getSchemeValue(uri);
 +        // numeric vlan or vlan uri are ok for now
 +        // TODO make a test for any supported scheme
 +        if (!(tiep == BroadcastDomainType.Vlan || tiep == BroadcastDomainType.Lswitch)) {
 +            throw new InvalidParameterValueException("unsupported type of broadcastUri specified: " + broadcastUriString);
 +        }
 +
 +        final NetworkOfferingVO ntwkOffFinal = ntwkOff;
 +        try {
 +            return Transaction.execute(new TransactionCallbackWithException<Network, Exception>() {
 +                @Override
 +                public Network doInTransaction(TransactionStatus status) throws ResourceAllocationException, InsufficientCapacityException {
 +                    //lock datacenter as we need to get mac address seq from there
 +                    DataCenterVO dc = _dcDao.lockRow(pNtwk.getDataCenterId(), true);
 +
 +                    //check if we need to create guest network
 +                    Network privateNetwork = _networksDao.getPrivateNetwork(uriString, cidr, networkOwnerId, pNtwk.getDataCenterId(), networkOfferingId);
 +                    if (privateNetwork == null) {
 +                        //create Guest network
 +                        privateNetwork = _networkMgr.createGuestNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, false, null, owner, null, pNtwk,
 +                                                                        pNtwk.getDataCenterId(), ACLType.Account, null, vpcId, null, null, true, null, null);
 +                        if (privateNetwork != null) {
 +                            s_logger.debug("Successfully created guest network " + privateNetwork);
 +                        } else {
 +                            throw new CloudRuntimeException("Creating guest network failed");
 +                        }
 +                    } else {
 +                        s_logger.debug("Private network already exists: " + privateNetwork);
 +                        //Do not allow multiple private gateways with same Vlan within a VPC
 +                        if (vpcId != null && vpcId.equals(privateNetwork.getVpcId())) {
 +                            throw new InvalidParameterValueException("Private network for the vlan: " + uriString + " and cidr  " + cidr + "  already exists " + "for Vpc " + vpcId
 +                                    + " in zone " + _entityMgr.findById(DataCenter.class, pNtwk.getDataCenterId()).getName());
 +                        }
 +                    }
 +                    if (vpcId != null) {
 +                        //add entry to private_ip_address table
 +                        PrivateIpVO privateIp = _privateIpDao.findByIpAndSourceNetworkIdAndVpcId(privateNetwork.getId(), startIp, vpcId);
 +                        if (privateIp != null) {
 +                            throw new InvalidParameterValueException("Private ip address " + startIp + " already used for private gateway" + " in zone "
 +                                    + _entityMgr.findById(DataCenter.class, pNtwk.getDataCenterId()).getName());
 +                        }
 +                        Long mac = dc.getMacAddress();
 +                        Long nextMac = mac + 1;
 +                        dc.setMacAddress(nextMac);
 +                        privateIp = new PrivateIpVO(startIp, privateNetwork.getId(), nextMac, vpcId, sourceNat);
 +                        _privateIpDao.persist(privateIp);
 +                        _dcDao.update(dc.getId(), dc);
 +                    }
 +
 +                    s_logger.debug("Private network " + privateNetwork + " is created");
 +
 +                    return privateNetwork;
 +                }
 +            });
 +        } catch (Exception e) {
 +            ExceptionUtil.rethrowRuntime(e);
 +            ExceptionUtil.rethrow(e, ResourceAllocationException.class);
 +            ExceptionUtil.rethrow(e, InsufficientCapacityException.class);
 +            throw new IllegalStateException(e);
 +        }
 +    }
 +
 +    private NetworkOfferingVO findSystemNetworkOffering(String offeringName) {
 +        List<NetworkOfferingVO> allOfferings = _networkOfferingDao.listSystemNetworkOfferings();
 +        for (NetworkOfferingVO offer : allOfferings) {
 +            if (offer.getName().equals(offeringName)) {
 +                return offer;
 +            }
 +        }
 +        return null;
 +    }
 +
 +    @Override
 +    public Network getNetwork(String networkUuid) {
 +       return _networksDao.findByUuid(networkUuid);
 +    }
 +
 +    @Override
 +    public List<? extends Nic> listNics(ListNicsCmd cmd) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        Long nicId = cmd.getNicId();
 +        long vmId = cmd.getVmId();
 +        String keyword = cmd.getKeyword();
 +        Long networkId = cmd.getNetworkId();
 +        UserVmVO  userVm = _userVmDao.findById(vmId);
 +
 +        if (userVm == null || (!userVm.isDisplayVm() && caller.getType() == Account.ACCOUNT_TYPE_NORMAL)) {
 +            throwInvalidIdException("Virtual machine id does not exist", Long.valueOf(vmId).toString(), "vmId");
 +            }
 +
 +        _accountMgr.checkAccess(caller, null, true, userVm);
 +        return _networkMgr.listVmNics(vmId, nicId, networkId, keyword);
 +    }
 +
 +    @Override
 +    public List<? extends NicSecondaryIp> listVmNicSecondaryIps(ListNicsCmd cmd)
 +    {
 +        Account caller = CallContext.current().getCallingAccount();
 +        Long nicId = cmd.getNicId();
 +        long vmId = cmd.getVmId();
 +        String keyword = cmd.getKeyword();
 +        UserVmVO  userVm = _userVmDao.findById(vmId);
 +
 +        if (userVm == null || (!userVm.isDisplayVm() && caller.getType() == Account.ACCOUNT_TYPE_NORMAL)) {
 +            throwInvalidIdException("Virtual machine id does not exist", Long.valueOf(vmId).toString(), "vmId");
 +        }
 +
 +        _accountMgr.checkAccess(caller, null, true, userVm);
 +        return _nicSecondaryIpDao.listSecondaryIpUsingKeyword(nicId, keyword);
 +    }
 +
 +    public List<NetworkGuru> getNetworkGurus() {
 +        return _networkGurus;
 +    }
 +
 +    @Inject
 +    public void setNetworkGurus(List<NetworkGuru> networkGurus) {
 +        _networkGurus = networkGurus;
 +    }
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_NET_IP_UPDATE, eventDescription = "updating public ip address", async = true)
 +    public IpAddress updateIP(Long id, String customId, Boolean displayIp) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        IPAddressVO ipVO = _ipAddressDao.findById(id);
 +        if (ipVO == null) {
 +            throw new InvalidParameterValueException("Unable to find ip address by id");
 +        }
 +
 +        // verify permissions
 +        if (ipVO.getAllocatedToAccountId() != null) {
 +            _accountMgr.checkAccess(caller, null, true, ipVO);
 +        } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
 +            throw new PermissionDeniedException("Only Root admin can update non-allocated ip addresses");
 +        }
 +
 +        if (customId != null) {
 +            ipVO.setUuid(customId);
 +        }
 +
 +        if (displayIp != null) {
 +            ipVO.setDisplay(displayIp);
 +        }
 +
 +        _ipAddressDao.update(id, ipVO);
 +        return _ipAddressDao.findById(id);
 +    }
 +
 +    @Override
 +    public AcquirePodIpCmdResponse allocatePodIp(Account ipOwner, String zoneId, String podId) throws ResourceAllocationException {
 +
 +        Account caller = CallContext.current().getCallingAccount();
 +        long callerUserId = CallContext.current().getCallingUserId();
 +        DataCenter zone = _entityMgr.findByUuid(DataCenter.class, zoneId);
 +
 +        if (zone == null)
 +            throw new InvalidParameterValueException("Invalid zone Id ");
 +        if (_accountMgr.checkAccessAndSpecifyAuthority(caller, zone.getId()) != zone.getId())
 +            throw new InvalidParameterValueException("Caller does not have permission for this Zone" + "(" + zoneId + ")");
 +        if (s_logger.isDebugEnabled())
 +            s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
 +        return _ipAddrMgr.allocatePodIp(zoneId, podId);
 +
 +    }
 +
 +    @Override
 +    public boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeException {
 +        _ipAddrMgr.releasePodIp(ip.getId());
 +        return true;
 +    }
 +
 +}

-- 
To stop receiving notification emails like this one, please contact
rohit@apache.org.