Skip to content
Permalink
Browse files

Lint cleanup.

Handle other API changes (Diff, streaming)
Add flush flag.


git-svn-id: http://google-mysql-tools.googlecode.com/svn/trunk@356 960bbd1a-3921-0410-93bb-a35bc832efea
  • Loading branch information...
flamingcow@google.com
flamingcow@google.com committed Feb 11, 2013
1 parent 25fee8a commit d4ff75549c1ea57f1781fabc9a448bb398452e96
Showing with 46 additions and 36 deletions.
  1. +16 −16 permissions_lib/define.py
  2. +29 −17 permissions_lib/use.py
  3. +1 −3 permissions_lib/utils.py
@@ -1,6 +1,4 @@
#!/usr/bin/python2.6
#
# Copyright 2011 Google Inc.
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -49,19 +47,17 @@
import functools

try:
from pylib import db
except ImportError:
from ..pylib import db
except (ValueError, ImportError):
from pylib import db

import utils


# Dictionary of setname -> Set.
# This variable is used during push/publish/dump operations; it should not
# appear in a permissions file.
SETS = {}
"""Dictionary of setname -> Set.
This variable is used during push/publish/dump operations; it should not appear
in a permissions file.
"""


class Error(Exception):
@@ -108,6 +104,10 @@ class DecryptionFailed(Error):
"""Raised when decryption fails, due to invalid key or data."""


class NoAllowedHosts(Error):
"""Account has no allowed hosts but is exported."""


_TOTAL_PRIVS = 28
_PRIVS = [2**x for x in xrange(_TOTAL_PRIVS)]
(
@@ -148,7 +148,7 @@ class DecryptionFailed(Error):

# Using this in place of a database name causes substitution for the "main
# database", e.g. "ads54".
DEFAULT = ('literal', 'DATABASE()')
DEFAULT = db.Literal('DATABASE()')
"""Refers to the (sharded) database name.
This is used to indicate that a permission should be set on the database
@@ -522,13 +522,9 @@ def GetAllEntities(dbh, fixed_values={}):
if not dbh:
raise NeedDBAccess('Need to retrieve table list from %s' %
str(fixed_values['Db']))
if fixed_values['Db'] == DEFAULT:
dbname = 'DATABASE()'
else:
dbname = "'%s'" % fixed_values['Db'].replace("'", "''")
result = dbh.CachedExecuteOrDie(
'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE'
' TABLE_SCHEMA=%s' % dbname)
' TABLE_SCHEMA=%(Db)s', fixed_values)
return [row['TABLE_NAME'] for row in result]


@@ -960,6 +956,10 @@ def GetTables(self, dbh=None):
'Password': self._password_hash,
}

if not self._allowed_hosts:
raise NoAllowedHosts('Account %s has no allowed hosts',
self.GetUsername())

for host in sorted(self._allowed_hosts):
fixed_values['Host'] = host
self._perm.PopulateTables(ret, fixed_values)
@@ -1,6 +1,4 @@
#!/usr/bin/python2.6
#
# Copyright 2011 Google Inc.
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -30,9 +28,9 @@
import threading

try:
from pylib import db
except ImportError:
from ..pylib import db
except (ImportError, ValueError):
from pylib import db

import define
import utils
@@ -62,7 +60,7 @@ class ValidationFailure(Error):
}


def Copy(dbh, set_name):
def Copy(dbh, set_name, flush=True):
"""Copies the permission set from the admin.* tables to the mysql.* tables.
Tables copied are::
@@ -79,6 +77,7 @@ def Copy(dbh, set_name):
Args:
dbh: A connected database handle (pylib.db).
set_name: The permissions set name, e.g. "primary", "secondary".
flush: If True, activate newly-copied permissions.
"""
with db.Lock(dbh, 'permissions copy'):
with db.Transaction(dbh) as trx:
@@ -95,7 +94,7 @@ def Copy(dbh, set_name):
' WHERE MysqlPermissionSetId=%(set_id)s', {'set_id': set_id})
assert result[0]['c'], 'Permissions copy with blank user table'

for dest, source in COPY_MAP.iteritems():
for dest, source in sorted(COPY_MAP.iteritems()):
result = dbh.ExecuteOrDie('DESC %s' % dest)
columns = [row['Field'] for row in result]
columns_str = ','.join(columns)
@@ -110,7 +109,8 @@ def Copy(dbh, set_name):
' LastPushed=FROM_UNIXTIME(%(last_pushed)s)',
{'set_id': set_id,
'last_pushed': last_updated})
dbh.ExecuteOrDie('FLUSH LOCAL PRIVILEGES')
if flush:
dbh.ExecuteOrDie('FLUSH LOCAL PRIVILEGES')


def GetPermissionSetId(dbh, set_name):
@@ -156,7 +156,15 @@ def __init__(self, permissions_contents=None, private_keyfile=None):
else:
self._decryption_key = None

def Parse(self, permissions_contents):
def Parse(self, permissions_contents, define_overrides=None):
"""Parses permissions definitions.
Args:
permissions_contents: string containing Python code that defines
permissions, using the framework provided in define.py.
define_overrides: An optional dict whose values override the normal
execution environment from define.py.
"""
code = compile(permissions_contents, 'permissions contents', 'exec')

# TODO(flamingcow): There is a race when using two instances of
@@ -166,12 +174,15 @@ def Parse(self, permissions_contents):
# This is self.globals as a backwards-compat hack, because there are some
# users of this class that want to get at things from the permissions file
# other than SETS.
self.globals = define.__dict__
# TODO(unbrice): Remove the hack, it seems there is only one user anyway.
self.globals = define.__dict__.copy()
if define_overrides:
self.globals.update(define_overrides)
# Reset define's global state. This makes multiple instantiations of
# PermissionsFile work.
self.globals['SETS'].clear()
self.globals['SETS'].update(self._sets)
exec(code, self.globals)
exec code in self.globals
self._sets = self.globals['SETS'].copy()

def GetSetTables(self, dbh, set_name):
@@ -192,8 +203,7 @@ def _GetTableDiffSQL(dbh, old_table, new_table, name):
for row in old_table.GetRows():
if row[db_index] == 'DATABASE()':
row[db_index] = define.DEFAULT
old_rows = old_table - new_table
new_rows = new_table - old_table
new_rows, old_rows = new_table.Diff(old_table)
args = {}
args['db'], args['table'] = name.split('.', 1)
query = """
@@ -264,7 +274,8 @@ def _GetFullTableSQL(table, name, delete_where):
"""Generate SQL to delete and rebuild table contents."""
if delete_where:
yield 'DELETE FROM %s WHERE %s;' % (name, delete_where)
for sql in table.GetInsertSQLList(name, max_size=2**20):
for sql in table.GetInsertSQLList(name, max_size=2**20,
on_duplicate_key_update=True):
yield sql

@classmethod
@@ -280,7 +291,7 @@ def GetSQL(cls, dbh, tables, delete_where=None, map=None, incremental=True):
map: mapping dict from keys in tables to database table names
"""
sql = []
for name, table in tables.iteritems():
for name, table in sorted(tables.iteritems()):
if map:
name = map[name]
if incremental and dbh:
@@ -375,6 +386,7 @@ def Publish(self, dbh, set_name, dest_set_name, push_duration=1800,
used by copiers to decide when to copy.
incremental: Whether the publish should attempt to make minimal changes to
the destination tables, rather than just wiping them.
extra_where: An additional where clause, see below.
"""
set_id = GetPermissionSetId(dbh, dest_set_name)
tables = self.GetSetTables(dbh, set_name)
@@ -420,8 +432,8 @@ def Test(self, dbh, incremental=True):
incremental: Whether the publish should attempt to make minimal changes to
the destination tables, rather than just wiping them.
"""
for set in self._sets:
tables = self.GetSetTables(dbh, set)
for permissions_set in self._sets:
tables = self.GetSetTables(dbh, permissions_set)
for _ in self.GetSQL(dbh, tables, '1', self.PUSH_MAP,
incremental=incremental):
pass
@@ -1,6 +1,4 @@
#!/usr/bin/python2.6
#
# Copyright 2011 Google Inc.
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

0 comments on commit d4ff755

Please sign in to comment.
You can’t perform that action at this time.