summaryrefslogtreecommitdiffstats
path: root/base/server/python
diff options
context:
space:
mode:
Diffstat (limited to 'base/server/python')
-rw-r--r--base/server/python/pki/server/__init__.py93
-rw-r--r--base/server/python/pki/server/upgrade.py307
2 files changed, 400 insertions, 0 deletions
diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py
new file mode 100644
index 000000000..62dee2feb
--- /dev/null
+++ b/base/server/python/pki/server/__init__.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+# Authors:
+# Endi S. Dewata <edewata@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2013 Red Hat, Inc.
+# All rights reserved.
+#
+
+import re
+import os
+
+import pki
+
+INSTANCE_BASE_DIR = '/var/lib/pki'
+REGISTRY_DIR = '/etc/sysconfig/pki'
+SUBSYSTEM_TYPES = ['ca', 'kra', 'ocsp', 'tks']
+
+
+class PKISubsystem(object):
+
+ def __init__(self, instance, subsystemName):
+ self.instance = instance
+ self.name = subsystemName
+ self.type = instance.type
+ if self.type >= 10:
+ self.conf_dir = os.path.join(INSTANCE_BASE_DIR, \
+ instance.name, 'conf', subsystemName)
+ self.base_dir = os.path.join(INSTANCE_BASE_DIR, \
+ instance.name, subsystemName)
+ else:
+ self.conf_dir = os.path.join(BASE_DIR, instance.name, 'conf')
+ self.base_dir = os.path.join(BASE_DIR, instance.name)
+
+ self.validate()
+
+ def validate(self):
+ if not os.path.exists(self.conf_dir):
+ raise PKIException(
+ 'Invalid subsystem: ' + self.__repr__(),
+ None, self.instance)
+
+
+ def __repr__(self):
+ return str(self.instance) + '/' + self.name
+
+
+class PKIInstance(object):
+
+ def __init__(self, name, type=10):
+ self.name = name
+ self.type = type
+ 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)
+ else:
+ self.conf_dir = os.path.join(BASE_DIR, name, 'conf')
+ self.base_dir = os.path.join(BASE_DIR, name)
+
+ self.validate()
+
+ def validate(self):
+ if not os.path.exists(self.conf_dir):
+ raise PKIException(
+ 'Invalid instance: ' + self.__repr__(), None)
+
+ def __repr__(self):
+ if self.type == 9:
+ return "Dogtag 9 " + self.name
+ return self.name
+
+
+class PKIServerException(pki.PKIException):
+
+ def __init__(self, message, exception=None,\
+ instance=None, subsystem=None):
+
+ pki.upgrade.PKIException.__init__(self, message, exception)
+
+ self.instance = instance
+ self.subsystem = subsystem
diff --git a/base/server/python/pki/server/upgrade.py b/base/server/python/pki/server/upgrade.py
new file mode 100644
index 000000000..45ed9c13b
--- /dev/null
+++ b/base/server/python/pki/server/upgrade.py
@@ -0,0 +1,307 @@
+#!/usr/bin/python
+# Authors:
+# Endi S. Dewata <edewata@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2013 Red Hat, Inc.
+# All rights reserved.
+#
+
+import os
+import traceback
+
+import pki
+import pki.upgrade
+import pki.server
+
+from pki.upgrade import verbose
+
+UPGRADE_DIR = pki.SHARE_DIR + '/server/upgrade'
+
+INSTANCE_TRACKER = '%s/tomcat.conf'
+SUBSYSTEM_TRACKER = '%s/CS.cfg'
+
+
+class PKIServerUpgradeScriptlet(pki.upgrade.PKIUpgradeScriptlet):
+
+ def __init__(self):
+
+ super(PKIServerUpgradeScriptlet, self).__init__()
+
+ def can_upgrade(self, instance, subsystem=None):
+
+ # A scriptlet can run if the version matches the tracker and
+ # the index is the next to be executed.
+
+ tracker = self.upgrader.get_tracker(instance, subsystem)
+
+ return self.version == tracker.get_version() and \
+ self.index == tracker.get_index() + 1
+
+ def update_tracker(self, instance, subsystem=None):
+
+ # Increment the index in the tracker. If it's the last scriptlet
+ # in this version, update the tracker version.
+
+ tracker = self.upgrader.get_tracker(instance, subsystem)
+
+ if not self.last:
+ tracker.set_index(self.index)
+
+ else:
+ tracker.remove_index()
+ tracker.set_version(self.version.next)
+
+ tracker.write()
+
+ def upgrade(self):
+
+ for instance in self.upgrader.instances():
+
+ self.upgrade_subsystems(instance)
+
+ # If upgrading a specific subsystem don't upgrade the instance.
+ if self.upgrader.subsystemName:
+ continue
+
+ if not self.can_upgrade(instance):
+ if verbose: print 'Skipping ' + str(instance) + ' instance.'
+ continue
+
+ try:
+ if verbose: print 'Upgrading ' + str(instance) + ' instance.'
+ self.upgrade_instance(instance)
+ self.update_tracker(instance)
+
+ except Exception as e:
+
+ if verbose: traceback.print_exc()
+ else: print 'ERROR: ' + e.message
+
+ message = 'Failed upgrading ' + str(instance) + ' instance.'
+ if self.upgrader.silent:
+ print message
+ else:
+ result = pki.read_text(message + ' Continue (Yes/No)',
+ options=['Y', 'N'], default='Y', delimiter='?', caseSensitive=False).lower()
+ if result == 'y': continue
+
+ raise pki.server.PKIServerException(
+ 'Upgrade failed in ' + str(instance) + ': ' + e.message,
+ e, instance)
+
+ def upgrade_subsystems(self, instance):
+
+ for subsystem in self.upgrader.subsystems(instance):
+
+ if not self.can_upgrade(instance, subsystem):
+ if verbose: print 'Skipping ' + str(subsystem) + ' subsystem.'
+ continue
+
+ try:
+ if verbose: print 'Upgrading ' + str(subsystem) + ' subsystem.'
+ self.upgrade_subsystem(instance, subsystem)
+ self.update_tracker(instance, subsystem)
+
+ except Exception as e:
+
+ if verbose: traceback.print_exc()
+ else: print 'ERROR: ' + e.message
+
+ message = 'Failed upgrading ' + str(subsystem) + ' subsystem.'
+ if self.upgrader.silent:
+ print message
+ else:
+ result = pki.read_text(message + ' Continue (Yes/No)',
+ options=['Y', 'N'], default='Y', delimiter='?', caseSensitive=False).lower()
+ if result == 'y': continue
+
+ raise pki.server.PKIServerException(
+ 'Upgrade failed in ' + str(subsystem) + ': ' + e.message,
+ e, instance, subsystem)
+
+ def upgrade_subsystem(self, instance, subsystem):
+ # Callback method to upgrade a subsystem.
+ pass
+
+ def upgrade_instance(self, instance):
+ # Callback method to upgrade an instance.
+ pass
+
+
+class PKIServerUpgrader(pki.upgrade.PKIUpgrader):
+
+ def __init__(self, instanceName=None, instanceType=None, subsystemName=None, \
+ upgrade_dir=UPGRADE_DIR, version=None, index=None, silent=False):
+
+ super(PKIServerUpgrader, self).__init__(upgrade_dir, version, index, silent)
+
+ if subsystemName and not instanceName:
+ raise pki.PKIException(
+ 'Invalid subsystem: ' + subsystemName + ', Instance not defined')
+
+ self.instanceName = instanceName
+ self.instanceType = instanceType
+ self.subsystemName = subsystemName
+
+ self.instance_trackers = {}
+ self.subsystem_trackers = {}
+
+ def instances(self):
+
+ if self.instanceName and self.instanceType:
+ return [pki.server.PKIInstance(self.instanceName, self.instanceType)]
+
+ list = []
+
+ if not self.instanceType or self.instanceType >=10:
+ if os.path.exists(os.path.join(pki.server.REGISTRY_DIR,'tomcat')):
+ for instanceName in os.listdir(pki.server.INSTANCE_BASE_DIR):
+ if not self.instanceName or \
+ self.instanceName == instanceName:
+ list.append(pki.server.PKIInstance(instanceName))
+
+ if not self.instanceType or self.instanceType == 9:
+ for s in pki.server.SUBSYSTEM_TYPES:
+ if os.path.exists(os.path.join(pki.server.REGISTRY_DIR, s)):
+ for instanceName in \
+ os.listdir(os.path.join(pki.server.REGISTRY_DIR, s)):
+ if not self.instanceName or \
+ self.instanceName == instanceName:
+ list.append(pki.server.PKIInstance(instanceName, 9))
+
+ list.sort()
+
+ return list
+
+
+ def subsystems(self, instance):
+
+ if self.subsystemName:
+ return [pki.server.PKISubsystem(instance, self.subsystemName)]
+
+ list = []
+
+ if instance.type >= 10:
+ registry_dir = os.path.join(pki.server.REGISTRY_DIR, 'tomcat',
+ instance.name)
+ for subsystemName in os.listdir(registry_dir):
+ if subsystemName in pki.server.SUBSYSTEM_TYPES:
+ list.append(pki.server.PKISubsystem(instance, subsystemName))
+ else:
+ for subsystemName in pki.server.SUBSYSTEM_TYPES:
+ registry_dir = os.path.join(
+ pki.server.REGISTRY_DIR,
+ subsystemName,
+ instance.name)
+ if os.path.exists(registry_dir):
+ list.append(pki.server.PKISubsystem(instance, subsystemName))
+
+ list.sort()
+
+ return list
+
+ def get_tracker(self, instance, subsystem=None):
+
+ if subsystem:
+ name = str(subsystem)
+ try:
+ tracker = self.subsystem_trackers[instance]
+ except KeyError:
+ tracker = pki.upgrade.PKIUpgradeTracker(name + ' subsystem',
+ SUBSYSTEM_TRACKER % subsystem.conf_dir,
+ version_key='cms.product.version',
+ index_key='cms.upgrade.index')
+ self.subsystem_trackers[name] = tracker
+
+ else:
+ try:
+ tracker = self.instance_trackers[str(instance)]
+ except KeyError:
+ tracker = pki.upgrade.PKIUpgradeTracker(str(instance) + ' instance',
+ INSTANCE_TRACKER % instance.conf_dir,
+ version_key='PKI_VERSION',
+ index_key='PKI_UPGRADE_INDEX')
+ self.instance_trackers[str(instance)] = tracker
+
+ return tracker
+
+ def get_current_version(self):
+
+ current_version = None
+
+ for instance in self.instances():
+
+ # if upgrading the entire instance, check the instance version
+ if not self.subsystemName:
+ tracker = self.get_tracker(instance)
+ version = tracker.get_version()
+
+ # if instance version is older, use instance version
+ if not current_version or version < current_version:
+ current_version = version
+
+ for subsystem in self.subsystems(instance):
+
+ # subsystem is always upgraded, check the subsystem version
+ tracker = self.get_tracker(instance, subsystem)
+ version = tracker.get_version()
+
+ # if subsystem version is older, use subsystem version
+ if not current_version or version < current_version:
+ current_version = version
+
+ return current_version
+
+ def show_tracker(self):
+
+ for instance in self.instances():
+
+ if not self.subsystemName:
+ tracker = self.get_tracker(instance)
+ tracker.show()
+
+ for subsystem in self.subsystems(instance):
+
+ tracker = self.get_tracker(instance, subsystem)
+ tracker.show()
+
+ def set_tracker(self, version):
+
+ for instance in self.instances():
+
+ if not self.subsystemName:
+ tracker = self.get_tracker(instance)
+ tracker.set(version)
+
+ for subsystem in self.subsystems(instance):
+
+ tracker = self.get_tracker(instance, subsystem)
+ tracker.set(version)
+
+ def remove_tracker(self):
+
+ for instance in self.instances():
+
+ if not self.subsystemName:
+ tracker = self.get_tracker(instance)
+ tracker.remove()
+
+ for subsystem in self.subsystems(instance):
+
+ tracker = self.get_tracker(instance, subsystem)
+ tracker.remove()
+
+ print 'Tracker has been removed.'