You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ko...@apache.org on 2013/04/15 15:30:52 UTC

[3/7] Squashed commit of the following:

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e94c7025/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoAsa1000vService.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoAsa1000vService.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoAsa1000vService.java
new file mode 100755
index 0000000..dff9288
--- /dev/null
+++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoAsa1000vService.java
@@ -0,0 +1,43 @@
+// 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.element;
+
+import java.util.List;
+
+import com.cloud.api.commands.AddCiscoAsa1000vResourceCmd;
+import com.cloud.api.commands.DeleteCiscoAsa1000vResourceCmd;
+import com.cloud.api.commands.ListCiscoAsa1000vResourcesCmd;
+import com.cloud.api.response.CiscoAsa1000vResourceResponse;
+import com.cloud.network.Network;
+import com.cloud.network.cisco.CiscoAsa1000vDevice;
+import com.cloud.network.cisco.CiscoAsa1000vDeviceVO;
+import com.cloud.utils.component.PluggableService;
+
+public interface CiscoAsa1000vService extends PluggableService {
+
+    public CiscoAsa1000vDevice addCiscoAsa1000vResource(AddCiscoAsa1000vResourceCmd cmd);
+
+    public CiscoAsa1000vResourceResponse createCiscoAsa1000vResourceResponse(
+            CiscoAsa1000vDevice ciscoAsa1000vDeviceVO);
+
+    boolean deleteCiscoAsa1000vResource(DeleteCiscoAsa1000vResourceCmd cmd);
+
+    List<CiscoAsa1000vDeviceVO> listCiscoAsa1000vResources(ListCiscoAsa1000vResourcesCmd cmd);
+
+    CiscoAsa1000vDevice assignAsa1000vToNetwork(Network network);
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e94c7025/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java
new file mode 100644
index 0000000..443bb40
--- /dev/null
+++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java
@@ -0,0 +1,928 @@
+// 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.element;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.AssociateAsaWithLogicalEdgeFirewallCommand;
+import com.cloud.agent.api.CleanupLogicalEdgeFirewallCommand;
+import com.cloud.agent.api.ConfigureNexusVsmForAsaCommand;
+import com.cloud.agent.api.CreateLogicalEdgeFirewallCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupExternalFirewallCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.api.routing.SetFirewallRulesCommand;
+import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
+import com.cloud.agent.api.routing.SetSourceNatCommand;
+import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
+import com.cloud.agent.api.to.FirewallRuleTO;
+import com.cloud.agent.api.to.IpAddressTO;
+import com.cloud.agent.api.to.PortForwardingRuleTO;
+import com.cloud.agent.api.to.StaticNatRuleTO;
+import com.cloud.api.commands.AddCiscoAsa1000vResourceCmd;
+import com.cloud.api.commands.AddCiscoVnmcResourceCmd;
+import com.cloud.api.commands.DeleteCiscoAsa1000vResourceCmd;
+import com.cloud.api.commands.DeleteCiscoVnmcResourceCmd;
+import com.cloud.api.commands.ListCiscoAsa1000vResourcesCmd;
+import com.cloud.api.commands.ListCiscoVnmcResourcesCmd;
+import com.cloud.api.response.CiscoAsa1000vResourceResponse;
+import com.cloud.api.response.CiscoVnmcResourceResponse;
+import com.cloud.configuration.ConfigurationManager;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.ClusterVSMMapVO;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.Vlan;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.VlanVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.ClusterVSMMapDao;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.DetailVO;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.CiscoNexusVSMDeviceVO;
+import com.cloud.network.IpAddress;
+import com.cloud.network.Network;
+import com.cloud.network.NetworkManager;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.PublicIpAddress;
+import com.cloud.network.addr.PublicIp;
+import com.cloud.network.cisco.CiscoAsa1000vDevice;
+import com.cloud.network.cisco.CiscoAsa1000vDeviceVO;
+import com.cloud.network.cisco.CiscoVnmcController;
+import com.cloud.network.cisco.CiscoVnmcControllerVO;
+import com.cloud.network.cisco.NetworkAsa1000vMapVO;
+import com.cloud.network.dao.CiscoAsa1000vDao;
+import com.cloud.network.dao.CiscoNexusVSMDeviceDao;
+import com.cloud.network.dao.CiscoVnmcDao;
+import com.cloud.network.dao.NetworkAsa1000vMapDao;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
+import com.cloud.network.resource.CiscoVnmcResource;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.PortForwardingRule;
+import com.cloud.network.rules.StaticNat;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.user.Account;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.net.NetUtils;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachine.Type;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Local(value = NetworkElement.class)
+public class CiscoVnmcElement extends AdapterBase implements SourceNatServiceProvider, FirewallServiceProvider,
+    PortForwardingServiceProvider, IpDeployer, StaticNatServiceProvider, ResourceStateAdapter, NetworkElement,
+    CiscoVnmcElementService, CiscoAsa1000vService {
+    private static final Logger s_logger = Logger.getLogger(CiscoVnmcElement.class);
+    private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
+
+    @Inject
+    AgentManager _agentMgr;
+    @Inject
+    ResourceManager _resourceMgr;
+    @Inject
+    ConfigurationManager _configMgr;
+    @Inject
+    NetworkManager _networkMgr;
+    @Inject
+    NetworkModel _networkModel;
+
+    @Inject
+    PhysicalNetworkDao _physicalNetworkDao;
+    @Inject
+    PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
+    @Inject 
+    HostDetailsDao _hostDetailsDao;
+    @Inject
+    HostDao _hostDao;
+    @Inject
+    NetworkDao _networkDao;
+    @Inject
+    ClusterDao _clusterDao;
+    @Inject
+    VlanDao _vlanDao;
+    @Inject
+    ClusterVSMMapDao _clusterVsmMapDao;
+    @Inject
+    CiscoNexusVSMDeviceDao _vsmDeviceDao;
+    @Inject
+    CiscoVnmcDao _ciscoVnmcDao;
+    @Inject
+    CiscoAsa1000vDao _ciscoAsa1000vDao;
+    @Inject
+    NetworkAsa1000vMapDao _networkAsa1000vMapDao;
+
+    protected boolean canHandle(Network network) {
+        if (network.getBroadcastDomainType() != BroadcastDomainType.Vlan) {
+            return false; //TODO: should handle VxLAN as well
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params)
+            throws ConfigurationException {
+        super.configure(name, params);
+        _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
+        return true;
+    }
+
+    private static Map<Service, Map<Capability, String>> setCapabilities() {
+        Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
+        capabilities.put(Service.Gateway, null);
+
+        Map<Capability, String> firewallCapabilities = new HashMap<Capability, String>();
+        firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
+        firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress,egress");
+        firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
+        firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp");
+        firewallCapabilities.put(Capability.MultipleIps, "true");
+        capabilities.put(Service.Firewall, firewallCapabilities);
+
+        capabilities.put(Service.StaticNat, null);
+        capabilities.put(Service.PortForwarding, null);
+
+        Map<Capability, String> sourceNatCapabilities = new HashMap<Capability, String>();
+        sourceNatCapabilities.put(Capability.SupportedSourceNatTypes, "peraccount");
+        sourceNatCapabilities.put(Capability.RedundantRouter, "false"); //TODO:
+        capabilities.put(Service.SourceNat, sourceNatCapabilities);
+        return capabilities;
+    }
+
+    @Override
+    public Map<Service, Map<Capability, String>> getCapabilities() {
+        return capabilities;
+    }
+
+    @Override
+    public Provider getProvider() {
+        return Provider.CiscoVnmc;
+    }
+
+    private boolean createLogicalEdgeFirewall(long vlanId,
+            String gateway, String gatewayNetmask,
+            String publicIp, String publicNetmask,
+            List<String> publicGateways, long hostId) {
+        CreateLogicalEdgeFirewallCommand cmd = new CreateLogicalEdgeFirewallCommand(vlanId, publicIp, gateway, publicNetmask, gatewayNetmask);
+        for (String publicGateway : publicGateways) {
+            cmd.getPublicGateways().add(publicGateway);
+        }
+        Answer answer = _agentMgr.easySend(hostId, cmd);
+        return answer.getResult();
+    }
+
+    private boolean configureNexusVsmForAsa(long vlanId, String gateway,
+            String vsmUsername, String vsmPassword, String vsmIp,
+            String asaInPortProfile, long hostId) {
+        ConfigureNexusVsmForAsaCommand cmd = new ConfigureNexusVsmForAsaCommand(vlanId, gateway, vsmUsername, vsmPassword, vsmIp, asaInPortProfile);
+        Answer answer = _agentMgr.easySend(hostId, cmd);
+        return answer.getResult();
+    }
+
+    private boolean configureSourceNat(long vlanId, String guestCidr,
+            PublicIp sourceNatIp, long hostId) {
+        boolean add = (sourceNatIp.getState() == IpAddress.State.Releasing ? false : true);
+        IpAddressTO ip = new IpAddressTO(sourceNatIp.getAccountId(), sourceNatIp.getAddress().addr(), add, false,
+                sourceNatIp.isSourceNat(), sourceNatIp.getVlanTag(), sourceNatIp.getGateway(), sourceNatIp.getNetmask(), sourceNatIp.getMacAddress(),
+                null, sourceNatIp.isOneToOneNat());
+        boolean addSourceNat = false;
+        if (sourceNatIp.isSourceNat()) {
+            addSourceNat = add;
+        }
+
+        SetSourceNatCommand cmd = new SetSourceNatCommand(ip, addSourceNat);
+        cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+        cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, guestCidr);
+        Answer answer = _agentMgr.easySend(hostId, cmd);
+        return answer.getResult();
+    }
+
+    private boolean associateAsaWithLogicalEdgeFirewall(long vlanId,
+            String asaMgmtIp, long hostId) {
+        AssociateAsaWithLogicalEdgeFirewallCommand cmd = 
+                new AssociateAsaWithLogicalEdgeFirewallCommand(vlanId, asaMgmtIp);
+        Answer answer = _agentMgr.easySend(hostId, cmd);
+        return answer.getResult();
+    }
+
+    @Override
+    public boolean implement(Network network, NetworkOffering offering,
+            DeployDestination dest, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException,
+            InsufficientCapacityException {
+        DataCenter zone = _configMgr.getZone(network.getDataCenterId());
+
+        if (zone.getNetworkType() == NetworkType.Basic) {
+            s_logger.debug("Not handling network implement in zone of type " + NetworkType.Basic);
+            return false;
+        }
+
+        if (!canHandle(network)) {
+            return false;
+        }
+
+        List<CiscoVnmcControllerVO> devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
+        if (devices.isEmpty()) {
+            s_logger.error("No Cisco Vnmc device on network " + network.getName());
+            return false;
+        }
+
+        List<CiscoAsa1000vDeviceVO> asaList = _ciscoAsa1000vDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
+        if (asaList.isEmpty()) {
+            s_logger.debug("No Cisco ASA 1000v device on network " + network.getName());
+            return false;
+        }
+
+        NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId());
+        if (asaForNetwork != null) {
+            s_logger.debug("Cisco ASA 1000v device already associated with network " + network.getName());
+            return true;
+        }
+
+        if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.SourceNat, Provider.CiscoVnmc)) {
+            s_logger.error("SourceNat service is not provided by Cisco Vnmc device on network " + network.getName());
+            return false;
+        }
+
+        Transaction txn = Transaction.currentTxn();
+        boolean status = false;
+        try {
+            txn.start();
+
+            // ensure that there is an ASA 1000v assigned to this network
+            CiscoAsa1000vDevice assignedAsa = assignAsa1000vToNetwork(network);
+            if (assignedAsa == null) {
+                s_logger.error("Unable to assign ASA 1000v device to network " + network.getName());
+                return false;
+            }
+
+            ClusterVO asaCluster = _clusterDao.findById(assignedAsa.getClusterId());
+            ClusterVSMMapVO clusterVsmMap = _clusterVsmMapDao.findByClusterId(assignedAsa.getClusterId());
+            if (clusterVsmMap == null) {
+                s_logger.error("Vmware cluster " + asaCluster.getName() + " has no Cisco Nexus VSM device associated with it");
+                return false;
+            }
+
+            CiscoNexusVSMDeviceVO vsmDevice = _vsmDeviceDao.findById(clusterVsmMap.getVsmId());
+            if (vsmDevice == null) {
+                s_logger.error("Unable to load details of Cisco Nexus VSM device associated with cluster " + asaCluster.getName());
+                return false;
+            }
+
+            CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0);
+            HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId());
+            _hostDao.loadDetails(ciscoVnmcHost);
+            Account owner = context.getAccount();
+            PublicIp sourceNatIp = _networkMgr.assignSourceNatIpAddressToGuestNetwork(owner, network);
+            String vlan = network.getBroadcastUri().getHost();
+            long vlanId = Long.parseLong(vlan);
+
+            List<VlanVO> vlanVOList = _vlanDao.listVlansByPhysicalNetworkId(network.getPhysicalNetworkId());
+            List<String> publicGateways = new ArrayList<String>();
+            for (VlanVO vlanVO : vlanVOList) {
+                publicGateways.add(vlanVO.getVlanGateway());
+            }
+
+            // create logical edge firewall in VNMC
+            String gatewayNetmask = NetUtils.getCidrNetmask(network.getCidr());
+            if (!createLogicalEdgeFirewall(vlanId, network.getGateway(), gatewayNetmask,
+                    sourceNatIp.getAddress().addr(), sourceNatIp.getNetmask(), publicGateways, ciscoVnmcHost.getId())) {
+                s_logger.error("Failed to create logical edge firewall in Cisco VNMC device for network " + network.getName());
+                return false;
+            }
+
+            // create stuff in VSM for ASA device
+            if (!configureNexusVsmForAsa(vlanId, network.getGateway(),
+                    vsmDevice.getUserName(), vsmDevice.getPassword(), vsmDevice.getipaddr(),
+                    assignedAsa.getInPortProfile(), ciscoVnmcHost.getId())) {
+                s_logger.error("Failed to configure Cisco Nexus VSM " + vsmDevice.getipaddr() +
+                        " for ASA device for network " + network.getName());
+                return false;
+            }
+
+            // configure source NAT
+            //if (!configureSourceNat(vlanId, network.getCidr(), sourceNatIp, ciscoVnmcHost.getId())) {
+            //    s_logger.error("Failed to configure source NAT in Cisco VNMC device for network " + network.getName());
+            //    return false;
+            //}
+
+            // associate Asa 1000v instance with logical edge firewall
+            if (!associateAsaWithLogicalEdgeFirewall(vlanId, assignedAsa.getManagementIp(), ciscoVnmcHost.getId())) {
+                s_logger.error("Failed to associate Cisco ASA 1000v (" + assignedAsa.getManagementIp() +
+                        ") with logical edge firewall in VNMC for network " + network.getName());
+                return false;
+            }
+
+            status = true;
+            txn.commit();
+        } finally {
+            if (!status) {
+                txn.rollback();
+                //FIXME: also undo changes in VNMC, VSM if anything failed
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean prepare(Network network, NicProfile nic,
+            VirtualMachineProfile<? extends VirtualMachine> vm,
+            DeployDestination dest, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException,
+            InsufficientCapacityException {
+        if (vm.getType() != Type.User) {
+            return false;
+        }
+
+        // ensure that there is an ASA 1000v assigned to this network
+        NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId());
+        if (asaForNetwork == null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean release(Network network, NicProfile nic,
+            VirtualMachineProfile<? extends VirtualMachine> vm,
+            ReservationContext context) throws ConcurrentOperationException,
+            ResourceUnavailableException {
+        return true;
+    }
+
+    private boolean cleanupLogicalEdgeFirewall(long vlanId, long hostId) {
+        CleanupLogicalEdgeFirewallCommand cmd = new CleanupLogicalEdgeFirewallCommand(vlanId);
+        Answer answer = _agentMgr.easySend(hostId, cmd);
+        return answer.getResult();
+    }
+
+    @Override
+    public boolean shutdown(Network network, ReservationContext context,
+            boolean cleanup) throws ConcurrentOperationException,
+            ResourceUnavailableException {
+
+        unassignAsa1000vFromNetwork(network);
+
+        String vlan = network.getBroadcastUri().getHost();
+        long vlanId = Long.parseLong(vlan);
+        List<CiscoVnmcControllerVO> devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
+        if (!devices.isEmpty()) {
+            CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0);
+            HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId());
+            cleanupLogicalEdgeFirewall(vlanId, ciscoVnmcHost.getId());
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean isReady(PhysicalNetworkServiceProvider provider) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean shutdownProviderInstances(
+            PhysicalNetworkServiceProvider provider, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean canEnableIndividualServices() {
+        return true;
+    }
+
+    @Override
+    public boolean verifyServicesCombination(Set<Service> services) {
+        if (!services.contains(Service.Firewall)) {
+            s_logger.warn("CiscoVnmc must be used as Firewall Service Provider in the network");
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean destroy(Network network, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException {
+        return true;
+    }
+
+    @Override
+    public List<Class<?>> getCommands() {
+        List<Class<?>> cmdList = new ArrayList<Class<?>>();
+        cmdList.add(AddCiscoVnmcResourceCmd.class);
+        cmdList.add(DeleteCiscoVnmcResourceCmd.class);
+        cmdList.add(ListCiscoVnmcResourcesCmd.class);
+        cmdList.add(AddCiscoAsa1000vResourceCmd.class);
+        cmdList.add(DeleteCiscoAsa1000vResourceCmd.class);
+        cmdList.add(ListCiscoAsa1000vResourcesCmd.class);
+        return cmdList;
+    }
+
+    @Override
+    public CiscoVnmcController addCiscoVnmcResource(AddCiscoVnmcResourceCmd cmd) {
+        String deviceName = Provider.CiscoVnmc.getName();
+        NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName);
+        Long physicalNetworkId = cmd.getPhysicalNetworkId();
+        CiscoVnmcController ciscoVnmcResource = null;
+
+        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork == null) {
+            throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId);
+        }
+        long zoneId = physicalNetwork.getDataCenterId();
+
+        PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(physicalNetwork.getId(), networkDevice.getNetworkServiceProvder());
+        if (ntwkSvcProvider == null) {
+            throw new CloudRuntimeException("Network Service Provider: " + networkDevice.getNetworkServiceProvder() +
+                    " is not enabled in the physical network: " + physicalNetworkId + "to add this device");
+        } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
+            throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
+                    " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device");
+        }
+
+        if (_ciscoVnmcDao.listByPhysicalNetwork(physicalNetworkId).size() != 0) {
+            throw new CloudRuntimeException("A Cisco Vnmc device is already configured on this physical network");
+        }
+
+        Map<String, String> params = new HashMap<String,String>();
+        params.put("guid", UUID.randomUUID().toString());
+        params.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId()));
+        params.put("physicalNetworkId", String.valueOf(physicalNetwork.getId()));
+        params.put("name", "Cisco VNMC Controller - " + cmd.getHost());
+        params.put("ip", cmd.getHost());
+        params.put("username", cmd.getUsername());
+        params.put("password", cmd.getPassword());
+        params.put("transportzoneisotype", physicalNetwork.getIsolationMethods().get(0).toLowerCase()); // FIXME What to do with multiple isolation types
+
+        Map<String, Object> hostdetails = new HashMap<String,Object>();
+        hostdetails.putAll(params);
+
+        ServerResource resource = new CiscoVnmcResource();
+        Transaction txn = Transaction.currentTxn();
+        try {
+            resource.configure(cmd.getHost(), hostdetails);
+
+            Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, params);
+            if (host != null) {
+                txn.start();
+
+                ciscoVnmcResource = new CiscoVnmcControllerVO(host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), deviceName);
+                _ciscoVnmcDao.persist((CiscoVnmcControllerVO)ciscoVnmcResource);
+                
+                DetailVO detail = new DetailVO(host.getId(), "deviceid", String.valueOf(ciscoVnmcResource.getId()));
+                _hostDetailsDao.persist(detail);
+
+                txn.commit();
+                return ciscoVnmcResource;
+            } else {
+                throw new CloudRuntimeException("Failed to add Cisco Vnmc device due to internal error.");
+            }
+        } catch (ConfigurationException e) {
+            txn.rollback();
+            throw new CloudRuntimeException(e.getMessage());
+        }
+    }
+
+    @Override
+    public CiscoVnmcResourceResponse createCiscoVnmcResourceResponse(
+            CiscoVnmcController ciscoVnmcResourceVO) {
+        HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcResourceVO.getHostId());
+
+        CiscoVnmcResourceResponse response = new CiscoVnmcResourceResponse();
+        response.setId(ciscoVnmcResourceVO.getUuid());
+        response.setPhysicalNetworkId(ciscoVnmcResourceVO.getPhysicalNetworkId());
+        response.setProviderName(ciscoVnmcResourceVO.getProviderName());
+        response.setResourceName(ciscoVnmcHost.getName());
+
+        return response;
+    }
+
+    @Override
+    public boolean deleteCiscoVnmcResource(DeleteCiscoVnmcResourceCmd cmd) {
+        Long vnmcResourceId = cmd.getCiscoVnmcResourceId();
+        CiscoVnmcControllerVO vnmcResource = _ciscoVnmcDao.findById(vnmcResourceId);
+        if (vnmcResource == null) {
+            throw new InvalidParameterValueException(
+                    "Could not find a Cisco VNMC appliance with id " + vnmcResourceId);
+        }
+
+        // Check if there any ASA 1000v appliances
+        Long physicalNetworkId = vnmcResource.getPhysicalNetworkId();
+        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork != null) {
+            List<CiscoAsa1000vDeviceVO> responseList = _ciscoAsa1000vDao.listByPhysicalNetwork(physicalNetworkId);
+            if (responseList.size() > 0) {
+                throw new CloudRuntimeException(
+                        "Cisco VNMC appliance with id " + vnmcResourceId +
+                        " cannot be deleted as there Cisco ASA 1000v appliances using it");
+            }
+        }
+
+        HostVO vnmcHost = _hostDao.findById(vnmcResource.getHostId());
+        Long hostId = vnmcHost.getId();
+        vnmcHost.setResourceState(ResourceState.Maintenance);
+        _hostDao.update(hostId, vnmcHost);
+        _resourceMgr.deleteHost(hostId, false, false);
+        _ciscoVnmcDao.remove(vnmcResourceId);
+
+        return true;
+    }
+
+    @Override
+    public List<CiscoVnmcControllerVO> listCiscoVnmcResources(
+            ListCiscoVnmcResourcesCmd cmd) {
+        Long physicalNetworkId = cmd.getPhysicalNetworkId();
+        Long ciscoVnmcResourceId = cmd.getCiscoVnmcResourceId();
+        List<CiscoVnmcControllerVO> responseList = new ArrayList<CiscoVnmcControllerVO>();
+
+        if (physicalNetworkId == null && ciscoVnmcResourceId == null) {
+            throw new InvalidParameterValueException("Either physical network Id or vnmc device Id must be specified");
+        }
+
+        if (ciscoVnmcResourceId != null) {
+            CiscoVnmcControllerVO ciscoVnmcResource = _ciscoVnmcDao.findById(ciscoVnmcResourceId);
+            if (ciscoVnmcResource == null) {
+                throw new InvalidParameterValueException("Could not find Cisco Vnmc device with id: " + ciscoVnmcResource);
+            }
+            responseList.add(ciscoVnmcResource);
+        }
+        else {
+            PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+            if (physicalNetwork == null) {
+                throw new InvalidParameterValueException("Could not find a physical network with id: " + physicalNetworkId);
+            }
+            responseList = _ciscoVnmcDao.listByPhysicalNetwork(physicalNetworkId);
+        }
+
+        return responseList;
+    }
+
+    @Override
+    public IpDeployer getIpDeployer(Network network) {
+        return this;
+    }
+
+    @Override
+    public boolean applyFWRules(Network network,
+            List<? extends FirewallRule> rules)
+            throws ResourceUnavailableException {
+
+        if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Firewall, Provider.CiscoVnmc)) {
+            s_logger.error("Firewall service is not provided by Cisco Vnmc device on network " + network.getName());
+            return false;
+        }
+
+        // Find VNMC host for physical network
+        List<CiscoVnmcControllerVO> devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
+        if (devices.isEmpty()) {
+            s_logger.error("No Cisco Vnmc device on network " + network.getName());
+            return true;
+        }
+
+        // Find if ASA 1000v is associated with network
+        NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId());
+        if (asaForNetwork == null) {
+            s_logger.debug("Cisco ASA 1000v device is not associated with network " + network.getName());
+            return true;
+        }
+
+        if (network.getState() == Network.State.Allocated) {
+            s_logger.debug("External firewall was asked to apply firewall rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands.");
+            return true;
+        }
+
+        CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0);
+        HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId());
+
+        List<FirewallRuleTO> rulesTO = new ArrayList<FirewallRuleTO>();
+        for (FirewallRule rule : rules) {
+            IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
+            FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr(), rule.getPurpose(), rule.getTrafficType());
+            rulesTO.add(ruleTO);
+        }
+
+        if (!rulesTO.isEmpty()) {
+            SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rulesTO);
+            cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, network.getBroadcastUri().getHost());
+            cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr());
+            Answer answer = _agentMgr.easySend(ciscoVnmcHost.getId(), cmd);
+            if (answer == null || !answer.getResult()) {
+                String details = (answer != null) ? answer.getDetails() : "details unavailable";
+                String msg = "Unable to apply firewall rules to Cisco ASA 1000v appliance due to: " + details + ".";
+                s_logger.error(msg);
+                throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId());
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean applyPFRules(Network network, List<PortForwardingRule> rules)
+            throws ResourceUnavailableException {
+
+        if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.PortForwarding, Provider.CiscoVnmc)) {
+            s_logger.error("Port forwarding service is not provided by Cisco Vnmc device on network " + network.getName());
+            return false;
+        }
+
+        // Find VNMC host for physical network
+        List<CiscoVnmcControllerVO> devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
+        if (devices.isEmpty()) {
+            s_logger.error("No Cisco Vnmc device on network " + network.getName());
+            return true;
+        }
+
+        // Find if ASA 1000v is associated with network
+        NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId());
+        if (asaForNetwork == null) {
+            s_logger.debug("Cisco ASA 1000v device is not associated with network " + network.getName());
+            return true;
+        }
+
+        if (network.getState() == Network.State.Allocated) {
+            s_logger.debug("External firewall was asked to apply port forwarding rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands.");
+            return true;
+        }
+
+        CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0);
+        HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId());
+
+        List<PortForwardingRuleTO> rulesTO = new ArrayList<PortForwardingRuleTO>();
+        for (PortForwardingRule rule : rules) {
+            IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
+            Vlan vlan = _vlanDao.findById(sourceIp.getVlanId());
+            PortForwardingRuleTO ruleTO = new PortForwardingRuleTO(rule, vlan.getVlanTag(), sourceIp.getAddress().addr());
+            rulesTO.add(ruleTO);
+        }
+
+        if (!rulesTO.isEmpty()) {
+            SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(rulesTO);
+            cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, network.getBroadcastUri().getHost());
+            cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr());
+            Answer answer = _agentMgr.easySend(ciscoVnmcHost.getId(), cmd);
+            if (answer == null || !answer.getResult()) {
+                String details = (answer != null) ? answer.getDetails() : "details unavailable";
+                String msg = "Unable to apply port forwarding rules to Cisco ASA 1000v appliance due to: " + details + ".";
+                s_logger.error(msg);
+                throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId());
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean applyStaticNats(Network network,
+            List<? extends StaticNat> rules)
+            throws ResourceUnavailableException {
+        if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.StaticNat, Provider.CiscoVnmc)) {
+            s_logger.error("Static NAT service is not provided by Cisco Vnmc device on network " + network.getName());
+            return false;
+        }
+
+        // Find VNMC host for physical network
+        List<CiscoVnmcControllerVO> devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
+        if (devices.isEmpty()) {
+            s_logger.error("No Cisco Vnmc device on network " + network.getName());
+            return true;
+        }
+
+        // Find if ASA 1000v is associated with network
+        NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId());
+        if (asaForNetwork == null) {
+            s_logger.debug("Cisco ASA 1000v device is not associated with network " + network.getName());
+            return true;
+        }
+
+        if (network.getState() == Network.State.Allocated) {
+            s_logger.debug("External firewall was asked to apply static NAT rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands.");
+            return true;
+        }
+
+        CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0);
+        HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId());
+
+        List<StaticNatRuleTO> rulesTO = new ArrayList<StaticNatRuleTO>();
+        for (StaticNat rule : rules) {
+            IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
+            StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, 
+                    null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false);
+            rulesTO.add(ruleTO);
+        }
+
+        if (!rulesTO.isEmpty()) {
+            SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rulesTO, null);
+            cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, network.getBroadcastUri().getHost());
+            cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr());
+            Answer answer = _agentMgr.easySend(ciscoVnmcHost.getId(), cmd);
+            if (answer == null || !answer.getResult()) {
+                String details = (answer != null) ? answer.getDetails() : "details unavailable";
+                String msg = "Unable to apply static NAT rules to Cisco ASA 1000v appliance due to: " + details + ".";
+                s_logger.error(msg);
+                throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId());
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean applyIps(Network network,
+            List<? extends PublicIpAddress> ipAddress, Set<Service> services)
+            throws ResourceUnavailableException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public HostVO createHostVOForConnectedAgent(HostVO host,
+            StartupCommand[] cmd) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public HostVO createHostVOForDirectConnectAgent(HostVO host,
+            StartupCommand[] startup, ServerResource resource,
+            Map<String, String> details, List<String> hostTags) {
+        if (!(startup[0] instanceof StartupExternalFirewallCommand)) {
+            return null;
+        }
+        host.setType(Host.Type.ExternalFirewall);
+        return host;
+    }
+
+    @Override
+    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced,
+            boolean isForceDeleteStorage) throws UnableDeleteHostException {
+        if (host.getType() != com.cloud.host.Host.Type.ExternalFirewall) {
+            return null;
+        }
+        return new DeleteHostAnswer(true);
+    }
+
+    @Override
+    public CiscoAsa1000vDevice addCiscoAsa1000vResource(
+            AddCiscoAsa1000vResourceCmd cmd) {
+        Long physicalNetworkId = cmd.getPhysicalNetworkId();
+        CiscoAsa1000vDevice ciscoAsa1000vResource = null;
+
+        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork == null) {
+            throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId);
+        }
+
+        ciscoAsa1000vResource = new CiscoAsa1000vDeviceVO(physicalNetworkId, cmd.getManagementIp(), cmd.getInPortProfile(), cmd.getClusterId());
+        _ciscoAsa1000vDao.persist((CiscoAsa1000vDeviceVO)ciscoAsa1000vResource);
+
+        return ciscoAsa1000vResource;
+    }
+
+    @Override
+    public CiscoAsa1000vResourceResponse createCiscoAsa1000vResourceResponse(
+            CiscoAsa1000vDevice ciscoAsa1000vDeviceVO) {
+        CiscoAsa1000vResourceResponse response = new CiscoAsa1000vResourceResponse();
+        response.setId(ciscoAsa1000vDeviceVO.getUuid());
+        response.setManagementIp(ciscoAsa1000vDeviceVO.getManagementIp());
+        response.setInPortProfile(ciscoAsa1000vDeviceVO.getInPortProfile());
+
+        NetworkAsa1000vMapVO networkAsaMap = _networkAsa1000vMapDao.findByAsa1000vId(ciscoAsa1000vDeviceVO.getId());
+        if (networkAsaMap != null) {
+            response.setGuestNetworkId(networkAsaMap.getNetworkId());
+        }
+
+        return response;
+    }
+
+    @Override
+    public boolean deleteCiscoAsa1000vResource(
+            DeleteCiscoAsa1000vResourceCmd cmd) {
+        Long asaResourceId = cmd.getCiscoAsa1000vResourceId();
+        CiscoAsa1000vDeviceVO asaResource = _ciscoAsa1000vDao.findById(asaResourceId);
+        if (asaResource == null) {
+            throw new InvalidParameterValueException(
+                    "Could not find a Cisco ASA 1000v appliance with id " + asaResourceId);
+        }
+
+        NetworkAsa1000vMapVO networkAsaMap = _networkAsa1000vMapDao.findByAsa1000vId(asaResource.getId());
+        if (networkAsaMap != null) {
+            throw new CloudRuntimeException(
+                    "Cisco ASA 1000v appliance with id " + asaResourceId +
+                    " cannot be deleted as it is associated with guest network");
+        }
+
+        _ciscoAsa1000vDao.remove(asaResourceId);
+
+        return true;
+    }
+
+    @Override
+    public List<CiscoAsa1000vDeviceVO> listCiscoAsa1000vResources(
+            ListCiscoAsa1000vResourcesCmd cmd) {
+        Long physicalNetworkId = cmd.getPhysicalNetworkId();
+        Long ciscoAsa1000vResourceId = cmd.getCiscoAsa1000vResourceId();
+        List<CiscoAsa1000vDeviceVO> responseList = new ArrayList<CiscoAsa1000vDeviceVO>();
+
+        if (physicalNetworkId == null && ciscoAsa1000vResourceId == null) {
+            throw new InvalidParameterValueException("Either physical network Id or Asa 1000v device Id must be specified");
+        }
+
+        if (ciscoAsa1000vResourceId != null) {
+            CiscoAsa1000vDeviceVO ciscoAsa1000vResource = _ciscoAsa1000vDao.findById(ciscoAsa1000vResourceId);
+            if (ciscoAsa1000vResource == null) {
+                throw new InvalidParameterValueException("Could not find Cisco Asa 1000v device with id: " + ciscoAsa1000vResourceId);
+            }
+            responseList.add(ciscoAsa1000vResource);
+        } else {
+            PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+            if (physicalNetwork == null) {
+                throw new InvalidParameterValueException("Could not find a physical network with id: " + physicalNetworkId);
+            }
+            responseList = _ciscoAsa1000vDao.listByPhysicalNetwork(physicalNetworkId);
+        }
+
+        return responseList;
+    }
+
+    @Override
+    public CiscoAsa1000vDevice assignAsa1000vToNetwork(Network network) {
+        List<CiscoAsa1000vDeviceVO> asaList = _ciscoAsa1000vDao.listByPhysicalNetwork(network.getPhysicalNetworkId());
+        for (CiscoAsa1000vDeviceVO asa : asaList) {
+            NetworkAsa1000vMapVO assignedToNetwork = _networkAsa1000vMapDao.findByAsa1000vId(asa.getId());
+            if (assignedToNetwork == null) {
+                NetworkAsa1000vMapVO networkAsaMap = new NetworkAsa1000vMapVO(network.getId(), asa.getId());
+                _networkAsa1000vMapDao.persist(networkAsaMap);
+                return asa;
+            }
+        }
+        return null;
+    }
+
+    private void unassignAsa1000vFromNetwork(Network network) {
+        NetworkAsa1000vMapVO networkAsaMap = _networkAsa1000vMapDao.findByNetworkId(network.getId());
+        if (networkAsaMap != null) {
+            _networkAsa1000vMapDao.remove(networkAsaMap.getId());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e94c7025/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElementService.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElementService.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElementService.java
new file mode 100644
index 0000000..e8eb473
--- /dev/null
+++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElementService.java
@@ -0,0 +1,42 @@
+// 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.element;
+
+import java.util.List;
+
+import com.cloud.api.commands.AddCiscoVnmcResourceCmd;
+import com.cloud.api.commands.DeleteCiscoVnmcResourceCmd;
+import com.cloud.api.commands.ListCiscoVnmcResourcesCmd;
+import com.cloud.api.response.CiscoVnmcResourceResponse;
+import com.cloud.network.cisco.CiscoVnmcController;
+import com.cloud.network.cisco.CiscoVnmcControllerVO;
+import com.cloud.utils.component.PluggableService;
+
+public interface CiscoVnmcElementService extends PluggableService {
+
+    //public static final Provider CiscoVnmc = new Provider("CiscoVnmc", true);
+
+    public CiscoVnmcController addCiscoVnmcResource(AddCiscoVnmcResourceCmd cmd);
+
+    public CiscoVnmcResourceResponse createCiscoVnmcResourceResponse(
+            CiscoVnmcController CiscoVnmcResourceVO);
+
+    boolean deleteCiscoVnmcResource(DeleteCiscoVnmcResourceCmd cmd);
+
+    List<CiscoVnmcControllerVO> listCiscoVnmcResources(ListCiscoVnmcResourcesCmd cmd);
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e94c7025/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java
new file mode 100644
index 0000000..9155978
--- /dev/null
+++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java
@@ -0,0 +1,780 @@
+// 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.resource;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.AssociateAsaWithLogicalEdgeFirewallCommand;
+import com.cloud.agent.api.CleanupLogicalEdgeFirewallCommand;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.ConfigureNexusVsmForAsaCommand;
+import com.cloud.agent.api.CreateLogicalEdgeFirewallCommand;
+import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer;
+import com.cloud.agent.api.ExternalNetworkResourceUsageCommand;
+import com.cloud.agent.api.MaintainAnswer;
+import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupExternalFirewallCommand;
+import com.cloud.agent.api.routing.IpAssocAnswer;
+import com.cloud.agent.api.routing.IpAssocCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.api.routing.SetFirewallRulesCommand;
+import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
+import com.cloud.agent.api.routing.SetSourceNatCommand;
+import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
+import com.cloud.agent.api.to.FirewallRuleTO;
+import com.cloud.agent.api.to.PortForwardingRuleTO;
+import com.cloud.agent.api.to.StaticNatRuleTO;
+import com.cloud.host.Host;
+import com.cloud.network.cisco.CiscoVnmcConnectionImpl;
+import com.cloud.network.rules.FirewallRule.TrafficType;
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Pair;
+import com.cloud.utils.cisco.n1kv.vsm.NetconfHelper;
+import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.OperationType;
+import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.SwitchPortMode;
+import com.cloud.utils.exception.ExecutionException;
+import com.cloud.utils.net.NetUtils;
+
+public class CiscoVnmcResource implements ServerResource {
+
+    private String _name;
+    private String _zoneId;
+    private String _physicalNetworkId;
+    private String _ip;
+    private String _username;
+    private String _password;
+    private String _guid;
+    private Integer _numRetries;
+
+    private CiscoVnmcConnectionImpl _connection;
+
+    public void setConnection(CiscoVnmcConnectionImpl connection) {
+        this._connection = connection;
+    }
+
+    private final Logger s_logger = Logger.getLogger(CiscoVnmcResource.class);
+
+    public Answer executeRequest(Command cmd) {
+        if (cmd instanceof ReadyCommand) {
+            return execute((ReadyCommand) cmd);
+        } else if (cmd instanceof MaintainCommand) {
+            return execute((MaintainCommand) cmd);
+        } else if (cmd instanceof IpAssocCommand) {
+            return execute((IpAssocCommand) cmd);
+        } else if (cmd instanceof SetSourceNatCommand) {
+            return execute((SetSourceNatCommand) cmd);
+        } else if (cmd instanceof SetFirewallRulesCommand) {
+            return execute((SetFirewallRulesCommand) cmd);
+        } else if (cmd instanceof SetStaticNatRulesCommand) {
+            return execute((SetStaticNatRulesCommand) cmd);
+        } else if (cmd instanceof SetPortForwardingRulesCommand) {
+            return execute((SetPortForwardingRulesCommand) cmd);
+        } else if (cmd instanceof ExternalNetworkResourceUsageCommand) {
+            return execute((ExternalNetworkResourceUsageCommand) cmd);
+        } else if (cmd instanceof CreateLogicalEdgeFirewallCommand) {
+            return execute((CreateLogicalEdgeFirewallCommand)cmd);
+        } else if (cmd instanceof CleanupLogicalEdgeFirewallCommand) {
+            return execute((CleanupLogicalEdgeFirewallCommand)cmd);
+        } else if (cmd instanceof ConfigureNexusVsmForAsaCommand) {
+            return execute((ConfigureNexusVsmForAsaCommand)cmd);
+        } else if (cmd instanceof AssociateAsaWithLogicalEdgeFirewallCommand) {
+            return execute((AssociateAsaWithLogicalEdgeFirewallCommand)cmd);
+        } else {
+            return Answer.createUnsupportedCommandAnswer(cmd);
+        }
+    }
+
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        try {
+            _name = (String) params.get("name");
+            if (_name == null) {
+                throw new ConfigurationException("Unable to find name");
+            }
+
+            _zoneId = (String) params.get("zoneId");
+            if (_zoneId == null) {
+                throw new ConfigurationException("Unable to find zone");
+            }
+
+            _physicalNetworkId = (String) params.get("physicalNetworkId");
+            if (_physicalNetworkId == null) {
+                throw new ConfigurationException("Unable to find physical network id in the configuration parameters");
+            }
+
+            _ip = (String) params.get("ip");
+            if (_ip == null) {
+                throw new ConfigurationException("Unable to find IP");
+            }
+
+            _username = (String) params.get("username");
+            if (_username == null) {
+                throw new ConfigurationException("Unable to find username");
+            }
+
+            _password = (String) params.get("password");
+            if (_password == null) {
+                throw new ConfigurationException("Unable to find password");
+            }
+
+            _guid = (String)params.get("guid");
+            if (_guid == null) {
+                throw new ConfigurationException("Unable to find the guid");
+            }
+
+            _numRetries = NumbersUtil.parseInt((String) params.get("numretries"), 1);
+
+            NumbersUtil.parseInt((String) params.get("timeout"), 300);
+
+            // Open a socket and login
+            _connection = new CiscoVnmcConnectionImpl(_ip, _username, _password);
+            //if (!refreshVnmcConnection()) {
+            //    throw new ConfigurationException("Unable to open a connection to the VNMC.");
+            //}
+
+            return true;
+        } catch (Exception e) {
+            throw new ConfigurationException(e.getMessage());
+        }
+
+    }
+
+    public StartupCommand[] initialize() {
+        StartupExternalFirewallCommand cmd = new StartupExternalFirewallCommand();
+        cmd.setName(_name);
+        cmd.setDataCenter(_zoneId);
+        cmd.setPod("");
+        cmd.setPrivateIpAddress(_ip);
+        cmd.setStorageIpAddress("");
+        cmd.setVersion("");
+        cmd.setGuid(_guid);
+        return new StartupCommand[] { cmd };
+    }
+
+    public Host.Type getType() {
+        return Host.Type.ExternalFirewall;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+    @Override
+    public PingCommand getCurrentStatus(final long id) {
+        if (!refreshVnmcConnection()) {
+            return null;
+        }
+        return new PingCommand(Host.Type.ExternalFirewall, id);
+    }
+
+    @Override
+    public void disconnected() {
+    }
+
+    public IAgentControl getAgentControl() {
+        return null;
+    }
+
+    public void setAgentControl(IAgentControl agentControl) {
+        return;
+    }
+
+    private Answer execute(ReadyCommand cmd) {
+        return new ReadyAnswer(cmd);
+    }
+
+    private Answer execute(MaintainCommand cmd) {
+        return new MaintainAnswer(cmd);
+    }
+
+    private ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) {
+        return new ExternalNetworkResourceUsageAnswer(cmd);
+    }
+
+    /*
+     * Login
+     */
+    private boolean refreshVnmcConnection() {
+        boolean ret = false;
+        try {
+            ret = _connection.login();
+        } catch (ExecutionException ex) {
+            s_logger.error("Login to Vnmc failed", ex);
+        }
+        return ret;
+    }
+
+    private synchronized Answer execute(IpAssocCommand cmd) {
+        refreshVnmcConnection();
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(IpAssocCommand cmd, int numRetries) {
+        String[] results = new String[cmd.getIpAddresses().length];
+        return new IpAssocAnswer(cmd, results);
+    }
+
+    private String[] getIpRangeFromCidr(String cidr) {
+        String[] result = new String[2];
+        String[] cidrData = cidr.split("\\/");
+        assert (cidrData.length == 2) : "Something is wrong with source cidr " + cidr;
+        long size = Long.valueOf(cidrData[1]);
+        result[0] = cidrData[0];
+        result[1] = cidrData[0];
+        if (size < 32) {
+            result[0] = NetUtils.getIpRangeStartIpFromCidr(cidrData[0], size);
+            result[1] = NetUtils.getIpRangeEndIpFromCidr(cidrData[0], size);
+        }
+        return result;
+    }
+
+    /*
+     * Source NAT
+     */
+    private synchronized Answer execute(SetSourceNatCommand cmd) {
+        refreshVnmcConnection();
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(SetSourceNatCommand cmd, int numRetries) {
+        String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG);
+        String tenant = "vlan-" + vlanId;
+        String policyIdentifier = cmd.getIpAddress().getPublicIp().replace('.', '-');
+        try {
+            if (!_connection.createTenantVDCNatPolicySet(tenant)) {
+                throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.createTenantVDCSourceNatPolicy(tenant, policyIdentifier)) {
+                throw new Exception("Failed to create source NAT policy in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.createTenantVDCSourceNatPolicyRef(tenant, policyIdentifier)) {
+                throw new Exception("Failed to associate source NAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.createTenantVDCSourceNatIpPool(tenant, policyIdentifier, cmd.getIpAddress().getPublicIp())) {
+                throw new Exception("Failed to create source NAT ip pool in VNMC for guest network with vlan " + vlanId);
+            }
+
+            String[] ipRange = getIpRangeFromCidr(cmd.getContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR));
+            if (!_connection.createTenantVDCSourceNatRule(tenant, policyIdentifier, ipRange[0], ipRange[1])) {
+                throw new Exception("Failed to create source NAT rule in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.associateNatPolicySet(tenant)) {
+                throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId);
+            }
+        } catch (Throwable e) {
+            String msg = "SetSourceNatCommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    /*
+     * Firewall rule
+     */
+    private synchronized Answer execute(SetFirewallRulesCommand cmd) {
+        refreshVnmcConnection();
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(SetFirewallRulesCommand cmd, int numRetries) {
+        String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG);
+        String tenant = "vlan-" + vlanId;
+
+        FirewallRuleTO[] rules = cmd.getRules();
+        Map<String, List<FirewallRuleTO>> publicIpRulesMap = new HashMap<String, List<FirewallRuleTO>>();
+        for (FirewallRuleTO rule : rules) {
+            String publicIp = rule.getSrcIp();
+            if (!publicIpRulesMap.containsKey(publicIp)) {
+                List<FirewallRuleTO> publicIpRulesList = new ArrayList<FirewallRuleTO>();
+                publicIpRulesMap.put(publicIp, publicIpRulesList);
+            }
+            publicIpRulesMap.get(publicIp).add(rule);
+        }
+
+        try {
+            if (!_connection.createTenantVDCAclPolicySet(tenant, true)) {
+                throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId);
+            }
+            if (!_connection.createTenantVDCAclPolicySet(tenant, false)) {
+                throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            for (String publicIp : publicIpRulesMap.keySet()) {
+                String policyIdentifier = publicIp.replace('.', '-');
+
+                if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) {
+                    throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) {
+                    throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) {
+                    throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId);
+                }
+
+                for (FirewallRuleTO rule : publicIpRulesMap.get(publicIp)) {
+                    if (rule.revoked()) {
+                        if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) {
+                            throw new Exception("Failed to delete ACL rule in VNMC for guest network with vlan " + vlanId);
+                        }
+                    } else {
+                        String[] externalIpRange = getIpRangeFromCidr(rule.getSourceCidrList().get(0));
+                        if (rule.getTrafficType() == TrafficType.Ingress) {
+                            if (!rule.getProtocol().equalsIgnoreCase("icmp")) {
+                                if (!_connection.createTenantVDCIngressAclRule(tenant,
+                                        Long.toString(rule.getId()), policyIdentifier,
+                                        rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1],
+                                        Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]), publicIp)) {
+                                    throw new Exception("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId);
+                                }
+                            } else {
+                                if (!_connection.createTenantVDCIngressAclRule(tenant,
+                                        Long.toString(rule.getId()), policyIdentifier,
+                                        rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1], publicIp)) {
+                                    throw new Exception("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId);
+                                }
+                            }
+                        } else {
+                            if (!rule.getProtocol().equalsIgnoreCase("icmp")) {
+                                if (!_connection.createTenantVDCEgressAclRule(tenant,
+                                        Long.toString(rule.getId()), policyIdentifier,
+                                        rule.getProtocol().toUpperCase(),
+                                        Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]), publicIp,
+                                        externalIpRange[0], externalIpRange[1])) {
+                                    throw new Exception("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId);
+                                }
+                            } else {
+                                if (!_connection.createTenantVDCEgressAclRule(tenant,
+                                        Long.toString(rule.getId()), policyIdentifier,
+                                        rule.getProtocol().toUpperCase(), publicIp, externalIpRange[0], externalIpRange[1])) {
+                                    throw new Exception("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (!_connection.associateAclPolicySet(tenant)) {
+                throw new Exception("Failed to associate ACL policy set with edge security profile in VNMC for guest network with vlan " + vlanId);
+            }
+        } catch (Throwable e) {
+            String msg = "SetFirewallRulesCommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    /*
+     * Static NAT
+     */
+    private synchronized Answer execute(SetStaticNatRulesCommand cmd) {
+        refreshVnmcConnection();
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(SetStaticNatRulesCommand cmd, int numRetries) {
+        String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG);
+        String tenant = "vlan-" + vlanId;
+
+        StaticNatRuleTO[] rules = cmd.getRules();
+        Map<String, List<StaticNatRuleTO>> publicIpRulesMap = new HashMap<String, List<StaticNatRuleTO>>();
+        for (StaticNatRuleTO rule : rules) {
+            String publicIp = rule.getSrcIp();
+            if (!publicIpRulesMap.containsKey(publicIp)) {
+                List<StaticNatRuleTO> publicIpRulesList = new ArrayList<StaticNatRuleTO>();
+                publicIpRulesMap.put(publicIp, publicIpRulesList);
+            }
+            publicIpRulesMap.get(publicIp).add(rule);
+        }
+
+        try {
+            if (!_connection.createTenantVDCNatPolicySet(tenant)) {
+                throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.createTenantVDCAclPolicySet(tenant, true)) {
+                throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.createTenantVDCAclPolicySet(tenant, false)) {
+                throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            for (String publicIp : publicIpRulesMap.keySet()) {
+                String policyIdentifier = publicIp.replace('.', '-');
+
+                if (!_connection.createTenantVDCDNatPolicy(tenant, policyIdentifier)) {
+                    throw new Exception("Failed to create DNAT policy in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCDNatPolicyRef(tenant, policyIdentifier)) {
+                    throw new Exception("Failed to associate DNAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId);
+                }
+
+                if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) {
+                    throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) {
+                    throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) {
+                    throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId);
+                }
+
+                for (StaticNatRuleTO rule : publicIpRulesMap.get(publicIp)) {
+                    if (rule.revoked()) {
+                        if (!_connection.deleteTenantVDCDNatRule(tenant, Long.toString(rule.getId()), policyIdentifier)) {
+                            throw new Exception("Failed to delete DNAT rule in VNMC for guest network with vlan " + vlanId);
+                        }
+
+                        if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) {
+                            throw new Exception("Failed to delete ACL ingress rule for DNAT in VNMC for guest network with vlan " + vlanId);
+                        }
+                    } else {
+                        if (!_connection.createTenantVDCDNatIpPool(tenant, policyIdentifier + "-" + rule.getId(), rule.getDstIp())) {
+                            throw new Exception("Failed to create DNAT ip pool in VNMC for guest network with vlan " + vlanId);
+                        }
+
+                        if (!_connection.createTenantVDCDNatRule(tenant,
+                                Long.toString(rule.getId()), policyIdentifier, rule.getSrcIp())) {
+                            throw new Exception("Failed to create DNAT rule in VNMC for guest network with vlan " + vlanId);
+                        }
+
+                        if (!_connection.createTenantVDCAclRuleForDNat(tenant,
+                                Long.toString(rule.getId()), policyIdentifier, rule.getDstIp())) {
+                            throw new Exception("Failed to create ACL rule for DNAT in VNMC for guest network with vlan " + vlanId);
+                        }
+                    }
+                }
+            }
+
+            if (!_connection.associateAclPolicySet(tenant)) {
+                throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId);
+            }
+        } catch (Throwable e) {
+            String msg = "SetSourceNatCommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    /*
+     * Destination NAT
+     */
+    private synchronized Answer execute(SetPortForwardingRulesCommand cmd) {
+        refreshVnmcConnection();
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(SetPortForwardingRulesCommand cmd, int numRetries) {
+        String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG);
+        String tenant = "vlan-" + vlanId;
+
+        PortForwardingRuleTO[] rules = cmd.getRules();
+        Map<String, List<PortForwardingRuleTO>> publicIpRulesMap = new HashMap<String, List<PortForwardingRuleTO>>();
+        for (PortForwardingRuleTO rule : rules) {
+            String publicIp = rule.getSrcIp();
+            if (!publicIpRulesMap.containsKey(publicIp)) {
+                List<PortForwardingRuleTO> publicIpRulesList = new ArrayList<PortForwardingRuleTO>();
+                publicIpRulesMap.put(publicIp, publicIpRulesList);
+            }
+            publicIpRulesMap.get(publicIp).add(rule);
+        }
+
+        try {
+            if (!_connection.createTenantVDCNatPolicySet(tenant)) {
+                throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.createTenantVDCAclPolicySet(tenant, true)) {
+                throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            if (!_connection.createTenantVDCAclPolicySet(tenant, false)) {
+                throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId);
+            }
+
+            for (String publicIp : publicIpRulesMap.keySet()) {
+                String policyIdentifier = publicIp.replace('.', '-');
+
+                if (!_connection.createTenantVDCPFPolicy(tenant, policyIdentifier)) {
+                    throw new Exception("Failed to create PF policy in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCPFPolicyRef(tenant, policyIdentifier)) {
+                    throw new Exception("Failed to associate PF policy with NAT policy set in VNMC for guest network with vlan " + vlanId);
+                }
+
+                if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) {
+                    throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) {
+                    throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId);
+                }
+                if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) {
+                    throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId);
+                }
+
+                for (PortForwardingRuleTO rule : publicIpRulesMap.get(publicIp)) {
+                    if (rule.revoked()) {
+                        if (!_connection.deleteTenantVDCPFRule(tenant, Long.toString(rule.getId()), policyIdentifier)) {
+                            throw new Exception("Failed to delete PF rule in VNMC for guest network with vlan " + vlanId);
+                        }
+
+                        if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) {
+                            throw new Exception("Failed to delete ACL ingress rule for PF in VNMC for guest network with vlan " + vlanId);
+                        }
+                    } else {
+                        if (!_connection.createTenantVDCPFIpPool(tenant, policyIdentifier + "-" + rule.getId(), rule.getDstIp())) {
+                            throw new Exception("Failed to create PF ip pool in VNMC for guest network with vlan " + vlanId);
+                        }
+                        if (!_connection.createTenantVDCPFPortPool(tenant, policyIdentifier + "-" + rule.getId(),
+                                Integer.toString(rule.getDstPortRange()[0]), Integer.toString(rule.getDstPortRange()[1]))) {
+                            throw new Exception("Failed to create PF port pool in VNMC for guest network with vlan " + vlanId);
+                        }
+
+                        if (!_connection.createTenantVDCPFRule(tenant,
+                                Long.toString(rule.getId()), policyIdentifier,
+                                rule.getProtocol().toUpperCase(), rule.getSrcIp(),
+                                Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) {
+                            throw new Exception("Failed to create PF rule in VNMC for guest network with vlan " + vlanId);
+                        }
+
+                        if (!_connection.createTenantVDCAclRuleForPF(tenant,
+                                Long.toString(rule.getId()), policyIdentifier,
+                                rule.getProtocol().toUpperCase(), rule.getDstIp(),
+                                Integer.toString(rule.getDstPortRange()[0]), Integer.toString(rule.getDstPortRange()[1]))) {
+                            throw new Exception("Failed to create ACL rule for PF in VNMC for guest network with vlan " + vlanId);
+                        }
+                    }
+                }
+            }
+
+            if (!_connection.associateAclPolicySet(tenant)) {
+                throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId);
+            }
+        } catch (Throwable e) {
+            String msg = "SetSourceNatCommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    /*
+     * Logical edge firewall
+     */
+    private synchronized Answer execute(CreateLogicalEdgeFirewallCommand cmd) {
+        refreshVnmcConnection();
+        return execute(cmd, _numRetries);
+    }
+
+    private void createEdgeDeviceProfile(String tenant, List<String> gateways, Long vlanId) throws Exception {
+        // create edge device profile
+        if (!_connection.createTenantVDCEdgeDeviceProfile(tenant))
+            throw new Exception("Failed to create tenant edge device profile in VNMC for guest network with vlan " + vlanId);
+
+        // create edge static route policy
+        if (!_connection.createTenantVDCEdgeStaticRoutePolicy(tenant))
+            throw new Exception("Failed to create tenant edge static route policy in VNMC for guest network with vlan " + vlanId);
+
+        // create edge static route for all gateways
+        for (String gateway : gateways) {
+            if (!_connection.createTenantVDCEdgeStaticRoute(tenant, gateway, "0.0.0.0", "0.0.0.0"))
+                throw new Exception("Failed to create tenant edge static route in VNMC for guest network with vlan " + vlanId);
+        }
+
+        // associate edge 
+        if (!_connection.associateTenantVDCEdgeStaticRoutePolicy(tenant))
+            throw new Exception("Failed to associate edge static route policy with edge device profile in VNMC for guest network with vlan " + vlanId);
+    }
+
+    private Answer execute(CreateLogicalEdgeFirewallCommand cmd, int numRetries) {
+        String tenant = "vlan-" + cmd.getVlanId();
+        try {
+            // create tenant
+            if (!_connection.createTenant(tenant))
+                throw new Exception("Failed to create tenant in VNMC for guest network with vlan " + cmd.getVlanId());
+
+            // create tenant VDC
+            if (!_connection.createTenantVDC(tenant))
+                throw new Exception("Failed to create tenant VDC in VNMC for guest network with vlan " + cmd.getVlanId());
+
+            // create edge security profile
+            if (!_connection.createTenantVDCEdgeSecurityProfile(tenant))
+                throw new Exception("Failed to create tenant edge security profile in VNMC for guest network with vlan " + cmd.getVlanId());
+
+            // create edge device profile and associated route
+            createEdgeDeviceProfile(tenant, cmd.getPublicGateways(), cmd.getVlanId());
+
+            // create logical edge firewall
+            if (!_connection.createEdgeFirewall(tenant, cmd.getPublicIp(), cmd.getInternalIp(), cmd.getPublicSubnet(), cmd.getInternalSubnet()))
+                throw new Exception("Failed to create edge firewall in VNMC for guest network with vlan " + cmd.getVlanId());
+        } catch (Throwable e) {
+            String msg = "CreateLogicalEdgeFirewallCommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    /*
+     * Create vservice node and update inside port profile for ASA appliance in VSM
+     */
+    private synchronized Answer execute(ConfigureNexusVsmForAsaCommand cmd) {
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(ConfigureNexusVsmForAsaCommand cmd, int numRetries) {
+        String vlanId = Long.toString(cmd.getVlanId());
+        NetconfHelper helper = null;
+        List<Pair<OperationType, String>> params = new ArrayList<Pair<OperationType, String>>();
+        params.add(new Pair<OperationType, String>(OperationType.addvlanid, vlanId));
+        try {
+            helper = new NetconfHelper(cmd.getVsmIp(), cmd.getVsmUsername(), cmd.getVsmPassword());
+            s_logger.debug("Connected to Cisco VSM " + cmd.getVsmIp());
+            helper.addVServiceNode(vlanId, cmd.getIpAddress());
+            s_logger.debug("Created vservice node for ASA appliance in Cisco VSM for vlan " + vlanId);
+            helper.updatePortProfile(cmd.getAsaInPortProfile(), SwitchPortMode.access, params);
+            s_logger.debug("Updated inside port profile for ASA appliance in Cisco VSM with new vlan " + vlanId);
+        } catch (Throwable e) {
+            String msg = "ConfigureVSMForASACommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        } finally {
+            helper.disconnect();
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    /*
+     * Associates ASA 1000v with logical edge firewall in VNMC
+     */
+    private synchronized Answer execute(AssociateAsaWithLogicalEdgeFirewallCommand cmd) {
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(AssociateAsaWithLogicalEdgeFirewallCommand cmd, int numRetries) {
+        String tenant = "vlan-" + cmd.getVlanId();
+        try {
+            Map<String, String> availableAsaAppliances = _connection.listUnAssocAsa1000v();
+            if (availableAsaAppliances.isEmpty()) {
+                throw new Exception("No ASA 1000v available to associate with logical edge firewall for guest vlan " + cmd.getVlanId());
+            }
+
+            String asaInstanceDn = availableAsaAppliances.get(cmd.getAsaMgmtIp());
+            if (asaInstanceDn == null) {
+                throw new Exception("Requested ASA 1000v (" + cmd.getAsaMgmtIp() + ") is not available");
+            }
+
+            if (!_connection.assignAsa1000v(tenant, asaInstanceDn)) {
+                throw new Exception("Failed to associate ASA 1000v (" + cmd.getAsaMgmtIp() + ") with logical edge firewall for guest vlan " + cmd.getVlanId());
+            }
+        } catch (Throwable e) {
+            String msg = "AssociateAsaWithLogicalEdgeFirewallCommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    /*
+     * Cleanup
+     */
+    private synchronized Answer execute(CleanupLogicalEdgeFirewallCommand cmd) {
+        refreshVnmcConnection();
+        return execute(cmd, _numRetries);
+    }
+
+    private Answer execute(CleanupLogicalEdgeFirewallCommand cmd, int numRetries) {
+        String tenant = "vlan-" + cmd.getVlanId();
+        try {
+            _connection.deleteTenant(tenant);
+        } catch (Throwable e) {
+            String msg = "CleanupLogicalEdgeFirewallCommand failed due to " + e.getMessage();
+            s_logger.error(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+
+        return new Answer(cmd, true, "Success");
+    }
+
+    @Override
+    public void setName(String name) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setConfigParams(Map<String, Object> params) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public Map<String, Object> getConfigParams() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getRunLevel() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setRunLevel(int level) {
+        // TODO Auto-generated method stub
+    }
+
+}