mirror of https://github.com/apache/cloudstack.git
156 lines
6.0 KiB
Java
156 lines
6.0 KiB
Java
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package com.cloud.network;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import javax.ejb.Local;
|
|
import javax.inject.Inject;
|
|
import javax.naming.ConfigurationException;
|
|
|
|
import org.apache.log4j.Logger;
|
|
|
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|
|
|
import com.cloud.configuration.Config;
|
|
import com.cloud.dc.DataCenter;
|
|
import com.cloud.dc.DataCenterVO;
|
|
import com.cloud.dc.Vlan;
|
|
import com.cloud.dc.VlanVO;
|
|
import com.cloud.dc.dao.DataCenterDao;
|
|
import com.cloud.dc.dao.VlanDao;
|
|
import com.cloud.exception.InsufficientAddressCapacityException;
|
|
import com.cloud.network.dao.NetworkDao;
|
|
import com.cloud.network.dao.UserIpv6AddressDao;
|
|
import com.cloud.user.Account;
|
|
import com.cloud.utils.NumbersUtil;
|
|
import com.cloud.utils.component.ManagerBase;
|
|
import com.cloud.utils.exception.CloudRuntimeException;
|
|
import com.cloud.utils.net.NetUtils;
|
|
|
|
@Local(value = {Ipv6AddressManager.class})
|
|
public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressManager {
|
|
public static final Logger s_logger = Logger.getLogger(Ipv6AddressManagerImpl.class.getName());
|
|
|
|
String _name = null;
|
|
int _ipv6RetryMax = 0;
|
|
|
|
@Inject
|
|
DataCenterDao _dcDao;
|
|
@Inject
|
|
VlanDao _vlanDao;
|
|
@Inject
|
|
NetworkModel _networkModel;
|
|
@Inject
|
|
UserIpv6AddressDao _ipv6Dao;
|
|
@Inject
|
|
NetworkDao _networkDao;
|
|
@Inject
|
|
ConfigurationDao _configDao;
|
|
|
|
@Override
|
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
|
_name = name;
|
|
Map<String, String> configs = _configDao.getConfiguration(params);
|
|
_ipv6RetryMax = NumbersUtil.parseInt(configs.get(Config.NetworkIPv6SearchRetryMax.key()), 10000);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public UserIpv6Address assignDirectIp6Address(long dcId, Account owner, Long networkId, String requestedIp6) throws InsufficientAddressCapacityException {
|
|
Network network = _networkDao.findById(networkId);
|
|
if (network == null) {
|
|
return null;
|
|
}
|
|
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
|
|
if (vlans == null) {
|
|
s_logger.debug("Cannot find related vlan attached to network " + networkId);
|
|
return null;
|
|
}
|
|
String ip = null;
|
|
Vlan ipVlan = null;
|
|
if (requestedIp6 == null) {
|
|
if (!_networkModel.isIP6AddressAvailableInNetwork(networkId)) {
|
|
throw new InsufficientAddressCapacityException("There is no more address available in the network " + network.getName(), DataCenter.class,
|
|
network.getDataCenterId());
|
|
}
|
|
for (Vlan vlan : vlans) {
|
|
if (!_networkModel.isIP6AddressAvailableInVlan(vlan.getId())) {
|
|
continue;
|
|
}
|
|
ip = NetUtils.getIp6FromRange(vlan.getIp6Range());
|
|
int count = 0;
|
|
while (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) != null) {
|
|
ip = NetUtils.getNextIp6InRange(ip, vlan.getIp6Range());
|
|
count++;
|
|
// It's an arbitrate number to prevent the infinite loop
|
|
if (count > _ipv6RetryMax) {
|
|
ip = null;
|
|
break;
|
|
}
|
|
}
|
|
if (ip != null) {
|
|
ipVlan = vlan;
|
|
}
|
|
}
|
|
if (ip == null) {
|
|
throw new InsufficientAddressCapacityException("Cannot find a usable IP in the network " + network.getName() + " after " + _ipv6RetryMax +
|
|
"(network.ipv6.search.retry.max) times retry!", DataCenter.class, network.getDataCenterId());
|
|
}
|
|
} else {
|
|
for (Vlan vlan : vlans) {
|
|
if (NetUtils.isIp6InRange(requestedIp6, vlan.getIp6Range())) {
|
|
ipVlan = vlan;
|
|
break;
|
|
}
|
|
}
|
|
if (ipVlan == null) {
|
|
throw new CloudRuntimeException("Requested IPv6 is not in the predefined range!");
|
|
}
|
|
ip = requestedIp6;
|
|
if (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) != null) {
|
|
throw new CloudRuntimeException("The requested IP is already taken!");
|
|
}
|
|
}
|
|
DataCenterVO dc = _dcDao.findById(dcId);
|
|
Long mac = dc.getMacAddress();
|
|
Long nextMac = mac + 1;
|
|
dc.setMacAddress(nextMac);
|
|
_dcDao.update(dc.getId(), dc);
|
|
|
|
String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(mac));
|
|
UserIpv6AddressVO ipVO = new UserIpv6AddressVO(ip, dcId, macAddress, ipVlan.getId());
|
|
ipVO.setPhysicalNetworkId(network.getPhysicalNetworkId());
|
|
ipVO.setSourceNetworkId(networkId);
|
|
ipVO.setState(UserIpv6Address.State.Allocated);
|
|
ipVO.setDomainId(owner.getDomainId());
|
|
ipVO.setAccountId(owner.getAccountId());
|
|
_ipv6Dao.persist(ipVO);
|
|
return ipVO;
|
|
}
|
|
|
|
@Override
|
|
public void revokeDirectIpv6Address(long networkId, String ip6Address) {
|
|
UserIpv6AddressVO ip = _ipv6Dao.findByNetworkIdAndIp(networkId, ip6Address);
|
|
if (ip != null) {
|
|
_ipv6Dao.remove(ip.getId());
|
|
}
|
|
}
|
|
}
|