[Pki-devel] [PATCH] 544 Added server management library.

Fraser Tweedale ftweedal at redhat.com
Tue Jan 27 03:44:53 UTC 2015


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 at 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@%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
> 

> _______________________________________________
> Pki-devel mailing list
> Pki-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/pki-devel




More information about the Pki-devel mailing list