mirror of https://github.com/apache/cloudstack.git
fix automatic dns record registration based on vm and nic lifecycle
This commit is contained in:
parent
8d10ae1094
commit
356781972e
|
|
@ -75,7 +75,6 @@ public interface DnsProviderManager extends Manager, PluggableService {
|
|||
|
||||
boolean disassociateZoneFromNetwork(DisassociateDnsZoneFromNetworkCmd cmd);
|
||||
|
||||
void addDnsRecordForVM(VirtualMachine instance, Network network, Nic nic);
|
||||
void deleteDnsRecordForVM(VirtualMachine instance, Network network, Nic nic);
|
||||
|
||||
void checkDnsServerPermission(Account caller, DnsServer dnsServer);
|
||||
|
|
|
|||
|
|
@ -317,5 +317,6 @@
|
|||
<bean id="dnsZoneNetworkMapDao" class="org.apache.cloudstack.dns.dao.DnsZoneNetworkMapDaoImpl" />
|
||||
<bean id="dnsServerJoinDao" class="org.apache.cloudstack.dns.dao.DnsServerJoinDaoImpl" />
|
||||
<bean id="dnsZoneJoinDao" class="org.apache.cloudstack.dns.dao.DnsZoneJoinDaoImpl" />
|
||||
<bean id="dnsNicJoinDao" class="org.apache.cloudstack.dns.dao.DnsNicJoinDaoImpl" />
|
||||
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.nics','enabled', 'TINYINT(1) NOT NUL
|
|||
-- ======================================================================
|
||||
|
||||
-- DNS Server Table (Stores DNS Server Configurations)
|
||||
CREATE TABLE `cloud`.`dns_server` (
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`dns_server` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id of the dns server',
|
||||
`uuid` varchar(40) COMMENT 'uuid of the dns server',
|
||||
`name` varchar(255) NOT NULL COMMENT 'display name of the dns server',
|
||||
|
|
@ -148,7 +148,7 @@ CREATE TABLE `cloud`.`dns_server` (
|
|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- DNS Zone Table (Stores DNS Zone Metadata)
|
||||
CREATE TABLE `cloud`.`dns_zone` (
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`dns_zone` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id of the dns zone',
|
||||
`uuid` varchar(40) COMMENT 'uuid of the dns zone',
|
||||
`name` varchar(255) NOT NULL COMMENT 'dns zone name (e.g. example.com)',
|
||||
|
|
@ -171,7 +171,7 @@ CREATE TABLE `cloud`.`dns_zone` (
|
|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- DNS Zone Network Map (One-to-Many Link)
|
||||
CREATE TABLE `cloud`.`dns_zone_network_map` (
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`dns_zone_network_map` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id of the dns zone to network mapping',
|
||||
`uuid` varchar(40),
|
||||
`dns_zone_id` bigint(20) unsigned NOT NULL,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
-- 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.
|
||||
|
||||
-- VIEW `cloud`.`dns_nic_view`;
|
||||
|
||||
DROP VIEW IF EXISTS `cloud`.`dns_nic_view`;
|
||||
CREATE VIEW `cloud`.`dns_nic_view` AS
|
||||
SELECT
|
||||
n.id AS id,
|
||||
n.uuid AS uuid,
|
||||
n.instance_id AS instance_id,
|
||||
n.network_id AS network_id,
|
||||
n.ip4_address AS ip4_address,
|
||||
n.ip6_address AS ip6_address,
|
||||
n.removed AS removed,
|
||||
nd.value AS nic_dns_url,
|
||||
map.dns_zone_id AS dns_zone_id,
|
||||
map.sub_domain AS sub_domain
|
||||
FROM
|
||||
`cloud`.`nics` n
|
||||
INNER JOIN
|
||||
`cloud`.`dns_zone_network_map` map ON n.network_id = map.network_id
|
||||
LEFT JOIN
|
||||
`cloud`.`nic_details` nd ON n.id = nd.nic_id AND nd.name = 'nicdnsrecord'
|
||||
WHERE
|
||||
map.removed IS NULL;
|
||||
|
|
@ -56,6 +56,7 @@ import org.apache.cloudstack.api.response.DnsZoneNetworkMapResponse;
|
|||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.dao.DnsNicJoinDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsServerDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsServerJoinDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsZoneDao;
|
||||
|
|
@ -63,7 +64,9 @@ import org.apache.cloudstack.dns.dao.DnsZoneJoinDao;
|
|||
import org.apache.cloudstack.dns.dao.DnsZoneNetworkMapDao;
|
||||
import org.apache.cloudstack.dns.exception.DnsConflictException;
|
||||
import org.apache.cloudstack.dns.exception.DnsNotFoundException;
|
||||
import org.apache.cloudstack.dns.exception.DnsProviderException;
|
||||
import org.apache.cloudstack.dns.exception.DnsTransportException;
|
||||
import org.apache.cloudstack.dns.vo.DnsNicJoinVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerJoinVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsZoneJoinVO;
|
||||
|
|
@ -73,7 +76,6 @@ import org.apache.cloudstack.framework.messagebus.MessageBus;
|
|||
import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
|
||||
import org.apache.cloudstack.framework.messagebus.PublishScope;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
|
@ -95,11 +97,11 @@ import com.cloud.utils.component.PluggableService;
|
|||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
|
||||
import com.cloud.utils.db.TransactionStatus;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.Nic;
|
||||
import com.cloud.vm.NicDetailVO;
|
||||
import com.cloud.vm.NicVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
|
|
@ -138,6 +140,8 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
MessageBus messageBus;
|
||||
@Inject
|
||||
VMInstanceDao vmInstanceDao;
|
||||
@Inject
|
||||
DnsNicJoinDao dnsNicJoinDao;
|
||||
|
||||
private DnsProvider getProviderByType(DnsProviderType type) {
|
||||
if (type == null) {
|
||||
|
|
@ -701,57 +705,6 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
return dnsZoneNetworkMapDao.remove(mapping.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDnsRecordForVM(VirtualMachine instance, Network network, Nic nic) {
|
||||
DnsZoneNetworkMapVO dnsZoneNetworkMap = dnsZoneNetworkMapDao.findByNetworkId(network.getId());
|
||||
if (dnsZoneNetworkMap == null) {
|
||||
logger.warn("No DNS zone is mapped to this network. Please associate a zone first.");
|
||||
return;
|
||||
}
|
||||
DnsZoneVO dnsZone = dnsZoneDao.findById(dnsZoneNetworkMap.getDnsZoneId());
|
||||
if (dnsZone == null || dnsZone.getState() != DnsZone.State.Active) {
|
||||
logger.warn("DNS zone is not available for DNS record setup");
|
||||
return;
|
||||
}
|
||||
DnsServerVO server = dnsServerDao.findById(dnsZone.getDnsServerId());
|
||||
if (server == null) {
|
||||
logger.warn("DNS server is not found to process DNS record for Instance: {}", instance.getInstanceName());
|
||||
return;
|
||||
}
|
||||
String recordName = finalizeDnsRecordNameForVm(instance, dnsZoneNetworkMap, server, dnsZone);
|
||||
String dnsRecordUrl = processDnsRecordInProvider(recordName, instance, server, dnsZone, nic, true);
|
||||
if (Strings.isBlank(dnsRecordUrl)) {
|
||||
logger.error("Failed to add DNS record in provider for Instance: {}", instance.getInstanceName());
|
||||
return;
|
||||
}
|
||||
nicDetailsDao.addDetail(nic.getId(), ApiConstants.NIC_DNS_RECORD, dnsRecordUrl, true);
|
||||
}
|
||||
|
||||
private String finalizeDnsRecordNameForVm(VirtualMachine instance, DnsZoneNetworkMapVO dnsZoneNetworkMap, DnsServerVO server, DnsZoneVO dnsZone) {
|
||||
String recordName;
|
||||
// Construct FQDN Prefix (e.g., "hostname.dnsZoneName" or "hostname.subdomain.dnsZoneName")
|
||||
try {
|
||||
List<String> parts = new ArrayList<>();
|
||||
parts.add(instance.getHostName());
|
||||
if (StringUtils.isNotBlank(dnsZoneNetworkMap.getSubDomain())) {
|
||||
parts.add(dnsZoneNetworkMap.getSubDomain());
|
||||
}
|
||||
parts.add(dnsZone.getName());
|
||||
recordName = String.join(".", parts);
|
||||
|
||||
DnsProvider provider = getProviderByType(server.getProviderType());
|
||||
boolean dnsRecordExist = provider.dnsRecordExists(server, dnsZone, recordName, DnsRecord.RecordType.A.toString());
|
||||
if (dnsRecordExist) {
|
||||
String randomPrefix = RandomStringUtils.randomAlphanumeric(3).toLowerCase();
|
||||
recordName = randomPrefix + "-" + recordName;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed while constructing DNS record name for Instance: {} ", instance.getInstanceName(), ex);
|
||||
throw new CloudRuntimeException("Error occurred during DNS record registration for Instance: " + instance.getInstanceName());
|
||||
}
|
||||
return recordName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDnsRecordForVM(VirtualMachine instance, Network network, Nic nic) {
|
||||
String instanceName = instance.getInstanceName();
|
||||
|
|
@ -918,11 +871,11 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
long instanceId = (long) event.get(ApiConstants.INSTANCE_ID);
|
||||
switch (newState) {
|
||||
case Running:
|
||||
handleVmEvent(instanceId, true);
|
||||
handleVmRunningState(instanceId);
|
||||
break;
|
||||
case Stopped:
|
||||
case Destroyed:
|
||||
handleVmEvent(instanceId, false);
|
||||
handleVmStopAndDestroy(instanceId);
|
||||
break;
|
||||
default:
|
||||
logger.warn("Ignoring lifecycle event for Instance ID: {}, unsupported state={}", instanceId, newState);
|
||||
|
|
@ -950,9 +903,9 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
return;
|
||||
}
|
||||
if (EVENT_NIC_CREATE.equals(eventType)) {
|
||||
handleNicEvent(nicId, instanceId, true);
|
||||
handleNicPlug(instanceId, nicId);
|
||||
} else if (EVENT_NIC_DELETE.equals(eventType)) {
|
||||
handleNicEvent(nicId, instanceId, false);
|
||||
handleNicUnplug(instanceId, nicId);
|
||||
} else {
|
||||
logger.warn("Ignoring lifecycle event for NIC with ID: {}, unsupported eventType={}", nicId, eventType);
|
||||
}
|
||||
|
|
@ -993,49 +946,6 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
}
|
||||
}
|
||||
|
||||
private void handleNicEvent(long nicId, long instanceId, boolean isAddDnsRecord) {
|
||||
VMInstanceVO vmInstanceVO = vmInstanceDao.findById(instanceId);
|
||||
if (vmInstanceVO == null) {
|
||||
logger.error("Unable to find Instance with ID: {}", instanceId);
|
||||
return;
|
||||
}
|
||||
Nic nic = nicDao.findByIdIncludingRemoved(nicId);
|
||||
if (nic == null) {
|
||||
logger.error("NIC is not found for the ID: {}", nicId);
|
||||
return;
|
||||
}
|
||||
Network network = networkDao.findById(nic.getNetworkId());
|
||||
if (network == null || !Network.GuestType.Shared.equals(network.getGuestType())) {
|
||||
logger.warn("Network is not eligible for DNS record registration");
|
||||
return;
|
||||
}
|
||||
processEventForDnsRecord(vmInstanceVO, network, nic, isAddDnsRecord);
|
||||
}
|
||||
|
||||
private void handleVmEvent(long instanceId, boolean isAddDnsRecord) {
|
||||
VMInstanceVO vmInstanceVO = vmInstanceDao.findByIdIncludingRemoved(instanceId);
|
||||
if (vmInstanceVO == null) {
|
||||
logger.error("Unable to find Instance with ID: {}", instanceId);
|
||||
return;
|
||||
}
|
||||
List<NicVO> vmNics = nicDao.listByVmIdIncludingRemoved(vmInstanceVO.getId());
|
||||
for (NicVO nic : vmNics) {
|
||||
Network network = networkDao.findById(nic.getNetworkId());
|
||||
if (network == null || !Network.GuestType.Shared.equals(network.getGuestType())) {
|
||||
continue;
|
||||
}
|
||||
processEventForDnsRecord(vmInstanceVO, network, nic, isAddDnsRecord);
|
||||
}
|
||||
}
|
||||
|
||||
void processEventForDnsRecord(VMInstanceVO vmInstanceVO, Network network, Nic nic, boolean isAddDnsRecord) {
|
||||
if (isAddDnsRecord) {
|
||||
addDnsRecordForVM(vmInstanceVO, network, nic);
|
||||
} else {
|
||||
deleteDnsRecordForVM(vmInstanceVO, network, nic);
|
||||
}
|
||||
}
|
||||
|
||||
void publishDnsRecordEventMessageBus(String dnsRecord, DnsRecord.RecordType recordType, Long accountId,
|
||||
String eventType, List<String> contents) {
|
||||
|
||||
|
|
@ -1056,4 +966,215 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa
|
|||
logger.error("Failed to publish {} event for DNS record: {}", eventType, dnsRecord, ex);
|
||||
}
|
||||
}
|
||||
|
||||
void handleVmRunningState(long instanceId) {
|
||||
VirtualMachine instance = vmInstanceDao.findById(instanceId);
|
||||
if (instance == null) {
|
||||
logger.debug("Instance is not found for the given ID: {}", instanceId);
|
||||
return;
|
||||
}
|
||||
List<DnsNicJoinVO> mappedNics = dnsNicJoinDao.listActiveByVmId(instanceId);
|
||||
if (CollectionUtils.isEmpty(mappedNics)) {
|
||||
logger.debug("No active DNS zone associated to NICs");
|
||||
return;
|
||||
}
|
||||
Map<Long, Map<String, List<DnsNicJoinVO>>> dnsZoneRecordNicMap = new HashMap<>();
|
||||
for (DnsNicJoinVO nic : mappedNics) {
|
||||
DnsZoneVO targetZone = dnsZoneDao.findById(nic.getDnsZoneId());
|
||||
if (targetZone == null) {
|
||||
continue;
|
||||
}
|
||||
String targetDnsRecordUrl = prepareDnsRecordUrl(instance.getHostName(), nic.getSubDomain(), targetZone.getName());
|
||||
dnsZoneRecordNicMap.computeIfAbsent(targetZone.getId(), k -> new HashMap<>())
|
||||
.computeIfAbsent(targetDnsRecordUrl, k -> new ArrayList<>())
|
||||
.add(nic);
|
||||
}
|
||||
|
||||
for (Map.Entry<Long, Map<String, List<DnsNicJoinVO>>> zoneEntry : dnsZoneRecordNicMap.entrySet()) {
|
||||
long targetZoneId = zoneEntry.getKey();
|
||||
for (Map.Entry<String, List<DnsNicJoinVO>> dnsUrlEntry : zoneEntry.getValue().entrySet()) {
|
||||
String dnsRecordUrl = dnsUrlEntry.getKey();
|
||||
List<DnsNicJoinVO> nicsForThisFqdn = dnsUrlEntry.getValue();
|
||||
try {
|
||||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<DnsProviderException>() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws DnsProviderException{
|
||||
DnsNicJoinVO existing = dnsNicJoinDao.findActiveByDnsRecordAndZone(dnsRecordUrl, targetZoneId);
|
||||
if (existing != null && existing.getInstanceId() != instanceId) {
|
||||
logger.error("DNS Collision: Cannot register DNS record: {}. Already owned by Instance: {}.",
|
||||
dnsRecordUrl, existing.getInstanceId());
|
||||
return;
|
||||
}
|
||||
for (DnsNicJoinVO nic : nicsForThisFqdn) {
|
||||
nicDetailsDao.addDetail(nic.getId(), ApiConstants.NIC_DNS_RECORD, dnsRecordUrl, true);
|
||||
}
|
||||
syncDnsState(instanceId, dnsRecordUrl, targetZoneId);
|
||||
}
|
||||
});
|
||||
} catch (DnsProviderException ex) {
|
||||
logger.error("Failed to register DNS record: {} in provider for Instance: {}", dnsRecordUrl, instance.getUuid(), ex);
|
||||
} catch (Exception ex) {
|
||||
logger.warn("Failed to register DNS record: {} for Instance: {}", dnsRecordUrl, instance.getUuid(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleVmStopAndDestroy(long instanceId) {
|
||||
List<DnsNicJoinVO> historicalNics = dnsNicJoinDao.listIncludingRemovedByVmId(instanceId);
|
||||
if (CollectionUtils.isEmpty(historicalNics)) {
|
||||
return;
|
||||
}
|
||||
Map<Long, Map<String, List<DnsNicJoinVO>>> groupByDnsZone = new HashMap<>();
|
||||
for (DnsNicJoinVO nic : historicalNics) {
|
||||
// If the DNS record url is null, it means this NIC was never registered in nic_details
|
||||
if (nic.getNicDnsUrl() == null) {
|
||||
continue;
|
||||
}
|
||||
groupByDnsZone
|
||||
.computeIfAbsent(nic.getDnsZoneId(), k -> new HashMap<>())
|
||||
.computeIfAbsent(nic.getNicDnsUrl(), k -> new ArrayList<>())
|
||||
.add(nic);
|
||||
}
|
||||
|
||||
for (Map.Entry<Long, Map<String, List<DnsNicJoinVO>>> zoneEntry : groupByDnsZone.entrySet()) {
|
||||
long targetZoneId = zoneEntry.getKey();
|
||||
for (Map.Entry<String, List<DnsNicJoinVO>> dnsRecordEntry : zoneEntry.getValue().entrySet()) {
|
||||
String dnsRecordUrl = dnsRecordEntry.getKey();
|
||||
List<DnsNicJoinVO> nicsForDnsUrl = dnsRecordEntry.getValue();
|
||||
|
||||
try {
|
||||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<DnsProviderException>() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws DnsProviderException {
|
||||
for (DnsNicJoinVO nic : nicsForDnsUrl) {
|
||||
nicDetailsDao.removeDetail(nic.getId(), ApiConstants.NIC_DNS_RECORD);
|
||||
}
|
||||
// Because we just deleted the nic_details, the sync method will naturally
|
||||
// find 0 active IPs for this VM/FQDN combo and issue a clean DELETE to PowerDNS.
|
||||
syncDnsState(instanceId, dnsRecordUrl, targetZoneId);
|
||||
}
|
||||
});
|
||||
logger.debug("Successfully cleaned up DNS record: {} for Instance with ID: {}", dnsRecordUrl, instanceId);
|
||||
} catch (DnsProviderException ex) {
|
||||
logger.error("Failed to cleanup DNS record: {} in provider", dnsRecordUrl, ex);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed DNS record: {} cleanup for Instance", dnsRecordUrl, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleNicPlug(long instanceId, long nicId) {
|
||||
VirtualMachine instance = vmInstanceDao.findById(instanceId);
|
||||
if (instance == null || instance.getState() != VirtualMachine.State.Running) {
|
||||
return;
|
||||
}
|
||||
DnsNicJoinVO nic = dnsNicJoinDao.findById(nicId);
|
||||
if (nic == null) {
|
||||
logger.debug("NIC with ID: {} doesn't have DNS zone associated", nicId);
|
||||
return;
|
||||
}
|
||||
|
||||
DnsZoneVO targetZone = dnsZoneDao.findById(nic.getDnsZoneId());
|
||||
if (targetZone == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String dnsRecordUrl = prepareDnsRecordUrl(instance.getHostName(), nic.getSubDomain(), targetZone.getName());
|
||||
try {
|
||||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<DnsProviderException>() {
|
||||
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws DnsProviderException {
|
||||
DnsNicJoinVO existing = dnsNicJoinDao.findActiveByDnsRecordAndZone(dnsRecordUrl, targetZone.getId());
|
||||
if (existing != null && existing.getInstanceId() != instanceId) {
|
||||
logger.error("DNS Collision: Cannot register DNS record: {}. Already owned by Instance: {}.",
|
||||
dnsRecordUrl, existing.getInstanceId());
|
||||
return;
|
||||
}
|
||||
nicDetailsDao.addDetail(nicId, ApiConstants.NIC_DNS_RECORD, dnsRecordUrl, true);
|
||||
syncDnsState(instanceId, dnsRecordUrl, targetZone.getId());
|
||||
logger.debug("Successfully synced DNS on NIC Plug for: {}", dnsRecordUrl);
|
||||
}
|
||||
});
|
||||
} catch (DnsProviderException ex) {
|
||||
logger.error("Failed to register DNS record: {} in provider for Instance: {}", dnsRecordUrl, instance.getUuid(), ex);
|
||||
} catch (Exception ex) {
|
||||
logger.warn("Failed to register DNS record: {} for Instance: {}", dnsRecordUrl, instance.getUuid(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
void handleNicUnplug(long instanceId, long nicId) {
|
||||
DnsNicJoinVO nic = dnsNicJoinDao.findByIdIncludingRemoved(nicId);
|
||||
if (nic == null || nic.getNicDnsUrl() == null) {
|
||||
return;
|
||||
}
|
||||
String dnsRecordUrl = nic.getNicDnsUrl();
|
||||
long dnsZoneId = nic.getDnsZoneId();
|
||||
|
||||
try {
|
||||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<DnsProviderException>() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws DnsProviderException {
|
||||
nicDetailsDao.removeDetail(nicId, ApiConstants.NIC_DNS_RECORD);
|
||||
syncDnsState(instanceId, dnsRecordUrl, dnsZoneId);
|
||||
logger.debug("Successfully synced DNS record: {} on NIC unplug", dnsRecordUrl);
|
||||
}
|
||||
});
|
||||
} catch (DnsProviderException ex) {
|
||||
logger.error("Failed to sync DNS record: {} on NIC unplug in provider", dnsRecordUrl);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed to sync DNS record: {} on NIC unplug ", dnsRecordUrl);
|
||||
}
|
||||
}
|
||||
|
||||
String prepareDnsRecordUrl(String hostName, String subDomain, String dnsZoneName) {
|
||||
List<String> parts = new ArrayList<>();
|
||||
parts.add(hostName);
|
||||
if (StringUtils.isNotBlank(subDomain)) {
|
||||
parts.add(subDomain.trim());
|
||||
}
|
||||
parts.add(dnsZoneName);
|
||||
return String.join(".", parts);
|
||||
}
|
||||
|
||||
public void syncDnsState(Long instanceId, String dnsRecordUrl, long dnsZoneId) throws DnsProviderException {
|
||||
DnsZone dnsZone = dnsZoneDao.findById(dnsZoneId);
|
||||
if (dnsZone == null) {
|
||||
logger.error("DNS zone not found for the provided ID: {}", dnsZoneId);
|
||||
return;
|
||||
}
|
||||
DnsServerVO dnsServer = dnsServerDao.findById(dnsZone.getDnsServerId());
|
||||
List<DnsNicJoinVO> activeNics = dnsNicJoinDao.listActiveByVmIdZoneAndDnsRecord(instanceId, dnsZoneId, dnsRecordUrl);
|
||||
|
||||
List<String> ipv4s = new ArrayList<>();
|
||||
List<String> ipv6s = new ArrayList<>();
|
||||
for (DnsNicJoinVO nic : activeNics) {
|
||||
if (nic.getIp4Address() != null && !nic.getIp4Address().isEmpty()) {
|
||||
ipv4s.add(nic.getIp4Address());
|
||||
}
|
||||
if (nic.getIp6Address() != null && !nic.getIp6Address().isEmpty()) {
|
||||
ipv6s.add(nic.getIp6Address());
|
||||
}
|
||||
}
|
||||
logger.debug("Syncing DNS for: {}. Found: {} IPv4s and {} IPv6s.", dnsRecordUrl, ipv4s.size(), ipv6s.size());
|
||||
DnsProvider provider = getProviderByType(dnsServer.getProviderType());
|
||||
DnsRecord recordIpv4 = new DnsRecord(dnsRecordUrl, DnsRecord.RecordType.A, null, 3600);
|
||||
// push A records into Provider
|
||||
if (ipv4s.isEmpty()) {
|
||||
provider.deleteRecord(dnsServer, dnsZone, recordIpv4);
|
||||
} else {
|
||||
recordIpv4.setContents(ipv4s);
|
||||
provider.addRecord(dnsServer, dnsZone, recordIpv4);
|
||||
}
|
||||
// push AAAA records into Provider
|
||||
DnsRecord recordIpv6 = new DnsRecord(dnsRecordUrl, DnsRecord.RecordType.AAAA, null, 3600);
|
||||
if (ipv6s.isEmpty()) {
|
||||
provider.deleteRecord(dnsServer, dnsZone, recordIpv6);
|
||||
} else {
|
||||
recordIpv6.setContents(ipv6s);
|
||||
provider.addRecord(dnsServer, dnsZone, recordIpv6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
// 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 org.apache.cloudstack.dns.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.dns.vo.DnsNicJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface DnsNicJoinDao extends GenericDao<DnsNicJoinVO, Long> {
|
||||
|
||||
/**
|
||||
* Used for Collision Checks.
|
||||
* @param dnsRecordUrl
|
||||
* @param dnsZoneId
|
||||
* @return active records to see who currently owns the dnsRecordUrl.
|
||||
*/
|
||||
DnsNicJoinVO findActiveByDnsRecordAndZone(String dnsRecordUrl, long dnsZoneId);
|
||||
|
||||
/**
|
||||
* Used to sync DNS record url based on available ips for vmId in the dnsZone
|
||||
* @param vmId
|
||||
* @param dnsZoneId
|
||||
* @param dnsRecordUrl
|
||||
* @return list of active nics using the dnsRecordUrl, supports null vmId for dnsZone wide query
|
||||
*/
|
||||
List<DnsNicJoinVO> listActiveByVmIdZoneAndDnsRecord(Long vmId, long dnsZoneId, String dnsRecordUrl);
|
||||
|
||||
/**
|
||||
* Used for VM Start/Running
|
||||
* @param vmId
|
||||
* @return records associated to vmId
|
||||
*/
|
||||
List<DnsNicJoinVO> listActiveByVmId(long vmId);
|
||||
|
||||
/**
|
||||
* Used by Instance Destroy/Stop or NIC delete
|
||||
* @param vmId
|
||||
* @return records with soft-delete
|
||||
*/
|
||||
List<DnsNicJoinVO> listIncludingRemovedByVmId(long vmId);
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
// 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 org.apache.cloudstack.dns.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.dns.vo.DnsNicJoinVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
public class DnsNicJoinDaoImpl extends GenericDaoBase<DnsNicJoinVO, Long> implements DnsNicJoinDao {
|
||||
private final SearchBuilder<DnsNicJoinVO> activeDnsRecordZoneSearch;
|
||||
private final SearchBuilder<DnsNicJoinVO> activeVmZoneDnsRecordSearch; // Route for null vmId
|
||||
private final SearchBuilder<DnsNicJoinVO> activeVmSearch;
|
||||
|
||||
public DnsNicJoinDaoImpl() {
|
||||
|
||||
activeDnsRecordZoneSearch = createSearchBuilder();
|
||||
activeDnsRecordZoneSearch.and(ApiConstants.NIC_DNS_RECORD, activeDnsRecordZoneSearch.entity().getNicDnsUrl(), SearchCriteria.Op.EQ);
|
||||
activeDnsRecordZoneSearch.and(ApiConstants.DNS_ZONE_ID, activeDnsRecordZoneSearch.entity().getDnsZoneId(), SearchCriteria.Op.EQ);
|
||||
activeDnsRecordZoneSearch.and(ApiConstants.REMOVED, activeDnsRecordZoneSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
activeDnsRecordZoneSearch.done();
|
||||
|
||||
activeVmZoneDnsRecordSearch = createSearchBuilder();
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.INSTANCE_ID, activeVmZoneDnsRecordSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.NIC_DNS_RECORD, activeVmZoneDnsRecordSearch.entity().getNicDnsUrl(), SearchCriteria.Op.EQ);
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.DNS_ZONE_ID, activeVmZoneDnsRecordSearch.entity().getDnsZoneId(), SearchCriteria.Op.EQ);
|
||||
activeVmZoneDnsRecordSearch.and(ApiConstants.REMOVED, activeVmZoneDnsRecordSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
activeVmZoneDnsRecordSearch.done();
|
||||
|
||||
activeVmSearch = createSearchBuilder();
|
||||
activeVmSearch.and(ApiConstants.INSTANCE_ID, activeVmSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
activeVmSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsNicJoinVO findActiveByDnsRecordAndZone(String dnsRecordUrl, long dnsZoneId) {
|
||||
SearchCriteria<DnsNicJoinVO> sc = activeDnsRecordZoneSearch.create();
|
||||
sc.setParameters(ApiConstants.NIC_DNS_RECORD, dnsRecordUrl);
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DnsNicJoinVO> listActiveByVmIdZoneAndDnsRecord(Long vmId, long dnsZoneId, String dnsRecordUrl) {
|
||||
if (vmId != null) {
|
||||
SearchCriteria<DnsNicJoinVO> sc = activeDnsRecordZoneSearch.create();
|
||||
sc.setParameters(ApiConstants.INSTANCE_ID, vmId);
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
sc.setParameters(ApiConstants.NIC_DNS_RECORD, dnsRecordUrl);
|
||||
return listBy(sc);
|
||||
} else {
|
||||
SearchCriteria<DnsNicJoinVO> sc = activeDnsRecordZoneSearch.create();
|
||||
sc.setParameters(ApiConstants.NIC_DNS_RECORD, dnsRecordUrl);
|
||||
sc.setParameters(ApiConstants.DNS_ZONE_ID, dnsZoneId);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DnsNicJoinVO> listActiveByVmId(long vmId) {
|
||||
SearchCriteria<DnsNicJoinVO> sc = activeVmSearch.create();
|
||||
sc.setParameters(ApiConstants.INSTANCE_ID, vmId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DnsNicJoinVO> listIncludingRemovedByVmId(long vmId) {
|
||||
SearchCriteria<DnsNicJoinVO> sc = activeVmSearch.create();
|
||||
sc.setParameters(ApiConstants.INSTANCE_ID, vmId);
|
||||
return listIncludingRemovedBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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 org.apache.cloudstack.dns.vo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.api.Identity;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import com.cloud.api.query.vo.BaseViewVO;
|
||||
|
||||
@Entity
|
||||
@Table(name = "dns_nic_view")
|
||||
public class DnsNicJoinVO extends BaseViewVO implements InternalIdentity, Identity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "uuid")
|
||||
private String uuid;
|
||||
|
||||
@Column(name = "instance_id")
|
||||
private long instanceId;
|
||||
|
||||
@Column(name = "network_id")
|
||||
private long networkId;
|
||||
|
||||
@Column(name = "ip4_address")
|
||||
private String ip4Address;
|
||||
|
||||
@Column(name = "ip6_address")
|
||||
private String ip6Address;
|
||||
|
||||
@Column(name = "nic_dns_url")
|
||||
private String nicDnsUrl;
|
||||
|
||||
@Column(name = "dns_zone_id")
|
||||
private long dnsZoneId;
|
||||
|
||||
@Column(name = "sub_domain")
|
||||
private String subDomain;
|
||||
|
||||
@Column(name = "removed")
|
||||
private Date removed;
|
||||
|
||||
public DnsNicJoinVO() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public long getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public long getDnsZoneId() {
|
||||
return dnsZoneId;
|
||||
}
|
||||
|
||||
public String getSubDomain() {
|
||||
return subDomain;
|
||||
}
|
||||
|
||||
public String getNicDnsUrl() {
|
||||
return nicDnsUrl;
|
||||
}
|
||||
|
||||
public String getIp4Address() {
|
||||
return ip4Address;
|
||||
}
|
||||
|
||||
public String getIp6Address() {
|
||||
return ip6Address;
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@ import org.apache.cloudstack.api.response.DnsZoneNetworkMapResponse;
|
|||
import org.apache.cloudstack.api.response.DnsZoneResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.dns.dao.DnsNicJoinDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsServerDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsServerJoinDao;
|
||||
import org.apache.cloudstack.dns.dao.DnsZoneDao;
|
||||
|
|
@ -59,7 +60,6 @@ import org.apache.cloudstack.dns.dao.DnsZoneJoinDao;
|
|||
import org.apache.cloudstack.dns.dao.DnsZoneNetworkMapDao;
|
||||
import org.apache.cloudstack.dns.exception.DnsConflictException;
|
||||
import org.apache.cloudstack.dns.exception.DnsNotFoundException;
|
||||
import org.apache.cloudstack.dns.exception.DnsProviderException;
|
||||
import org.apache.cloudstack.dns.exception.DnsTransportException;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerJoinVO;
|
||||
import org.apache.cloudstack.dns.vo.DnsServerVO;
|
||||
|
|
@ -130,6 +130,8 @@ public class DnsProviderManagerImplTest {
|
|||
@Mock
|
||||
NicDetailsDao nicDetailsDao;
|
||||
@Mock
|
||||
DnsNicJoinDao dnsNicJoinDao;
|
||||
@Mock
|
||||
MessageBus messageBus;
|
||||
@Mock
|
||||
VMInstanceDao vmInstanceDao;
|
||||
|
|
@ -571,51 +573,6 @@ public class DnsProviderManagerImplTest {
|
|||
manager.checkDnsZonePermission(callerMock, zoneVO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddDnsRecordForVMNoNetworkMapping() throws DnsProviderException {
|
||||
Network network = mock(Network.class);
|
||||
NicVO nic = mock(NicVO.class);
|
||||
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||
when(dnsZoneNetworkMapDao.findByNetworkId(anyLong())).thenReturn(null);
|
||||
when(network.getId()).thenReturn(NETWORK_ID);
|
||||
manager.addDnsRecordForVM(vm, network, nic);
|
||||
verify(dnsProviderMock, never()).addRecord(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddDnsRecordForVMInactiveZone() {
|
||||
Network network = mock(Network.class);
|
||||
NicVO nic = mock(NicVO.class);
|
||||
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||
DnsZoneNetworkMapVO mapping = mock(DnsZoneNetworkMapVO.class);
|
||||
when(network.getId()).thenReturn(NETWORK_ID);
|
||||
when(dnsZoneNetworkMapDao.findByNetworkId(NETWORK_ID)).thenReturn(mapping);
|
||||
when(mapping.getDnsZoneId()).thenReturn(ZONE_ID);
|
||||
DnsZoneVO inactiveZone = Mockito.spy(new DnsZoneVO("ex.com", DnsZone.ZoneType.Public, SERVER_ID, ACCOUNT_ID, DOMAIN_ID, ""));
|
||||
// state defaults to Inactive
|
||||
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(inactiveZone);
|
||||
manager.addDnsRecordForVM(vm, network, nic);
|
||||
verify(dnsServerDao, never()).findById(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddDnsRecordForVMServerMissing() {
|
||||
Network network = mock(Network.class);
|
||||
NicVO nic = mock(NicVO.class);
|
||||
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||
DnsZoneNetworkMapVO mapping = mock(DnsZoneNetworkMapVO.class);
|
||||
when(network.getId()).thenReturn(NETWORK_ID);
|
||||
when(dnsZoneNetworkMapDao.findByNetworkId(NETWORK_ID)).thenReturn(mapping);
|
||||
when(mapping.getDnsZoneId()).thenReturn(ZONE_ID);
|
||||
DnsZoneVO activeZone = Mockito.spy(new DnsZoneVO("ex.com", DnsZone.ZoneType.Public, SERVER_ID, ACCOUNT_ID, DOMAIN_ID, ""));
|
||||
activeZone.setState(DnsZone.State.Active);
|
||||
when(dnsZoneDao.findById(ZONE_ID)).thenReturn(activeZone);
|
||||
when(dnsServerDao.findById(SERVER_ID)).thenReturn(null);
|
||||
when(vm.getInstanceName()).thenReturn("vm-1");
|
||||
manager.addDnsRecordForVM(vm, network, nic);
|
||||
verify(nicDetailsDao, never()).addDetail(anyLong(), anyString(), anyString(), eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteDnsRecordForVMNoNicDetail() {
|
||||
Network network = mock(Network.class);
|
||||
|
|
@ -642,32 +599,6 @@ public class DnsProviderManagerImplTest {
|
|||
verify(dnsZoneNetworkMapDao, never()).findByNetworkId(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessEventForDnsRecordAdd() throws Exception {
|
||||
Network network = mock(Network.class);
|
||||
NicVO nic = mock(NicVO.class);
|
||||
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||
|
||||
when(dnsZoneNetworkMapDao.findByNetworkId(anyLong())).thenReturn(null);
|
||||
when(network.getId()).thenReturn(NETWORK_ID);
|
||||
manager.processEventForDnsRecord(vm, network, nic, true);
|
||||
// addDnsRecordForVM was called → returns early because no mapping
|
||||
verify(dnsZoneNetworkMapDao, times(1)).findByNetworkId(NETWORK_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessEventForDnsRecordDelete() {
|
||||
Network network = mock(Network.class);
|
||||
NicVO nic = mock(NicVO.class);
|
||||
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||
|
||||
when(nic.getId()).thenReturn(50L);
|
||||
when(vm.getInstanceName()).thenReturn("vm-1");
|
||||
when(nicDetailsDao.findDetail(50L, "nicdnsrecord")).thenReturn(null);
|
||||
manager.processEventForDnsRecord(vm, network, nic, false);
|
||||
verify(nicDetailsDao, times(1)).findDetail(50L, "nicdnsrecord");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCommandsReturnsNonEmptyList() {
|
||||
List<Class<?>> commands = manager.getCommands();
|
||||
|
|
@ -820,31 +751,6 @@ public class DnsProviderManagerImplTest {
|
|||
verify(messageBus, times(3)).subscribe(anyString(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleVmEventAndNicEvent() throws Exception {
|
||||
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||
NicVO nic = mock(NicVO.class);
|
||||
NetworkVO network = mock(NetworkVO.class);
|
||||
when(network.getId()).thenReturn(NETWORK_ID);
|
||||
|
||||
when(vmInstanceDao.findById(10L)).thenReturn(vm);
|
||||
when(nicDao.findByIdIncludingRemoved(50L)).thenReturn(nic);
|
||||
when(nic.getNetworkId()).thenReturn(NETWORK_ID);
|
||||
when(networkDao.findById(NETWORK_ID)).thenReturn(network);
|
||||
when(network.getGuestType()).thenReturn(Network.GuestType.Shared);
|
||||
when(dnsZoneNetworkMapDao.findByNetworkId(NETWORK_ID)).thenReturn(null);
|
||||
|
||||
org.springframework.test.util.ReflectionTestUtils.invokeMethod(manager, "handleNicEvent", 50L, 10L, true);
|
||||
verify(dnsZoneNetworkMapDao, times(1)).findByNetworkId(NETWORK_ID);
|
||||
|
||||
when(vmInstanceDao.findByIdIncludingRemoved(10L)).thenReturn(vm);
|
||||
when(vm.getId()).thenReturn(10L);
|
||||
when(nicDao.listByVmIdIncludingRemoved(10L)).thenReturn(Collections.singletonList(nic));
|
||||
|
||||
org.springframework.test.util.ReflectionTestUtils.invokeMethod(manager, "handleVmEvent", 10L, true);
|
||||
verify(dnsZoneNetworkMapDao, times(2)).findByNetworkId(NETWORK_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddDnsServerSuccess() throws Exception {
|
||||
org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd cmd = mock(org.apache.cloudstack.api.command.user.dns.AddDnsServerCmd.class);
|
||||
|
|
@ -1011,10 +917,10 @@ public class DnsProviderManagerImplTest {
|
|||
event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 12L);
|
||||
|
||||
// Expect handleVmEvent to be called, which accesses vmInstanceDao.findByIdIncludingRemoved
|
||||
when(vmInstanceDao.findByIdIncludingRemoved(12L)).thenReturn(null);
|
||||
when(vmInstanceDao.findById(12L)).thenReturn(null);
|
||||
|
||||
subscriber.onPublishMessage("sender", "subject", event);
|
||||
verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(12L);
|
||||
verify(vmInstanceDao, times(1)).findById(12L);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1024,11 +930,9 @@ public class DnsProviderManagerImplTest {
|
|||
event.put(org.apache.cloudstack.api.ApiConstants.OLD_STATE, com.cloud.vm.VirtualMachine.State.Running);
|
||||
event.put(org.apache.cloudstack.api.ApiConstants.NEW_STATE, com.cloud.vm.VirtualMachine.State.Stopped);
|
||||
event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 15L);
|
||||
|
||||
when(vmInstanceDao.findByIdIncludingRemoved(15L)).thenReturn(null);
|
||||
|
||||
when(dnsNicJoinDao.listIncludingRemovedByVmId(15L)).thenReturn(null);
|
||||
subscriber.onPublishMessage("sender", "subject", event);
|
||||
verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(15L);
|
||||
verify(dnsNicJoinDao, times(1)).listIncludingRemovedByVmId(15L);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1073,11 +977,9 @@ public class DnsProviderManagerImplTest {
|
|||
event.put(org.apache.cloudstack.api.ApiConstants.EVENT_TYPE, com.cloud.event.EventTypes.EVENT_NIC_DELETE);
|
||||
event.put(org.apache.cloudstack.api.ApiConstants.NIC_ID, 101L);
|
||||
event.put(org.apache.cloudstack.api.ApiConstants.INSTANCE_ID, 201L);
|
||||
|
||||
when(vmInstanceDao.findById(201L)).thenReturn(null);
|
||||
|
||||
when(dnsNicJoinDao.findByIdIncludingRemoved(101L)).thenReturn(null);
|
||||
subscriber.onPublishMessage("sender", "subject", event);
|
||||
verify(vmInstanceDao, times(1)).findById(201L);
|
||||
verify(dnsNicJoinDao, times(1)).findByIdIncludingRemoved(101L);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue