@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 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 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 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( rule.getSourceIpAddressId(), 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 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()); 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 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 = _ipAddrMgr.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()); } // due to VNMC limitation of not allowing source NAT ip as the outside ip of firewall, // an additional public ip needs to acquired for assigning as firewall outside ip. // In case there are already additional ip addresses available (network restart) use one // of them such that it is not the source NAT ip IpAddress outsideIp = null; List<IPAddressVO> publicIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null); for (IPAddressVO ip : publicIps) { if (!ip.isSourceNat()) { outsideIp = ip; break; } } if (outsideIp == null) { // none available, acquire one try { Account caller = CallContext.current().getCallingAccount(); long callerUserId = CallContext.current().getCallingUserId(); outsideIp = _ipAddrMgr.allocateIp(owner, false, caller, callerUserId, zone); } catch (ResourceAllocationException e) { s_logger.error("Unable to allocate additional public Ip address. Exception details " + e); return false; } try { outsideIp = _ipAddrMgr.associateIPToGuestNetwork(outsideIp.getId(), network.getId(), true); } catch (ResourceAllocationException e) { s_logger.error( "Unable to assign allocated additional public Ip " + outsideIp.getAddress().addr() + " to network with vlan " + vlanId + ". Exception details " + e); return false; } } // create logical edge firewall in VNMC String gatewayNetmask = NetUtils.getCidrNetmask(network.getCidr()); // due to ASA limitation of allowing single subnet to be assigned to firewall interfaces, // all public ip addresses must be from same subnet, this essentially means single public // subnet in zone if (!createLogicalEdgeFirewall( vlanId, network.getGateway(), gatewayNetmask, outsideIp.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; }