github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/repository/xenial/mysql/hooks/shared_db_relations.py (about)

     1  #!/usr/bin/python
     2  #
     3  # Create relations between a shared database to many peers.
     4  # Join does nothing.   Peer requests access to $DATABASE from $REMOTE_HOST.
     5  # It's up to the hooks to ensure database exists, peer has access and
     6  # clean up grants after a broken/departed peer (TODO)
     7  #
     8  # Author: Adam Gandelman <adam.gandelman@canonical.com>
     9  
    10  
    11  from common import (
    12      database_exists,
    13      create_database,
    14      grant_exists,
    15      create_grant
    16      )
    17  import subprocess
    18  import json
    19  import socket
    20  import os
    21  import lib.utils as utils
    22  import lib.cluster_utils as cluster
    23  
    24  LEADER_RES = 'res_mysql_vip'
    25  
    26  
    27  def pwgen():
    28      return str(subprocess.check_output(['pwgen', '-s', '16'])).strip()
    29  
    30  
    31  def relation_get():
    32      return json.loads(subprocess.check_output(
    33                          ['relation-get',
    34                           '--format',
    35                           'json']
    36                          )
    37                        )
    38  
    39  
    40  def shared_db_changed():
    41  
    42      def configure_db(hostname,
    43                       database,
    44                       username):
    45          passwd_file = "/var/lib/mysql/mysql-{}.passwd"\
    46                          .format(username)
    47          if hostname != local_hostname:
    48              remote_ip = socket.gethostbyname(hostname)
    49          else:
    50              remote_ip = '127.0.0.1'
    51  
    52          if not os.path.exists(passwd_file):
    53              password = pwgen()
    54              with open(passwd_file, 'w') as pfile:
    55                  pfile.write(password)
    56          else:
    57              with open(passwd_file) as pfile:
    58                  password = pfile.read().strip()
    59  
    60          if not database_exists(database):
    61              create_database(database)
    62          if not grant_exists(database,
    63                              username,
    64                              remote_ip):
    65              create_grant(database,
    66                           username,
    67                           remote_ip, password)
    68          return password
    69  
    70      if not cluster.eligible_leader(LEADER_RES):
    71          utils.juju_log('INFO',
    72                         'MySQL service is peered, bailing shared-db relation'
    73                         ' as this service unit is not the leader')
    74          return
    75  
    76      settings = relation_get()
    77      local_hostname = utils.unit_get('private-address')
    78      singleset = set([
    79          'database',
    80          'username',
    81          'hostname'
    82          ])
    83  
    84      if singleset.issubset(settings):
    85          # Process a single database configuration
    86          password = configure_db(settings['hostname'],
    87                                  settings['database'],
    88                                  settings['username'])
    89          if not cluster.is_clustered():
    90              utils.relation_set(db_host=local_hostname,
    91                                 password=password)
    92          else:
    93              utils.relation_set(db_host=utils.config_get("vip"),
    94                                 password=password)
    95  
    96      else:
    97          # Process multiple database setup requests.
    98          # from incoming relation data:
    99          #  nova_database=xxx nova_username=xxx nova_hostname=xxx
   100          #  quantum_database=xxx quantum_username=xxx quantum_hostname=xxx
   101          # create
   102          #{
   103          #   "nova": {
   104          #        "username": xxx,
   105          #        "database": xxx,
   106          #        "hostname": xxx
   107          #    },
   108          #    "quantum": {
   109          #        "username": xxx,
   110          #        "database": xxx,
   111          #        "hostname": xxx
   112          #    }
   113          #}
   114          #
   115          databases = {}
   116          for k, v in settings.iteritems():
   117              db = k.split('_')[0]
   118              x = '_'.join(k.split('_')[1:])
   119              if db not in databases:
   120                  databases[db] = {}
   121              databases[db][x] = v
   122          return_data = {}
   123          for db in databases:
   124              if singleset.issubset(databases[db]):
   125                  return_data['_'.join([db, 'password'])] = \
   126                      configure_db(databases[db]['hostname'],
   127                                   databases[db]['database'],
   128                                   databases[db]['username'])
   129          if len(return_data) > 0:
   130              utils.relation_set(**return_data)
   131          if not cluster.is_clustered():
   132              utils.relation_set(db_host=local_hostname)
   133          else:
   134              utils.relation_set(db_host=utils.config_get("vip"))
   135  
   136  hooks = {
   137      "shared-db-relation-changed": shared_db_changed
   138      }
   139  
   140  utils.do_hooks(hooks)