throws NetworkRuleConflictException {
UserContext ctx = UserContext.current();
Account caller = ctx.getCaller();
// make sure ip address exists
PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId);
if (ipAddr == null) {
throw new InvalidParameterValueException("Unable to create remote access vpn, invalid public IP address id" + publicIpId);
}
_accountMgr.checkAccess(caller, null, true, ipAddr);
if (!ipAddr.readyToUse()) {
throw new InvalidParameterValueException("The Ip address is not ready to be used yet: " + ipAddr.getAddress());
}
IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId);
_networkMgr.checkIpForService(ipAddress, Service.Vpn, null);
RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId);
if (vpnVO != null) {
//if vpn is in Added state, return it to the api
if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
return vpnVO;
}
throw new InvalidParameterValueException("A Remote Access VPN already exists for this public Ip address");
}
// TODO: assumes one virtual network / domr per account per zone
vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId);
if (vpnVO != null) {
//if vpn is in Added state, return it to the api
if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
return vpnVO;
}
throw new InvalidParameterValueException("A Remote Access VPN already exists for this account");
}
//Verify that vpn service is enabled for the network
Network network = _networkMgr.getNetwork(networkId);
if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) {
throw new InvalidParameterValueException("Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId());
}
if (ipRange == null) {
ipRange = _configServer.getConfigValue(Config.RemoteAccessVpnClientIpRange.key(), Config.ConfigurationParameterScope.account.toString(), ipAddr.getAccountId());
}
String[] range = ipRange.split("-");
if (range.length != 2) {
throw new InvalidParameterValueException("Invalid ip range");
}
if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])) {
throw new InvalidParameterValueException("Invalid ip in range specification " + ipRange);
}
if (!NetUtils.validIpRange(range[0], range[1])) {
throw new InvalidParameterValueException("Invalid ip range " + ipRange);
}
Pair<String, Integer> cidr = NetUtils.getCidr(network.getCidr());
// FIXME: This check won't work for the case where the guest ip range
// changes depending on the vlan allocated.
String[] guestIpRange = NetUtils.getIpRangeFromCidr(cidr.first(), cidr.second());
if (NetUtils.ipRangesOverlap(range[0], range[1], guestIpRange[0], guestIpRange[1])) {
throw new InvalidParameterValueException("Invalid ip range: " + ipRange + " overlaps with guest ip range " + guestIpRange[0] + "-"
+ guestIpRange[1]);
}
// TODO: check sufficient range
// TODO: check overlap with private and public ip ranges in datacenter
long startIp = NetUtils.ip2Long(range[0]);
String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1];
String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength);
Transaction txn = Transaction.currentTxn();
txn.start();
_rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewall, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT);
vpnVO = new RemoteAccessVpnVO(ipAddr.getAccountId(), ipAddr.getDomainId(), ipAddr.getAssociatedWithNetworkId(),
publicIpId, range[0], newIpRange, sharedSecret);
RemoteAccessVpn vpn = _remoteAccessVpnDao.persist(vpnVO);
txn.commit();
return vpn;