| // 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.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; |
| |
| 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,NetworkModel.MACIdentifier.value())); |
| 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()); |
| } |
| } |
| } |