231 lines
8.2 KiB
Python
231 lines
8.2 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import re
|
|
|
|
import Logger
|
|
import Packager
|
|
from Component import (ComponentBase, RuntimeComponent,
|
|
UninstallComponent, InstallComponent)
|
|
from Util import (DB,
|
|
get_pkg_list, get_host_ip,
|
|
execute_template)
|
|
from Exceptions import (StartException, StopException,
|
|
StatusException, RestartException)
|
|
from Trace import (TraceWriter, TraceReader,
|
|
IN_TRACE)
|
|
from Shell import (mkdirslist, execute, deldir,
|
|
load_file, write_file)
|
|
|
|
LOG = Logger.getLogger("install.db")
|
|
TYPE = DB
|
|
MYSQL = 'mysql'
|
|
DB_ACTIONS = {
|
|
MYSQL: {
|
|
#hopefully these are distro independent, these should be since they are invoking system init scripts
|
|
'start': ["service", "mysql", 'start'],
|
|
'stop': ["service", 'mysql', "stop"],
|
|
'status': ["service", 'mysql', "status"],
|
|
'restart': ["service", 'mysql', "status"],
|
|
#
|
|
'create_db': ['mysql', '--user=%USER%', '--password=%PASSWORD%', '-e', 'CREATE DATABASE %DB%;'],
|
|
'drop_db': ['mysql', '--user=%USER%', '--password=%PASSWORD%', '-e', 'DROP DATABASE IF EXISTS %DB%;'],
|
|
'grant_all': [
|
|
"mysql",
|
|
"--user=%USER%",
|
|
"--password=%PASSWORD%",
|
|
"-e \"GRANT ALL PRIVILEGES ON *.* TO '%USER%'@'%' identified by '%PASSWORD%';\"",
|
|
],
|
|
#we could do this in python directly, but executing allows us to not have to sudo the whole program
|
|
'host_adjust': ['perl', '-p', '-i', '-e'] + ["'s/127.0.0.1/0.0.0.0/g'", '/etc/mysql/my.cnf'],
|
|
},
|
|
}
|
|
|
|
BASE_ERROR = 'Currently we do not know how to %s for database type [%s]'
|
|
|
|
|
|
class DBUninstaller(ComponentBase, UninstallComponent):
|
|
def __init__(self, *args, **kargs):
|
|
ComponentBase.__init__(self, TYPE, *args, **kargs)
|
|
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
|
|
self.runtime = DBRuntime(*args, **kargs)
|
|
|
|
def unconfigure(self):
|
|
#nothing to unconfigure, we are just a pkg
|
|
pass
|
|
|
|
def uninstall(self):
|
|
#clean out removeable packages
|
|
pkgsfull = self.tracereader.packages_installed()
|
|
if(len(pkgsfull)):
|
|
LOG.info("Potentially removing %s packages" % (len(pkgsfull)))
|
|
self.packager.remove_batch(pkgsfull)
|
|
dirsmade = self.tracereader.dirs_made()
|
|
if(len(dirsmade)):
|
|
LOG.info("Removing %s created directories" % (len(dirsmade)))
|
|
for dirname in dirsmade:
|
|
deldir(dirname)
|
|
LOG.info("Removed %s" % (dirname))
|
|
|
|
|
|
class DBInstaller(ComponentBase, InstallComponent):
|
|
def __init__(self, *args, **kargs):
|
|
ComponentBase.__init__(self, TYPE, *args, **kargs)
|
|
self.tracewriter = TraceWriter(self.tracedir, IN_TRACE)
|
|
self.runtime = DBRuntime(*args, **kargs)
|
|
|
|
def download(self):
|
|
#nothing to download, we are just a pkg
|
|
pass
|
|
|
|
def configure(self):
|
|
#nothing to configure, we are just a pkg
|
|
pass
|
|
|
|
def _get_install_params(self):
|
|
#this dictionary will be used for parameter replacement
|
|
#in pre-install and post-install sections
|
|
out = dict()
|
|
out['PASSWORD'] = self.cfg.getpw("passwords", "sql")
|
|
out['BOOT_START'] = str(True).lower()
|
|
out['USER'] = self.cfg.get("db", "sql_user")
|
|
hostip = get_host_ip(self.cfg)
|
|
out['SERVICE_HOST'] = hostip
|
|
out['HOST_IP'] = hostip
|
|
return out
|
|
|
|
def _do_install(self, pkgs):
|
|
mp = self._get_install_params()
|
|
self.packager.pre_install(pkgs, mp)
|
|
self.packager.install_batch(pkgs)
|
|
self.packager.post_install(pkgs, mp)
|
|
#
|
|
#extra actions to ensure we are granted access
|
|
#
|
|
dbtype = self.cfg.get("db", "type")
|
|
dbactions = DB_ACTIONS.get(dbtype)
|
|
if(dbactions and dbactions.get('grant_all')):
|
|
#update the DB to give user 'USER'@'%' full control of the all databases:
|
|
grant_cmd = dbactions.get('grant_all')
|
|
params = mp
|
|
cmds = list()
|
|
cmds.append({
|
|
'cmd': grant_cmd,
|
|
'run_as_root': False,
|
|
})
|
|
#shell seems to be needed here
|
|
#since python escapes this to much...
|
|
execute_template(*cmds, params=params, shell=True)
|
|
#
|
|
#special mysql actions
|
|
if(dbactions and dbtype == MYSQL):
|
|
cmd = dbactions.get('host_adjust')
|
|
if(cmd):
|
|
execute(*cmd, run_as_root=True, shell=True)
|
|
|
|
def install(self):
|
|
#just install the pkgs
|
|
pkgs = get_pkg_list(self.distro, TYPE)
|
|
pkgnames = sorted(pkgs.keys())
|
|
LOG.info("Installing packages %s" % (", ".join(pkgnames)))
|
|
self._do_install(pkgs)
|
|
#add trace used to remove the pkgs
|
|
for name in pkgnames:
|
|
self.tracewriter.package_install(name, pkgs.get(name))
|
|
#restart it to make sure all good
|
|
self.runtime.restart()
|
|
return self.tracedir
|
|
|
|
|
|
class DBRuntime(ComponentBase, RuntimeComponent):
|
|
def __init__(self, *args, **kargs):
|
|
ComponentBase.__init__(self, TYPE, *args, **kargs)
|
|
self.tracereader = TraceReader(self.tracedir, IN_TRACE)
|
|
|
|
def _gettypeactions(self, act, exception_cls):
|
|
pkgsinstalled = self.tracereader.packages_installed()
|
|
if(len(pkgsinstalled) == 0):
|
|
msg = "Can not %s %s since it was not installed" % (act, TYPE)
|
|
raise exception_cls(msg)
|
|
#figure out how to do it
|
|
dbtype = self.cfg.get("db", "type")
|
|
typeactions = DB_ACTIONS.get(dbtype)
|
|
if(typeactions == None or not typeactions.get(act)):
|
|
msg = BASE_ERROR % (act, dbtype)
|
|
raise NotImplementedError(msg)
|
|
return typeactions.get(act)
|
|
|
|
def start(self):
|
|
if(self.status().find('start') == -1):
|
|
startcmd = self._gettypeactions('start', StartException)
|
|
execute(*startcmd, run_as_root=True)
|
|
return None
|
|
|
|
def stop(self):
|
|
if(self.status().find('stop') == -1):
|
|
stopcmd = self._gettypeactions('stop', StopException)
|
|
execute(*stopcmd, run_as_root=True)
|
|
return None
|
|
|
|
def restart(self):
|
|
restartcmd = self._gettypeactions('restart', RestartException)
|
|
execute(*restartcmd, run_as_root=True)
|
|
return None
|
|
|
|
def status(self):
|
|
statuscmd = self._gettypeactions('status', StatusException)
|
|
(sysout, stderr) = execute(*statuscmd, run_as_root=True)
|
|
return sysout.strip()
|
|
|
|
|
|
def drop_db(cfg, dbname):
|
|
dbtype = cfg.get("db", "type")
|
|
dbactions = DB_ACTIONS.get(dbtype)
|
|
if(dbactions and dbactions.get('drop_db')):
|
|
dropcmd = dbactions.get('drop_db')
|
|
params = dict()
|
|
params['PASSWORD'] = cfg.getpw("passwords", "sql")
|
|
params['USER'] = cfg.get("db", "sql_user")
|
|
params['DB'] = dbname
|
|
cmds = list()
|
|
cmds.append({
|
|
'cmd': dropcmd,
|
|
'run_as_root': False,
|
|
})
|
|
execute_template(*cmds, params=params)
|
|
else:
|
|
msg = BASE_ERROR % ('drop', dbtype)
|
|
raise NotImplementedError(msg)
|
|
|
|
|
|
def create_db(cfg, dbname):
|
|
dbtype = cfg.get("db", "type")
|
|
dbactions = DB_ACTIONS.get(dbtype)
|
|
if(dbactions and dbactions.get('create_db')):
|
|
createcmd = dbactions.get('create_db')
|
|
params = dict()
|
|
params['PASSWORD'] = cfg.getpw("passwords", "sql")
|
|
params['USER'] = cfg.get("db", "sql_user")
|
|
params['DB'] = dbname
|
|
cmds = list()
|
|
cmds.append({
|
|
'cmd': createcmd,
|
|
'run_as_root': False,
|
|
})
|
|
execute_template(*cmds, params=params)
|
|
else:
|
|
msg = BASE_ERROR % ('create', dbtype)
|
|
raise NotImplementedError(msg)
|