~hopem/charms/trusty/percona-cluster/fix-peerstore-passwd-lp1451890-stable-backport

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/database/mysql.py

  • Committer: Billy Olsen
  • Date: 2015-02-27 06:12:46 UTC
  • mfrom: (48.1.1 percona-cluster.next)
  • Revision ID: billy.olsen@canonical.com-20150227061246-f3q1g0bucvx2xxl3
[hopem, r=wolsen] sync charm-helpers fix for LP #1425999

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
    log,
22
22
    DEBUG,
23
23
    INFO,
 
24
    WARNING,
24
25
)
25
26
from charmhelpers.core.hookenv import config as config_get
26
27
from charmhelpers.fetch import (
220
221
        """Retrieve or generate mysql root password for service units."""
221
222
        return self.get_mysql_password(username=None, password=password)
222
223
 
 
224
    def normalize_address(self, hostname):
 
225
        """Ensure that address returned is an IP address (i.e. not fqdn)"""
 
226
        if config_get('prefer-ipv6'):
 
227
            # TODO: add support for ipv6 dns
 
228
            return hostname
 
229
 
 
230
        if hostname != unit_get('private-address'):
 
231
            try:
 
232
                return socket.gethostbyname(hostname)
 
233
            except Exception:
 
234
                # socket.gethostbyname doesn't support ipv6
 
235
                log("Failed to normalize hostname '%s'" % (hostname),
 
236
                    level=WARNING)
 
237
                return hostname
 
238
 
 
239
        # Otherwise assume localhost
 
240
        return '127.0.0.1'
 
241
 
223
242
    def get_allowed_units(self, database, username, relation_id=None):
224
243
        """Get list of units with access grants for database with username.
225
244
 
247
266
 
248
267
            if hosts:
249
268
                for host in hosts:
 
269
                    host = self.normalize_address(host)
250
270
                    if self.grant_exists(database, username, host):
251
271
                        log("Grant exists for host '%s' on db '%s'" %
252
272
                            (host, database), level=DEBUG)
262
282
 
263
283
    def configure_db(self, hostname, database, username, admin=False):
264
284
        """Configure access to database for username from hostname."""
265
 
        if config_get('prefer-ipv6'):
266
 
            remote_ip = hostname
267
 
        elif hostname != unit_get('private-address'):
268
 
            try:
269
 
                remote_ip = socket.gethostbyname(hostname)
270
 
            except Exception:
271
 
                # socket.gethostbyname doesn't support ipv6
272
 
                remote_ip = hostname
273
 
        else:
274
 
            remote_ip = '127.0.0.1'
275
 
 
276
285
        self.connect(password=self.get_mysql_root_password())
277
286
        if not self.database_exists(database):
278
287
            self.create_database(database)
279
288
 
 
289
        remote_ip = self.normalize_address(hostname)
280
290
        password = self.get_mysql_password(username)
281
291
        if not self.grant_exists(database, username, remote_ip):
282
292
            if not admin:
289
299
 
290
300
class PerconaClusterHelper(object):
291
301
 
292
 
    # Going for the biggest page size to avoid wasted bytes. InnoDB page size is
293
 
    # 16MB
 
302
    # Going for the biggest page size to avoid wasted bytes.
 
303
    # InnoDB page size is 16MB
 
304
 
294
305
    DEFAULT_PAGE_SIZE = 16 * 1024 * 1024
 
306
    DEFAULT_INNODB_BUFFER_FACTOR = 0.50
295
307
 
296
308
    def human_to_bytes(self, human):
297
309
        """Convert human readable configuration options to bytes."""
352
364
        if 'max-connections' in config:
353
365
            mysql_config['max_connections'] = config['max-connections']
354
366
 
355
 
        # Total memory available for dataset
356
 
        dataset_bytes = self.human_to_bytes(config['dataset-size'])
357
 
        mysql_config['dataset_bytes'] = dataset_bytes
358
 
 
359
 
        if 'query-cache-type' in config:
360
 
            # Query Cache Configuration
361
 
            mysql_config['query_cache_size'] = config['query-cache-size']
362
 
            if (config['query-cache-size'] == -1 and
363
 
                    config['query-cache-type'] in ['ON', 'DEMAND']):
364
 
                # Calculate the query cache size automatically
365
 
                qcache_bytes = (dataset_bytes * 0.20)
366
 
                qcache_bytes = int(qcache_bytes -
367
 
                                   (qcache_bytes % self.DEFAULT_PAGE_SIZE))
368
 
                mysql_config['query_cache_size'] = qcache_bytes
369
 
                dataset_bytes -= qcache_bytes
370
 
 
371
 
            # 5.5 allows the words, but not 5.1
372
 
            if config['query-cache-type'] == 'ON':
373
 
                mysql_config['query_cache_type'] = 1
374
 
            elif config['query-cache-type'] == 'DEMAND':
375
 
                mysql_config['query_cache_type'] = 2
376
 
            else:
377
 
                mysql_config['query_cache_type'] = 0
378
 
 
379
367
        # Set a sane default key_buffer size
380
368
        mysql_config['key_buffer'] = self.human_to_bytes('32M')
381
 
 
382
 
        if 'preferred-storage-engine' in config:
383
 
            # Storage engine configuration
384
 
            preferred_engines = config['preferred-storage-engine'].split(',')
385
 
            chunk_size = int(dataset_bytes / len(preferred_engines))
386
 
            mysql_config['innodb_flush_log_at_trx_commit'] = 1
387
 
            mysql_config['sync_binlog'] = 1
388
 
            if 'InnoDB' in preferred_engines:
389
 
                mysql_config['innodb_buffer_pool_size'] = chunk_size
390
 
                if config['tuning-level'] == 'fast':
391
 
                    mysql_config['innodb_flush_log_at_trx_commit'] = 2
392
 
            else:
393
 
                mysql_config['innodb_buffer_pool_size'] = 0
394
 
 
395
 
            mysql_config['default_storage_engine'] = preferred_engines[0]
396
 
            if 'MyISAM' in preferred_engines:
397
 
                mysql_config['key_buffer'] = chunk_size
398
 
 
399
 
            if config['tuning-level'] == 'fast':
400
 
                mysql_config['sync_binlog'] = 0
401
 
 
 
369
        total_memory = self.human_to_bytes(self.get_mem_total())
 
370
 
 
371
        log("Option 'dataset-size' has been deprecated, instead by default %d%% of system \
 
372
        available RAM will be used for innodb_buffer_pool_size allocation" %
 
373
            (self.DEFAULT_INNODB_BUFFER_FACTOR * 100), level="WARN")
 
374
 
 
375
        innodb_buffer_pool_size = config.get('innodb-buffer-pool-size', None)
 
376
 
 
377
        if innodb_buffer_pool_size:
 
378
            innodb_buffer_pool_size = self.human_to_bytes(
 
379
                innodb_buffer_pool_size)
 
380
 
 
381
            if innodb_buffer_pool_size > total_memory:
 
382
                log("innodb_buffer_pool_size; {} is greater than system available memory:{}".format(
 
383
                    innodb_buffer_pool_size,
 
384
                    total_memory), level='WARN')
 
385
        else:
 
386
            innodb_buffer_pool_size = int(
 
387
                total_memory * self.DEFAULT_INNODB_BUFFER_FACTOR)
 
388
 
 
389
        mysql_config['innodb_buffer_pool_size'] = innodb_buffer_pool_size
402
390
        return mysql_config