Last active
August 29, 2015 13:57
-
-
Save nitecoder/9536584 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from starcluster.clustersetup import ClusterSetup | |
from starcluster.logger import log | |
import subprocess | |
from starcluster import threadpool | |
from boto.route53.connection import Route53Connection | |
from boto.route53.connection import ResourceRecordSets | |
class Route53Plugin(ClusterSetup): | |
def __init__(self, | |
zone_name, | |
master_name_template, | |
node_name_template, | |
dry_run): | |
"""Parameters: | |
zone_name - name of the Route53 zone in which to register A records | |
master_name_template - register name for master based on this template | |
node_name_template - register name for nodes based on this template | |
dry_run - don't commit changes if True | |
templates can use | |
{alias} to substitute for node.alias | |
{zone} to substitute for zone.name | |
""" | |
self.zone_name = zone_name | |
self.master_name_template = master_name_template | |
self.node_name_template = node_name_template | |
self.dry_run = dry_run | |
self.conn = Route53Connection() | |
log.info("route53_plugin: *********** init: DRY_RUN=%s" % dry_run) | |
def run (self, nodes, master, user, user_shell, volumes): | |
log.debug("route53_plugin: *********** run: %s", nodes) | |
comment="Starcluster route53_plugin run for %s" % [n.alias for n in nodes] | |
self._registerNodes(nodes, comment) | |
# def on_restart(self, nodes, master, user, user_shell, volumes): | |
# log.debug("route53_plugin: *********** run: %s", nodes) | |
# comment="Starcluster route53_plugin run for %s" % [n.alias for n in nodes] | |
# _registerNodes(nodes, comment) | |
def on_add_node(self, node, nodes, master, user, user_shell, volumes): | |
log.debug("route53_plugin: *********** add_node: %s", node) | |
comment="Starcluster route53_plugin add_node %s" % node.alias | |
self._registerNodes([node], comment) | |
def on_remove_node(self, node, nodes, master, user, user_shell, volumes): | |
log.debug("route53_plugin: *********** remove_node: %s", node) | |
comment="Starcluster route53_plugin remove_node %s" % node.alias | |
self._unregisterNodes([node], comment) | |
def on_shutdown(self, nodes, master, user, user_shell, volumes): | |
log.debug("route53_plugin: *********** shutdown: %s", nodes) | |
comment="Starcluster route53_plugin shutdown %s" % [n.alias for n in nodes] | |
self._unregisterNodes(nodes, comment) | |
def _registerNodes(self, nodes, comment): | |
changeSet = self._startChangeSet(comment) | |
if changeSet == None: | |
log.error("route53_plugin: *** unable to create change set") | |
return | |
for node in nodes: | |
log.debug("route53_plugin: checking node %s (is_master %s)", node, node.is_master()) | |
if not node.is_master() and self.master_name_template: | |
self._registerNode(changeSet, node, self.master_name_template) | |
elif self.node_name_template: | |
self._registerNode(changeSet, node, self.node_name_template) | |
self._commitChangeSet(changeSet) | |
def _unregisterNodes(self, nodes, comment): | |
changeSet = self._startChangeSet(comment) | |
if changeSet == None: | |
log.error("route53_plugin: *** unable to create change set") | |
return | |
for node in nodes: | |
log.debug("route53_plugin: checking node %s (is_master %s)", node, node.is_master()) | |
if not node.is_master() and self.master_name_template: | |
self._unregisterNode(changeSet, node) | |
elif self.node_name_template: | |
self._unregisterNode(changeSet, node) | |
self._commitChangeSet(changeSet) | |
def _startChangeSet(self, comment=None): | |
zone = self.conn.get_zone(self.zone_name) | |
if not zone: | |
log.error("route53_plugin: *** No zone %s, please create", self.zone_name) | |
return None | |
log.debug("route53_plugin: *** creating change set for zone %s (%s)", zone, comment) | |
return ResourceRecordSets(self.conn, zone.id, comment=comment) | |
def _commitChangeSet(self, changeSet): | |
log.info("chef_plugin: *** Submitting to route53 %s", changeSet) | |
if not changeSet.changes: | |
log.debug("chef_plugin: empty change set - nothing to do") | |
return | |
if self.dry_run: | |
log.warn("chef_plugin: DRY-RUN ONLY - not sending to route53") | |
return | |
return changeSet.commit() | |
# TODO: consider waiting for request to be INSYNC | |
def _unregisterNode(self, changeSet, node): | |
hostname = node.tags.get('hostname', None) | |
if not hostname: | |
log.info("route53_plugin: *** not hostname tag, nothing to unregister for %s", node) | |
return | |
return self._unregisterHostName(changeSet, hostname) | |
def _registerNode(self, changeSet, node, name_template): | |
addr = node.ip_address #node.addr | |
if not addr: | |
addr = node.private_ip_address | |
if not addr: | |
log.error("route53_plugin: *** unable to obtain address for node %s", node) | |
return | |
name = name_template.format( | |
alias=node.alias, | |
zone=self.zone_name | |
) | |
if not name: | |
log.error("route53_plugin: *** unable to obtain the name for node %s template %s", node, node_template) | |
return | |
node.add_tag('hostname', name) | |
return self._registerHostName(changeSet, name, addr) | |
def _unregisterHostName(self, changeSet, name): | |
zone = self.conn.get_zone(self.zone_name) | |
r = zone.get_a(name) | |
if not r: | |
log.warn("route53_plugin: *** no record found for name %s - nothing to unregister", name) | |
return | |
req = changeSet.add_change_record('DELETE', r) | |
#log.info("route53_plugin: *** Deleting A record %s for %s", r, name) | |
#zone.delete_a(name) | |
def _registerHostName(self, changeSet, name, addr): | |
req = changeSet.add_change(action='UPSERT', name=name, type='A', ttl=300) | |
req.add_value(addr) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a plugin for integrating Starcluster with route53. It will publish DNS A entries for the master and all nodes that are created by starcluster. If the node with the same name is started again with another IP, it will update the DNS entry.