summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/common/python/pki/__init__.py7
-rw-r--r--base/common/python/pki/upgrade.py182
-rw-r--r--base/common/python/pki/util.py34
-rwxr-xr-xbase/common/sbin/pki-upgrade40
-rw-r--r--base/server/python/pki/server/upgrade.py6
-rwxr-xr-xbase/server/sbin/pki-server-upgrade41
-rwxr-xr-xbase/server/upgrade/10.0.1/01-ReplaceRandomNumberGenerator10
-rwxr-xr-xbase/server/upgrade/10.0.1/02-CloningInterfaceChanges2
-rwxr-xr-xbase/server/upgrade/10.0.1/03-AddRestServlet2
-rw-r--r--specs/pki-core.spec1
10 files changed, 279 insertions, 46 deletions
diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py
index 95f3a7335..404aa92d4 100644
--- a/base/common/python/pki/__init__.py
+++ b/base/common/python/pki/__init__.py
@@ -19,13 +19,14 @@
# All rights reserved.
#
-import re
import os
+import re
CONF_DIR = '/etc/pki'
SHARE_DIR = '/usr/share/pki'
BASE_DIR = '/var/lib'
+LOG_DIR = '/var/log/pki'
PACKAGE_VERSION = SHARE_DIR + '/VERSION'
@@ -137,6 +138,10 @@ class PropertyFile(object):
self.lines.insert(index, line)
+ def remove_line(self, index):
+
+ self.lines.pop(index)
+
def index(self, name):
for i, line in enumerate(self.lines):
diff --git a/base/common/python/pki/upgrade.py b/base/common/python/pki/upgrade.py
index 3be5025b2..9f927130f 100644
--- a/base/common/python/pki/upgrade.py
+++ b/base/common/python/pki/upgrade.py
@@ -22,16 +22,18 @@
import functools
import os
import re
+import shutil
import traceback
import pki
+import pki.util
DEFAULT_VERSION = '10.0.0'
UPGRADE_DIR = pki.SHARE_DIR + '/upgrade'
+BACKUP_DIR = pki.LOG_DIR + '/upgrade'
SYSTEM_TRACKER = pki.CONF_DIR + '/pki.version'
-
verbose = False
@@ -246,6 +248,9 @@ class PKIUpgradeScriptlet(object):
self.message = None
self.upgrader = None
+ def get_backup_dir(self):
+ return BACKUP_DIR + '/' + str(self.version) + '/' + str(self.index)
+
def can_upgrade(self):
# A scriptlet can run if the version matches the tracker and
@@ -276,6 +281,15 @@ class PKIUpgradeScriptlet(object):
def upgrade(self):
+ backup_dir = self.get_backup_dir()
+
+ if os.path.exists(backup_dir):
+ # remove old backup dir
+ shutil.rmtree(backup_dir)
+
+ # create backup dir
+ os.makedirs(backup_dir)
+
try:
if not self.can_upgrade():
if verbose: print 'Skipping system.'
@@ -300,6 +314,58 @@ class PKIUpgradeScriptlet(object):
raise pki.PKIException('Upgrade failed: ' + e.message, e)
+ def revert(self):
+
+ backup_dir = self.get_backup_dir()
+
+ if not os.path.exists(backup_dir):
+ return
+
+ oldfiles = backup_dir + '/oldfiles'
+ if os.path.exists(oldfiles):
+
+ # restore all backed up files
+ for root, dirnames, filenames in os.walk(oldfiles):
+ path = root[len(oldfiles):]
+ for filename in filenames:
+ source = root + '/' + filename
+ target = path + '/' + filename
+
+ if verbose: print 'Restoring ' + target
+ pki.util.copyfile(source, target)
+
+ newfiles = backup_dir + '/newfiles'
+ if os.path.exists(newfiles):
+
+ # remove files that did not exist before upgrade
+ with open(newfiles, 'r') as f:
+ for filename in f:
+ filename = filename.strip('\n')
+
+ if os.path.exists(filename):
+ if verbose: print 'Deleting ' + filename
+ os.remove(filename)
+
+ def backup(self, filename):
+
+ backup_dir = self.get_backup_dir()
+ backup_file = backup_dir + '/oldfiles' + filename
+
+ if os.path.exists(filename):
+
+ # if file exists, keep a copy
+
+ if verbose: print 'Saving ' + filename
+ pki.util.copyfile(filename, backup_file)
+
+ else:
+
+ # otherwise, keep the name
+
+ if verbose: print 'Recording ' + filename
+ with open(backup_dir + '/newfiles', 'a') as f:
+ f.write(filename + '\n')
+
def __eq__(self, other):
return self.version == other.version and self.index == other.index
@@ -330,30 +396,41 @@ class PKIUpgrader(object):
return os.path.join(self.upgrade_dir, str(version))
- def versions(self):
-
- current_version = self.get_current_version()
- target_version = self.get_target_version()
+ def all_versions(self):
all_versions = []
if os.path.exists(self.upgrade_dir):
for version in os.listdir(self.upgrade_dir):
version = Version(version)
-
- # skip old versions
- if version >= current_version:
- all_versions.append(version)
+ all_versions.append(version)
all_versions.sort()
+ return all_versions
+
+ def versions(self):
+
+ current_version = self.get_current_version()
+ target_version = self.get_target_version()
+
+ current_versions = []
+
+ for version in self.all_versions():
+
+ # skip old versions
+ if version >= current_version:
+ current_versions.append(version)
+
+ current_versions.sort()
+
versions = []
- for index, version in enumerate(all_versions):
+ for index, version in enumerate(current_versions):
# link versions
- if index < len(all_versions) - 1:
- version.next = all_versions[index + 1]
+ if index < len(current_versions) - 1:
+ version.next = current_versions[index + 1]
else:
version.next = target_version
@@ -367,10 +444,13 @@ class PKIUpgrader(object):
def scriptlets(self, version):
- version_dir = self.version_dir(version)
- filenames = os.listdir(version_dir)
scriptlets = []
+ version_dir = self.version_dir(version)
+ if not os.path.exists(version_dir):
+ return scriptlets
+
+ filenames = os.listdir(version_dir)
for filename in filenames:
# parse <index>-<classname>
@@ -449,7 +529,7 @@ class PKIUpgrader(object):
return
# execute scriptlets
- for index, scriptlet in enumerate(scriptlets):
+ for scriptlet in scriptlets:
message = str(scriptlet.index) + '. ' + scriptlet.message
@@ -493,7 +573,7 @@ class PKIUpgrader(object):
versions = self.versions()
- for index, version in enumerate(versions):
+ for version in versions:
self.upgrade_version(version)
print
@@ -506,6 +586,72 @@ class PKIUpgrader(object):
print 'Upgrade incomplete.'
+ def revert_version(self, version):
+
+ print 'Reverting to version ' + str(version) + ':'
+
+ scriptlets = self.scriptlets(version)
+ scriptlets.reverse()
+
+ for scriptlet in scriptlets:
+
+ message = str(scriptlet.index) + '. ' + scriptlet.message
+
+ if self.silent:
+ print message
+
+ else:
+ result = pki.read_text(message + ' (Yes/No)',
+ options=['Y', 'N'], default='Y', caseSensitive=False).lower()
+
+ if result == 'n':
+ raise pki.PKIException('Revert canceled.')
+
+ try:
+ scriptlet.revert()
+
+ except pki.PKIException as e:
+ raise
+
+ except Exception as e:
+
+ print
+
+ message = 'Revert failed: ' + e.message
+
+ if verbose:
+ traceback.print_exc()
+ else:
+ print e.message
+
+ print
+
+ result = pki.read_text('Continue (Yes/No)',
+ options=['Y', 'N'], default='Y', delimiter='?', caseSensitive=False).lower()
+
+ if result == 'n':
+ raise pki.PKIException(message, e)
+
+ self.set_tracker(version)
+
+ def revert(self):
+
+ current_version = self.get_current_version()
+
+ versions = self.all_versions()
+ versions.reverse()
+
+ # find the first version smaller than the current version
+ for version in versions:
+
+ if version >= current_version:
+ continue
+
+ self.revert_version(version)
+ return
+
+ print 'Unable to revert from version ' + str(current_version) + '.'
+
def show_tracker(self):
tracker = self.get_tracker()
@@ -527,13 +673,13 @@ class PKIUpgrader(object):
tracker = self.get_tracker()
tracker.set(version)
+ print 'Tracker has been set to version ' + str(version) + '.'
+
def reset_tracker(self):
target_version = self.get_target_version()
self.set_tracker(target_version)
- print 'Tracker has been set to version ' + str(target_version) + '.'
-
def remove_tracker(self):
tracker = self.get_tracker()
diff --git a/base/common/python/pki/util.py b/base/common/python/pki/util.py
new file mode 100644
index 000000000..7db4fbe79
--- /dev/null
+++ b/base/common/python/pki/util.py
@@ -0,0 +1,34 @@
+#!/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 shutil
+
+
+def copyfile(source, dest):
+
+ dir = os.path.dirname(dest)
+ if not os.path.exists(dir):
+ os.makedirs(dir)
+
+ shutil.copy2(source, dest)
+ st = os.stat(source)
+ os.chown(dest, st.st_uid, st.st_gid)
diff --git a/base/common/sbin/pki-upgrade b/base/common/sbin/pki-upgrade
index 8b30f8fff..c739598d4 100755
--- a/base/common/sbin/pki-upgrade
+++ b/base/common/sbin/pki-upgrade
@@ -43,6 +43,7 @@ def usage():
print
print ' --silent Upgrade in silent mode. Ignore any failures.'
print ' --status Show upgrade status only. Do not perform upgrade.'
+ print ' --revert Revert the last version'
print
print ' -X Show advanced usage.'
print ' -v, --verbose Run in verbose mode.'
@@ -52,8 +53,9 @@ def usage():
def advancedUsage():
print 'WARNING: These options may render the system unusable.'
print 'Usage: pki-upgrade [OPTIONS]'
- print ' --remove-tracker Remove tracker'
- print ' --reset-tracker Reset tracker to match package version'
+ print ' --remove-tracker Remove tracker'
+ print ' --reset-tracker Reset tracker to match package version'
+ print ' --set-tracker <version> Set tracker to a specific version'
def main(argv):
@@ -63,8 +65,8 @@ def main(argv):
try:
opts, args = getopt.getopt(argv[1:], 'hi:s:t:vX', [
'scriptlet-version=', 'scriptlet-index=',
- 'silent', 'status',
- 'remove-tracker', 'reset-tracker',
+ 'silent', 'status', 'revert',
+ 'remove-tracker', 'reset-tracker', 'set-tracker=',
'verbose', 'help'])
except getopt.GetoptError as e:
@@ -72,20 +74,24 @@ def main(argv):
usage()
sys.exit(1)
- version = None
- index = None
+ scriptlet_version = None
+ scriptlet_index = None
silent = False
status = False
+ revert = False
+
remove_tracker = False
reset_tracker = False
+ tracker_version = None
+
for o, a in opts:
if o == '--scriptlet-version':
- version = a
+ scriptlet_version = a
elif o == '--scriptlet-index':
- index = int(a)
+ scriptlet_index = int(a)
elif o == '--silent':
silent = True
@@ -93,12 +99,18 @@ def main(argv):
elif o == '--status':
status = True
+ elif o == '--revert':
+ revert = True
+
elif o == '--remove-tracker':
remove_tracker = True
elif o == '--reset-tracker':
reset_tracker = True
+ elif o == '--set-tracker':
+ tracker_version = pki.upgrade.Version(a)
+
elif o in ('-v', '--verbose'):
pki.upgrade.verbose = True
@@ -115,26 +127,32 @@ def main(argv):
usage()
sys.exit(1)
- if index and not version:
+ if scriptlet_index and not scriptlet_version:
print 'ERROR: --scriptlet-index requires --scriptlet-version'
usage()
sys.exit(1)
try:
upgrader = pki.upgrade.PKIUpgrader(
- version = version,
- index = index,
+ version = scriptlet_version,
+ index = scriptlet_index,
silent = silent)
if status:
upgrader.status()
+ elif revert:
+ upgrader.revert()
+
elif remove_tracker:
upgrader.remove_tracker()
elif reset_tracker:
upgrader.reset_tracker()
+ elif tracker_version is not None:
+ upgrader.set_tracker(tracker_version)
+
else:
upgrader.upgrade()
diff --git a/base/server/python/pki/server/upgrade.py b/base/server/python/pki/server/upgrade.py
index 84e05127e..940dbe44a 100644
--- a/base/server/python/pki/server/upgrade.py
+++ b/base/server/python/pki/server/upgrade.py
@@ -29,6 +29,7 @@ import pki.server
from pki.upgrade import verbose
UPGRADE_DIR = pki.SHARE_DIR + '/server/upgrade'
+BACKUP_DIR = pki.LOG_DIR + '/server/upgrade'
INSTANCE_TRACKER = '%s/tomcat.conf'
SUBSYSTEM_TRACKER = '%s/CS.cfg'
@@ -40,6 +41,9 @@ class PKIServerUpgradeScriptlet(pki.upgrade.PKIUpgradeScriptlet):
super(PKIServerUpgradeScriptlet, self).__init__()
+ def get_backup_dir(self):
+ return BACKUP_DIR + '/' + str(self.version) + '/' + str(self.index)
+
def can_upgrade(self, instance, subsystem=None):
# A scriptlet can run if the version matches the tracker and
@@ -293,6 +297,8 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader):
tracker = self.get_tracker(instance, subsystem)
tracker.set(version)
+ print 'Tracker has been set to version ' + str(version) + '.'
+
def remove_tracker(self):
for instance in self.instances():
diff --git a/base/server/sbin/pki-server-upgrade b/base/server/sbin/pki-server-upgrade
index 58bc9ccb4..0b43f9b4b 100755
--- a/base/server/sbin/pki-server-upgrade
+++ b/base/server/sbin/pki-server-upgrade
@@ -24,6 +24,7 @@ import signal
import sys
import pki
+import pki.upgrade
import pki.server.upgrade
@@ -47,6 +48,7 @@ def usage():
print
print ' --silent Upgrade in silent mode. Ignore any failures.'
print ' --status Show upgrade status only. Do not perform upgrade.'
+ print ' --revert Revert the last version'
print
print ' -X Show advanced usage.'
print ' -v, --verbose Run in verbose mode.'
@@ -56,8 +58,9 @@ def usage():
def advancedUsage():
print 'WARNING: These options may render the system unusable.'
print 'Usage: pki-upgrade [OPTIONS]'
- print ' --remove-tracker Remove tracker'
- print ' --reset-tracker Reset tracker to match package version'
+ print ' --remove-tracker Remove tracker'
+ print ' --reset-tracker Reset tracker to match package version'
+ print ' --set-tracker <version> Set tracker to a specific version'
def main(argv):
@@ -68,8 +71,8 @@ def main(argv):
opts, args = getopt.getopt(argv[1:], 'hi:s:t:vX', [
'instance=', 'subsystem=', 'instance-type=',
'scriptlet-version=', 'scriptlet-index=',
- 'silent', 'status',
- 'remove-tracker', 'reset-tracker',
+ 'silent', 'status', 'revert',
+ 'remove-tracker', 'reset-tracker', 'set-tracker=',
'verbose', 'help'])
except getopt.GetoptError as e:
@@ -81,14 +84,18 @@ def main(argv):
subsystemName = None
instanceType = None
- version = None
- index = None
+ scriptlet_version = None
+ scriptlet_index = None
silent = False
status = False
+ revert = False
+
remove_tracker = False
reset_tracker = False
+ tracker_version = None
+
for o, a in opts:
if o in ('-i', '--instance'):
instanceName = a
@@ -100,10 +107,10 @@ def main(argv):
instanceType = int(a)
elif o == '--scriptlet-version':
- version = a
+ scriptlet_version = a
elif o == '--scriptlet-index':
- index = int(a)
+ scriptlet_index = int(a)
elif o == '--silent':
silent = True
@@ -111,12 +118,18 @@ def main(argv):
elif o == '--status':
status = True
+ elif o == '--revert':
+ revert = True
+
elif o == '--remove-tracker':
remove_tracker = True
elif o == '--reset-tracker':
reset_tracker = True
+ elif o == '--set-tracker':
+ tracker_version = pki.upgrade.Version(a)
+
elif o in ('-v', '--verbose'):
pki.upgrade.verbose = True
@@ -138,7 +151,7 @@ def main(argv):
usage()
sys.exit(1)
- if index and not version:
+ if scriptlet_index and not scriptlet_version:
print 'ERROR: --scriptlet-index requires --scriptlet-version'
usage()
sys.exit(1)
@@ -148,19 +161,25 @@ def main(argv):
instanceName = instanceName,
subsystemName = subsystemName,
instanceType = instanceType,
- version = version,
- index = index,
+ version = scriptlet_version,
+ index = scriptlet_index,
silent = silent)
if status:
upgrader.status()
+ elif revert:
+ upgrader.revert()
+
elif remove_tracker:
upgrader.remove_tracker()
elif reset_tracker:
upgrader.reset_tracker()
+ elif tracker_version is not None:
+ upgrader.set_tracker(tracker_version)
+
else:
upgrader.upgrade()
diff --git a/base/server/upgrade/10.0.1/01-ReplaceRandomNumberGenerator b/base/server/upgrade/10.0.1/01-ReplaceRandomNumberGenerator
index e73ede236..af3d53cc4 100755
--- a/base/server/upgrade/10.0.1/01-ReplaceRandomNumberGenerator
+++ b/base/server/upgrade/10.0.1/01-ReplaceRandomNumberGenerator
@@ -46,6 +46,8 @@ class ReplaceRandomNumberGenerator(pki.server.upgrade.PKIServerUpgradeScriptlet)
'webapps', subsystem.name,
'META-INF', 'context.xml')
+ self.backup(context_xml)
+
if not os.path.exists(context_xml):
self.create_context_xml(
instance,
@@ -64,13 +66,11 @@ class ReplaceRandomNumberGenerator(pki.server.upgrade.PKIServerUpgradeScriptlet)
with open(context_xml, 'w') as f:
f.write(etree.tostring(document, pretty_print=True))
-
def upgrade_instance(self, instance):
self.update_root_context_xml(instance)
self.update_pki_context_xml(instance)
-
def update_root_context_xml(self, instance):
context_xml = os.path.join(
@@ -78,6 +78,8 @@ class ReplaceRandomNumberGenerator(pki.server.upgrade.PKIServerUpgradeScriptlet)
'webapps', 'ROOT',
'META-INF', 'context.xml')
+ self.backup(context_xml)
+
if not os.path.exists(context_xml):
self.create_context_xml(instance, 'server', 'ROOT')
@@ -95,6 +97,8 @@ class ReplaceRandomNumberGenerator(pki.server.upgrade.PKIServerUpgradeScriptlet)
'webapps', 'pki',
'META-INF', 'context.xml')
+ self.backup(context_xml)
+
if not os.path.exists(context_xml):
self.create_context_xml(instance, 'server', 'pki')
@@ -105,7 +109,6 @@ class ReplaceRandomNumberGenerator(pki.server.upgrade.PKIServerUpgradeScriptlet)
with open(context_xml, 'w') as f:
f.write(etree.tostring(document, pretty_print=True))
-
def create_context_xml(self, instance, pkg, context):
uid = pwd.getpwnam('pkiuser').pw_uid
@@ -147,7 +150,6 @@ class ReplaceRandomNumberGenerator(pki.server.upgrade.PKIServerUpgradeScriptlet)
manager.set('secureRandomProvider', 'Mozilla-JSS')
manager.set('secureRandomAlgorithm', 'pkcs11prng')
-
def update_authenticator(self, document):
context = document.getroot()
diff --git a/base/server/upgrade/10.0.1/02-CloningInterfaceChanges b/base/server/upgrade/10.0.1/02-CloningInterfaceChanges
index d97cb4258..c70a4263c 100755
--- a/base/server/upgrade/10.0.1/02-CloningInterfaceChanges
+++ b/base/server/upgrade/10.0.1/02-CloningInterfaceChanges
@@ -106,6 +106,8 @@ class CloningInterfaceChanges(pki.server.upgrade.PKIServerUpgradeScriptlet):
'webapps', subsystem.name,
'WEB-INF', 'web.xml')
+ self.backup(web_xml)
+
self.doc = ET.parse(web_xml)
self.root = self.doc.getroot()
self.remove_get_token_info(subsystem.name)
diff --git a/base/server/upgrade/10.0.1/03-AddRestServlet b/base/server/upgrade/10.0.1/03-AddRestServlet
index dd656e972..37304e294 100755
--- a/base/server/upgrade/10.0.1/03-AddRestServlet
+++ b/base/server/upgrade/10.0.1/03-AddRestServlet
@@ -53,6 +53,8 @@ class AddRestServlet(pki.server.upgrade.PKIServerUpgradeScriptlet):
'webapps', subsystem.name,
'WEB-INF', 'web.xml')
+ self.backup(web_xml)
+
self.doc = ET.parse(web_xml)
self.root = self.doc.getroot()
self.add_rest_services_servlet()
diff --git a/specs/pki-core.spec b/specs/pki-core.spec
index 812f86b6f..158383b77 100644
--- a/specs/pki-core.spec
+++ b/specs/pki-core.spec
@@ -625,7 +625,6 @@ then
else
# On RPM upgrade run system upgrade
echo "Upgrading system at `/bin/date`." >> /var/log/pki/pki-upgrade-%{version}.log 2>&1
- /sbin/pki-upgrade --remove-tracker >> /var/log/pki/pki-upgrade-%{version}.log 2>&1
/sbin/pki-upgrade --silent >> /var/log/pki/pki-upgrade-%{version}.log 2>&1
echo >> /var/log/pki/pki-upgrade-%{version}.log 2>&1
fi