From 03bf1c8d3a1c987582bc65d2e8df0f3d258f8843 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Sat, 11 Oct 2014 13:18:45 -0400 Subject: [PATCH] Added server management library. The PKISubsystem and PKIInstance classes used by the upgrade framework have been converted into a server management library. They have been enhanced to provide the following functionalities: * starting and stopping instances * enabling and disabling subsystems * checking instance and subsystem statuses The validate() invocation has been moved out of the constructors into the upgrade framework such that these objects can be created to represent subsystems and instances that do not exist yet. https://fedorahosted.org/pki/ticket/1183 --- base/common/python/pki/__init__.py | 6 +- base/server/python/pki/server/__init__.py | 142 ++++++++++++++++++++++++++---- base/server/python/pki/server/upgrade.py | 29 +++--- 3 files changed, 146 insertions(+), 31 deletions(-) diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py index 62d87a01c454878d5d0c1dc14b5f5e143326b4d8..01ac2639392c40c799972f50bd78c7023f7187f1 100644 --- a/base/common/python/pki/__init__.py +++ b/base/common/python/pki/__init__.py @@ -27,10 +27,10 @@ import re import requests -CONF_DIR = '/etc/pki' +CONF_DIR = '/etc/pki' SHARE_DIR = '/usr/share/pki' -BASE_DIR = '/var/lib' -LOG_DIR = '/var/log/pki' +BASE_DIR = '/var/lib' +LOG_DIR = '/var/log/pki' PACKAGE_VERSION = SHARE_DIR + '/VERSION' CERT_HEADER = "-----BEGIN CERTIFICATE-----" diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py index 3eb6b5f97b0c22b2ff95f8f5e73ae3e09d89b693..3c471071fc023903bb7c7a4e7b5175e665800bbb 100644 --- a/base/server/python/pki/server/__init__.py +++ b/base/server/python/pki/server/__init__.py @@ -19,41 +19,61 @@ # All rights reserved. # -import re +from lxml import etree +import grp import os +import pwd +import re +import subprocess import pki INSTANCE_BASE_DIR = '/var/lib/pki' -REGISTRY_DIR = '/etc/sysconfig/pki' -SUBSYSTEM_TYPES = ['ca', 'kra', 'ocsp', 'tks', 'tps'] +REGISTRY_DIR = '/etc/sysconfig/pki' +SUBSYSTEM_TYPES = ['ca', 'kra', 'ocsp', 'tks', 'tps'] class PKISubsystem(object): def __init__(self, instance, subsystem_name): + self.instance = instance self.name = subsystem_name self.type = instance.type + if self.type >= 10: - self.conf_dir = os.path.join( - INSTANCE_BASE_DIR, - instance.name, 'conf', subsystem_name) - self.base_dir = os.path.join( - INSTANCE_BASE_DIR, - instance.name, subsystem_name) + self.base_dir = os.path.join(self.instance.base_dir, self.name) + self.conf_dir = os.path.join(self.base_dir, 'conf') else: - self.conf_dir = os.path.join(pki.BASE_DIR, instance.name, 'conf') - self.base_dir = os.path.join(pki.BASE_DIR, instance.name) + self.base_dir = instance.base_dir + self.conf_dir = os.path.join(self.base_dir, 'conf') - self.validate() + self.context_xml_template = os.path.join( + pki.SHARE_DIR, self.name, 'conf', 'Catalina', 'localhost', self.name + '.xml') + + self.context_xml = os.path.join( + instance.conf_dir, 'Catalina', 'localhost', self.name + '.xml') + + self.doc_base = os.path.join(self.base_dir, 'webapps', self.name) + + def is_valid(self): + return os.path.exists(self.conf_dir) def validate(self): - if not os.path.exists(self.conf_dir): + if not self.is_valid(): raise pki.PKIException( 'Invalid subsystem: ' + self.__repr__(), None, self.instance) + def is_enabled(self): + return self.instance.is_deployed(self.name) + + def enable(self): + self.instance.deploy(self.name, self.context_xml_template, self.doc_base) + + def disable(self): + self.instance.undeploy(self.name) + def __repr__(self): return str(self.instance) + '/' + self.name @@ -61,22 +81,110 @@ class PKISubsystem(object): class PKIInstance(object): def __init__(self, name, instanceType=10): + self.name = name self.type = instanceType + if self.type >= 10: - self.conf_dir = os.path.join(INSTANCE_BASE_DIR, name, 'conf') self.base_dir = os.path.join(INSTANCE_BASE_DIR, name) + self.conf_dir = os.path.join(self.base_dir, 'conf') else: - self.conf_dir = os.path.join(pki.BASE_DIR, name, 'conf') self.base_dir = os.path.join(pki.BASE_DIR, name) + self.conf_dir = os.path.join(self.base_dir, 'conf') - self.validate() + self.registry_file = os.path.join( + pki.server.REGISTRY_DIR, 'tomcat', self.name, self.name) + + self.service_name = 'pki-tomcatd@%s.service' % self.name + + self.user = None + self.group = None + + def is_valid(self): + return os.path.exists(self.conf_dir) def validate(self): - if not os.path.exists(self.conf_dir): + if not self.is_valid(): raise pki.PKIException( 'Invalid instance: ' + self.__repr__(), None) + def start(self): + subprocess.check_call(['systemctl', 'start', self.service_name]) + + def stop(self): + subprocess.check_call(['systemctl', 'stop', self.service_name]) + + def is_active(self): + rc = subprocess.call(['systemctl', '--quiet', 'is-active', self.service_name]) + return rc == 0 + + def load(self): + with open(self.registry_file, 'r') as registry: + lines = registry.readlines() + + for line in lines: + + m = re.search('^PKI_USER=(.*)$', line) + if m: + self.user = m.group(1) + + m = re.search('^PKI_GROUP=(.*)$', line) + if m: + self.group = m.group(1) + + def is_deployed(self, webapp_name): + context_xml = os.path.join( + self.conf_dir, 'Catalina', 'localhost', webapp_name + '.xml') + return os.path.exists(context_xml) + + def deploy(self, webapp_name, descriptor, doc_base=None): + """ + Deploy a web application into a Tomcat instance. + + This method will copy the specified deployment descriptor into + /conf/Catalina/localhost/.xml and point the docBase + to the specified location. The web application will become available + under "/" URL path. + + See also: http://tomcat.apache.org/tomcat-7.0-doc/config/context.html + + :param webapp_name: Web application name. + :type webapp_name: str + :param descriptor: Path to deployment descriptor (context.xml). + :type descriptor: str + :param doc_base: Path to web application content. + :type doc_base: str + """ + + context_xml = os.path.join( + self.conf_dir, 'Catalina', 'localhost', webapp_name + '.xml') + + # read deployment descriptor + parser = etree.XMLParser(remove_blank_text=True) + document = etree.parse(descriptor, parser) + + if doc_base: + # customize docBase + context = document.getroot() + context.set('docBase', doc_base) + + # write deployment descriptor + with open(context_xml, 'w') as f: + f.write(etree.tostring(document, pretty_print=True)) + + # find uid and gid + uid = pwd.getpwnam(self.user).pw_uid + gid = grp.getgrnam(self.group).gr_gid + + # set deployment descriptor ownership and permission + os.chown(context_xml, uid, gid) + os.chmod(context_xml, 00660) + + def undeploy(self, webapp_name): + context_xml = os.path.join( + self.conf_dir, 'Catalina', 'localhost', webapp_name + '.xml') + os.remove(context_xml) + def __repr__(self): if self.type == 9: return "Dogtag 9 " + self.name diff --git a/base/server/python/pki/server/upgrade.py b/base/server/python/pki/server/upgrade.py index 4cae695d1fa1dd90d959fe17f219b7040863f383..db3d968aa85e977838ebd8a13be798dc373ab172 100644 --- a/base/server/python/pki/server/upgrade.py +++ b/base/server/python/pki/server/upgrade.py @@ -182,8 +182,9 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): def instances(self): if self.instanceName and self.instanceType: - return [pki.server.PKIInstance( - self.instanceName, self.instanceType)] + instance = pki.server.PKIInstance(self.instanceName, self.instanceType) + instance.validate() + return [instance] instance_list = [] @@ -192,8 +193,9 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): for instanceName in os.listdir(pki.server.INSTANCE_BASE_DIR): if not self.instanceName or \ self.instanceName == instanceName: - instance_list.append( - pki.server.PKIInstance(instanceName)) + instance = pki.server.PKIInstance(instanceName) + instance.validate() + instance_list.append(instance) if not self.instanceType or self.instanceType == 9: for s in pki.server.SUBSYSTEM_TYPES: @@ -202,8 +204,9 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): os.path.join(pki.server.REGISTRY_DIR, s)): if not self.instanceName or \ self.instanceName == instanceName: - instance_list.append( - pki.server.PKIInstance(instanceName, 9)) + instance = pki.server.PKIInstance(instanceName, 9) + instance.validate() + instance_list.append(instance) instance_list.sort() @@ -212,7 +215,9 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): def subsystems(self, instance): if self.subsystemName: - return [pki.server.PKISubsystem(instance, self.subsystemName)] + subsystem = pki.server.PKISubsystem(instance, self.subsystemName) + subsystem.validate() + return [subsystem] subsystem_list = [] @@ -222,8 +227,9 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): instance.name) for subsystemName in os.listdir(registry_dir): if subsystemName in pki.server.SUBSYSTEM_TYPES: - subsystem_list.append( - pki.server.PKISubsystem(instance, subsystemName)) + subsystem = pki.server.PKISubsystem(instance, subsystemName) + subsystem.validate() + subsystem_list.append(subsystem) else: for subsystemName in pki.server.SUBSYSTEM_TYPES: registry_dir = os.path.join( @@ -231,8 +237,9 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader): subsystemName, instance.name) if os.path.exists(registry_dir): - subsystem_list.append( - pki.server.PKISubsystem(instance, subsystemName)) + subsystem = pki.server.PKISubsystem(instance, subsystemName) + subsystem.validate() + subsystem_list.append(subsystem) subsystem_list.sort() -- 1.8.4.2