class Controller(object): def __init__(self, unit=None, group_rules=None): state_path = os.path.join(os.environ.get("CHARM_DIR", ""), "rds.state") self._state = KVFile(state_path) self.unit = unit or Unit() self._group_rules = group_rules or () def get_region(self): return self.unit.ec2metadata['availability-zone'][:-1] def get_rds(self, config): return rds.connect_to_region(self.get_region()) def get_ec2(self, config): return rds.connect_to_region(self.get_region()) def get_db(self, config, instance): if 'mysql' in config['engine'].lower(): db = MySQL(config) if not self._state.get('mysql.client'): db.install_driver() self._state.set('mysql.client', True) return db def get_svc_dbname(self): return self.get_db_identifier()[:16].replace('-', '_') def get_db_identifier(self): service = os.environ["JUJU_REMOTE_UNIT"].split("/")[0] rel_id = os.environ["JUJU_RELATION_ID"].split(":")[-1] return "-".join([ service, rel_id, os.environ["JUJU_ENV_UUID"]]) def wait_for_db_instance(self, rds, instance_id): # Don't wait more than 10m print "test: waiting for db instance", instance_id, t = time.time() seen = set() while True: time.sleep(3) sys.stdout.write(".") try: dbs = rds.get_all_dbinstances(instance_id) except boto.exception.EC2ResponseError, e: if e.error_code == "InvalidInstanceId.NotFound": continue db = dbs.pop() if db.status == "available": print "\ntest: db %s available in %s" % ( instance_id, time.time() - t) return db elif db.status not in seen: print "\n db status", db.status, (time.time() - t), seen.add(db.status) if time.time() - t > 15 * 60: raise RuntimeError( "Database not provisioned within threshold %s" % ( instance_id))
class Controller(BaseController): def __init__(self, unit=None): self.unit = unit or Unit() self._elb = None self._ec2 = None self._config = None state_path = os.path.join(os.environ.get("CHARM_DIR", ""), "elb.state") self._state = KVFile(state_path) def get_zones(self): """ Get all the zones currently in use by backend instances """ zones = [] for k, v in self._state.get_all().items(): zones.append(v['zone']) return zones def get_elb(self): """ Get the charm elb abstraction. """ if self._elb: return self._elb data = self.get_config() self._elb = ELB( data['access-key-id'], data['secret-access-key'], self.get_region(), self.unit.get_service_identifier()) return self._elb def get_instance(self): """ Get the remote instance id and zone the hook is currently executing for. Also saves the information for future use. """ data = self.unit.relation_get() port = data.get('port') address = data.get('hostname') if not port or not address: self.unit.log('Peer address not set, waiting for handshake') raise RetryLater() ec2 = self.get_ec2() instance = self.unit.get_instance(ec2) return instance.id, instance.placement def on_changed(self): """Called when a unit changes it settings or comes online. """ lb = self.get_elb() instance_id, zone = self.get_instance() if instance_id is None: return if lb.exists(): print "added %s to elb %s" % (instance_id, lb.elb_name) lb.add(instance_id, zone) else: print "creating elb %s" % (lb.elb_name) lb.create([zone]) lb.add(instance_id, zone) def on_depart(self): """Called when a unit is no longer available. """ data = self._state.get(self.unit.remote_unit) if data is None: print "could not find remote unit %s" % self.unit.remote_unit return instance_id = data['instance-id'] lb = self.get_elb() if lb.exists(): print "removed %s from elb %s" % (instance_id, lb.elb_name) lb.remove(instance_id) self._state.remove(self.unit.remote_unit) lb.sync(self.get_zones()) def on_broken(self): """Called when the relationship is broken. """ lb = self.get_elb() if lb.exists(): print "removed elb %s" % (lb.elb_name) lb.destroy() def on_config_changed(self): lb = self.get_elb() print lb