diff --git a/onedns/api.py b/onedns/api.py new file mode 100644 index 0000000..159bdde --- /dev/null +++ b/onedns/api.py @@ -0,0 +1,59 @@ +from onedns.clients import one +from onedns.clients import skydns +from onedns.logger import log + + +class OneDNS(object): + """ + This class bridges the gap between OpenNebula and SkyDNS APIs. It primarily + provides convenience methods for adding/removing VMs to SkyDNS. + """ + + def __init__(self, domain, one_kwargs={}, etcd_kwargs={}): + self._one = one.OneClient(**one_kwargs) + self._skydns = skydns.SkyDNSClient(domain, etcd_kwargs=etcd_kwargs) + + def _get_vm_dns_entries(self, vm): + entries = {} + if not hasattr(vm.template, 'nics'): + return entries + hostname = vm.name + primary_ip = vm.template.nics[0].ip + entries[hostname] = primary_ip + for nic in vm.template.nics[1:]: + nicname = "{hostname}-{id}".format(hostname=hostname, + id=nic.nic_id) + entries[nicname] = nic.ip + return entries + + def add_vm(self, vm): + dns_entries = self._get_vm_dns_entries(vm) + if not dns_entries: + log.warn("No networks found for VM {id}: {vm} - skipping".format( + vm=vm.name, id=vm.id)) + return + log.info("Adding VM {id}: {vm}".format(id=vm.id, vm=vm.name)) + for name, ip in dns_entries.items(): + self._skydns.add_host(name, ip) + + def remove_vm(self, vm): + dns_entries = self._get_vm_dns_entries(vm) + if not dns_entries: + log.warn("No networks found for VM {id}: {vm} - skipping".format( + vm=vm.name, id=vm.id)) + return + log.info("Removing VM {id}: {vm}".format(id=vm.id, vm=vm.name)) + for name, ip in dns_entries.items(): + self._skydns.remove_host(name, ip) + + def add_vm_by_id(self, vm_id): + vm = self._one.get_vm_by_id(vm_id) + return self.add_vm(vm) + + def remove_vm_by_id(self, vm_id): + vm = self._one.get_vm_by_id(vm_id) + return self.remove_vm(vm) + + def sync(self): + for vm in self._one.vms(): + self.add_vm(vm) diff --git a/onedns/clients/skydns.py b/onedns/clients/skydns.py index 328a8f3..ca40179 100644 --- a/onedns/clients/skydns.py +++ b/onedns/clients/skydns.py @@ -15,6 +15,9 @@ class SkyDNSClient(object): self._reverse_domain_parts.reverse() self._etcd = etcd.Client(**etcd_kwargs) + def _sanitize_name(self, name): + return RE_VALIDNAME.sub('', name).rstrip('.') + def _skydns_ns(self, parts): return '/'.join(['skydns'] + parts) @@ -27,10 +30,10 @@ class SkyDNSClient(object): def add_forward(self, hostname, ip): forward = self._get_forward_ns(hostname) - log.debug("forward path: {path}".format(path=forward)) + log.debug("adding forward: {path}".format(path=forward)) self._etcd.write(forward, json.dumps(dict(host=ip))) - def remove_forward(self, hostname, ip): + def remove_forward(self, hostname): forward = self._get_forward_ns(hostname) log.debug("removing forward: {path}".format(path=forward)) self._etcd.delete(forward) @@ -38,28 +41,20 @@ class SkyDNSClient(object): def add_reverse(self, ip, hostname): reverse = self._get_reverse_ns(ip) fqdn = '.'.join([hostname, self.domain]) - log.debug("reverse path: {path}".format(path=reverse)) + log.debug("adding reverse: {path}".format(path=reverse)) self._etcd.write(reverse, json.dumps(dict(host=fqdn))) - def remove_reverse(self, ip, hostname): + def remove_reverse(self, ip): reverse = self._get_reverse_ns(ip) log.debug("removing reverse: {path}".format(path=reverse)) self._etcd.delete(reverse) def add_host(self, hostname, ip): + hostname = self._sanitize_name(hostname) self.add_forward(hostname, ip) self.add_reverse(ip, hostname) def remove_host(self, hostname, ip): - self.remove_forward(hostname, ip) - self.remove_reverse(ip, hostname) - - def register(self, vm): - log.info("Registering VM: {vm}".format(vm=vm.name)) - hostname = RE_VALIDNAME.sub('', vm.name).rstrip('.') - primary_ip = vm.template.nics[0].ip - self.add_host(hostname, primary_ip) - for nic in vm.template.nics[1:]: - nicname = "{hostname}-{id}".format(hostname=hostname, - id=nic.nic_id) - self.add_host(nicname, nic.ip) + hostname = self._sanitize_name(hostname) + self.remove_forward(hostname) + self.remove_reverse(ip) diff --git a/onedns/monitor.py b/onedns/monitor.py index 46bb491..d2c7d54 100644 --- a/onedns/monitor.py +++ b/onedns/monitor.py @@ -1,24 +1,13 @@ import time -from onedns.clients import one -from onedns.clients import skydns +from onedns import api -class OneMonitor(object): - ''' - Reads events from OpenNebula and activates/deactivates VM domain names - ''' - - def __init__(self, domain, one_kwargs={}, etcd_kwargs={}): - self._one = one.OneClient(**one_kwargs) - self._skydns = skydns.SkyDNSClient(domain, etcd_kwargs=etcd_kwargs) - - def update(self): - for vm in self._one.vms(): - if hasattr(vm.template, 'nics'): - self._skydns.register(vm) - - def run(self, interval=10): +class OneMonitor(api.OneDNS): + """ + Daemon that syncs OpenNebula VMs with SkyDNS + """ + def run(self, interval=60): while True: - self.update() + self.sync() time.sleep(interval)