server: implement tiebreaker for VMs with same name/IP

The tiebreaker is first-come first serve - ie whichever VM had the name
or IP first wins (based on VM id). The sync() method now sorts the VM
list by id in order to evaluate the tiebreaker correctly (VM list comes
that way from ONED but just in case...).
master
Justin Riley 2016-09-28 11:18:14 -04:00
parent a7051e0689
commit 4c245819ce
2 changed files with 25 additions and 0 deletions

View File

@ -36,3 +36,11 @@ class RecordDoesNotExist(OneDnsException):
self.msg = "Record Does Not Exist: {}".format(key)
if val is not None:
self.msg += " -> {}".format(val)
class DuplicateVMError(OneDnsException):
"""
Raised when two or more VMs share a name or IP
"""
def __init__(self, vmid, key, val):
self.msg = "VM one-{} has a duplicate: {} -> {}".format(vmid, key, val)

View File

@ -31,10 +31,24 @@ class OneDNS(resolver.DynamicResolver):
entries[nicname] = nic.ip
return entries
def _check_for_duplicates(self, vm_id, name, ip, zone=None):
z = zone or self.zone
try:
f = z.get_forward(name)
raise exception.DuplicateVMError(vm_id, f, ip)
except exception.RecordDoesNotExist:
pass
try:
r = z.get_reverse(ip)
raise exception.DuplicateVMError(vm_id, ip, r)
except exception.RecordDoesNotExist:
pass
def add_vm(self, vm, zone=None):
dns_entries = self._get_vm_dns_entries(vm)
log.info("Adding VM {id}: {vm}".format(id=vm.id, vm=vm.name))
for name, ip in dns_entries.items():
self._check_for_duplicates(vm.id, name, ip, zone=zone)
self.add_host(name, ip, zone=zone)
def remove_vm(self, vm, zone=None):
@ -54,9 +68,12 @@ class OneDNS(resolver.DynamicResolver):
def sync(self, vms=None):
z = zone.Zone(self.domain)
vms = vms or self._one.vms()
vms.sort(key=lambda x: x.id)
for vm in vms:
try:
self.add_vm(vm, zone=z)
except exception.NoNetworksError as e:
e.log(warn=True)
except exception.DuplicateVMError as e:
e.log(warn=True)
self.load(z)