Tested in conjection with 545.
ACK modulo comments:
1. Subsystem enable/disable requires instance restart to take
effect. If this is intended/unavoidable, that's fine, but could be
made clearer.
2. What are the implications for Debian/Ubuntu with hardedcoded
calls to systemctl? Could you dispatch to systemctl/service/upstart
as appropriate?
On Thu, Jan 22, 2015 at 01:20:01PM -0600, Endi Sukma Dewata wrote:
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
--
Endi S. Dewata
From 03bf1c8d3a1c987582bc65d2e8df0f3d258f8843 Mon Sep 17 00:00:00
2001
From: "Endi S. Dewata" <edewata(a)redhat.com>
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(a)%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
+ <instance>/conf/Catalina/localhost/<name>.xml and point the docBase
+ to the specified location. The web application will become available
+ under "/<name>" 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