fuel_upgrade: install rpm packages with fuel 6.1
We don't need to install bootstrap images, provisioning images and new puppet manifests, because we have them packaged now. Since now, the fuel_upgrade is supposed to install the "fuel-release" package, run puppet and create new Docker containers. Depends-On: I417f8e9495e7dc8b22fc33b3c88408b879abaec2 Implements: blueprint package-fuel-components Change-Id: I379749673c67c459c7070d986094ec6236d7ca6e Signed-off-by: Igor Kalnitsky <igor@kalnitsky.org>
This commit is contained in:
parent
de04ee015c
commit
dbb9b9f384
|
@ -1,180 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
import os
|
||||
import six
|
||||
|
||||
from fuel_upgrade.utils import copy
|
||||
from fuel_upgrade.utils import remove
|
||||
from fuel_upgrade.utils import rename
|
||||
from fuel_upgrade.utils import symlink
|
||||
from fuel_upgrade.utils import symlink_if_src_exists
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Action(object):
|
||||
"""An action interface.
|
||||
|
||||
The interface is clear and no need to be commented.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
# declare custom undo action, not a default one
|
||||
if 'undo' in kwargs:
|
||||
self.undo = ActionManager(kwargs['undo']).do
|
||||
|
||||
@abc.abstractmethod
|
||||
def do(self):
|
||||
"""Performs an action.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def undo(self):
|
||||
"""Rollbacks an action.
|
||||
"""
|
||||
|
||||
|
||||
class Copy(Action):
|
||||
"""Copy action provides a way to copy stuff from one place to another.
|
||||
|
||||
The source and destination could be either a file or directory.
|
||||
|
||||
:param from: copy from
|
||||
:param to: copy to
|
||||
:param overwrite: overwrite a destination if True
|
||||
:param symlinks: resolve symlinks if True
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Copy, self).__init__(**kwargs)
|
||||
|
||||
self._from = kwargs['from']
|
||||
self._to = kwargs['to']
|
||||
self._overwrite = kwargs.get('overwrite', True)
|
||||
self._symlinks = kwargs.get('symlinks', True)
|
||||
|
||||
def do(self):
|
||||
copy(self._from, self._to, self._overwrite, self._symlinks)
|
||||
|
||||
def undo(self):
|
||||
# destination should be a path/to/file in case source was a file
|
||||
destination = self._to
|
||||
if not os.path.isdir(self._from) and os.path.isdir(self._to):
|
||||
basename = os.path.basename(self._from)
|
||||
destination = os.path.join(self._to, basename)
|
||||
|
||||
# do nothing if destination doesn't exist
|
||||
remove(destination, ignore_errors=True)
|
||||
|
||||
|
||||
class Move(Action):
|
||||
"""Move action provides a way to move stuff from one place to another.
|
||||
|
||||
:param from: a move source
|
||||
:param to: a move destination
|
||||
:param overwrite: overwrite a destination if True
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Move, self).__init__(**kwargs)
|
||||
|
||||
self._from = kwargs['from']
|
||||
self._to = kwargs['to']
|
||||
self._overwrite = kwargs.get('overwrite', True)
|
||||
|
||||
def do(self):
|
||||
rename(self._from, self._to, self._overwrite)
|
||||
|
||||
def undo(self):
|
||||
rename(self._to, self._from, self._overwrite)
|
||||
|
||||
|
||||
class Symlink(Action):
|
||||
"""Symlink action provides a way to make a symbolic link to some resource.
|
||||
|
||||
:param from: a path to origin resource
|
||||
:param to: a path to link
|
||||
:param overwrite: overwrite link if True
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Symlink, self).__init__(**kwargs)
|
||||
|
||||
self._from = kwargs['from']
|
||||
self._to = kwargs['to']
|
||||
self._overwrite = kwargs.get('overwrite', True)
|
||||
|
||||
def do(self):
|
||||
symlink(self._from, self._to, self._overwrite)
|
||||
|
||||
def undo(self):
|
||||
remove(self._to)
|
||||
|
||||
|
||||
class SymlinkIfSrcExists(Symlink):
|
||||
"""SymlinkIfSrcExists action provides a way
|
||||
to make a symbolic link to some resource but only if
|
||||
source exists. I.e. link 1 -> 2 will be created only if 2 exists.
|
||||
|
||||
:param from: a path to origin resource
|
||||
:param to: a path to link
|
||||
:param overwrite: overwrite link if True
|
||||
"""
|
||||
def do(self):
|
||||
symlink_if_src_exists(self._from, self._to, self._overwrite)
|
||||
|
||||
|
||||
class ActionManager(Action):
|
||||
"""The action manager is designed to manage actions, run it or
|
||||
rollback based on action description.
|
||||
|
||||
:param actions: a list with action descriptions
|
||||
:param context: a dict with some context that's passed to actions
|
||||
"""
|
||||
|
||||
#: a list of supported actions
|
||||
supported_actions = {
|
||||
'copy': Copy,
|
||||
'move': Move,
|
||||
'symlink': Symlink,
|
||||
'symlink_if_src_exists': SymlinkIfSrcExists
|
||||
}
|
||||
|
||||
def __init__(self, actions):
|
||||
#: a list of actions to execute
|
||||
self._actions = []
|
||||
|
||||
#: a list of executed actions (we need it to rollback feature)
|
||||
self._history = []
|
||||
|
||||
# convert some input action description to class instances
|
||||
for action in actions:
|
||||
action_class = self.supported_actions[action['name']]
|
||||
self._actions.append(action_class(**action))
|
||||
|
||||
def do(self):
|
||||
"""Performs actions saving in history."""
|
||||
|
||||
for action in self._actions:
|
||||
action.do()
|
||||
self._history.append(action)
|
||||
|
||||
def undo(self):
|
||||
"""Rollbacks completed actions."""
|
||||
|
||||
while self._history:
|
||||
action = self._history.pop()
|
||||
action.undo()
|
|
@ -29,13 +29,11 @@ from fuel_upgrade.checker_manager import CheckerManager
|
|||
from fuel_upgrade.config import build_config
|
||||
from fuel_upgrade.upgrade import UpgradeManager
|
||||
|
||||
from fuel_upgrade.engines.bootstrap import BootstrapUpgrader
|
||||
from fuel_upgrade.engines.docker_engine import DockerInitializer
|
||||
from fuel_upgrade.engines.docker_engine import DockerUpgrader
|
||||
from fuel_upgrade.engines.host_system import HostSystemUpgrader
|
||||
from fuel_upgrade.engines.openstack import OpenStackUpgrader
|
||||
from fuel_upgrade.engines.raise_error import RaiseErrorUpgrader
|
||||
from fuel_upgrade.engines.targetimages import TargetImagesUpgrader
|
||||
|
||||
from fuel_upgrade.pre_upgrade_hooks import PreUpgradeHookManager
|
||||
|
||||
|
@ -48,9 +46,7 @@ SUPPORTED_SYSTEMS = {
|
|||
'host-system': HostSystemUpgrader,
|
||||
'docker-init': DockerInitializer,
|
||||
'docker': DockerUpgrader,
|
||||
'bootstrap': BootstrapUpgrader,
|
||||
'openstack': OpenStackUpgrader,
|
||||
'targetimages': TargetImagesUpgrader,
|
||||
'raise-error': RaiseErrorUpgrader,
|
||||
}
|
||||
|
||||
|
|
|
@ -27,16 +27,19 @@ Why python based config?
|
|||
and it's hard to create variables nesting more than 1
|
||||
"""
|
||||
|
||||
import six
|
||||
|
||||
import glob
|
||||
import logging
|
||||
import yaml
|
||||
|
||||
from os.path import basename
|
||||
from os.path import exists
|
||||
from os.path import join
|
||||
|
||||
import six
|
||||
import yaml
|
||||
|
||||
from fuel_upgrade.utils import normversion
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -196,19 +199,23 @@ def get_host_system(update_path, new_version):
|
|||
:returns: a host-system upgrade settings
|
||||
"""
|
||||
openstack_versions = glob.glob(
|
||||
join(update_path, 'puppet', '[0-9.-]*{0}'.format(new_version)))
|
||||
join(update_path, 'repos', '[0-9.-]*{0}'.format(new_version)))
|
||||
openstack_versions = [basename(v) for v in openstack_versions]
|
||||
openstack_version = sorted(openstack_versions, reverse=True)[0]
|
||||
centos_repo_path = join(
|
||||
update_path, 'repos', openstack_version, 'centos/x86_64')
|
||||
|
||||
return {
|
||||
'install_packages': [
|
||||
'fuel-release-{0}'.format(normversion(new_version)),
|
||||
],
|
||||
|
||||
'manifest_path': join(
|
||||
update_path, 'puppet', openstack_version,
|
||||
'/etc/puppet', openstack_version,
|
||||
'modules/nailgun/examples/host-upgrade.pp'),
|
||||
|
||||
'puppet_modules_path': join(
|
||||
update_path, 'puppet', openstack_version, 'modules'),
|
||||
'/etc/puppet', openstack_version, 'modules'),
|
||||
|
||||
'repo_config_path': join(
|
||||
'/etc/yum.repos.d',
|
||||
|
@ -291,7 +298,7 @@ def config(update_path, admin_password):
|
|||
image_prefix = 'fuel/'
|
||||
|
||||
# Path to the Docker images to be loaded
|
||||
images = join(update_path, 'images', 'fuel-images.tar')
|
||||
images = '/var/www/nailgun/docker/images/fuel-images.tar'
|
||||
|
||||
# Docker containers description section
|
||||
container_prefix = 'fuel-core-'
|
||||
|
@ -589,71 +596,4 @@ def config(update_path, admin_password):
|
|||
# Config for host system upgarde engine
|
||||
host_system = get_host_system(update_path, new_version)
|
||||
|
||||
# Config for bootstrap upgrade
|
||||
bootstrap = {
|
||||
'actions': [
|
||||
{
|
||||
'name': 'move',
|
||||
'from': '/var/www/nailgun/bootstrap',
|
||||
'to': '/var/www/nailgun/{0}_bootstrap'.format(from_version),
|
||||
# Don't overwrite backup files
|
||||
'overwrite': False,
|
||||
'undo': [
|
||||
{
|
||||
# NOTE(eli): Rollback bootstrap files
|
||||
# with copy, because in 5.0 version
|
||||
# we have volumes linking in container
|
||||
# which doesn't work correctly with symlinks
|
||||
'name': 'copy',
|
||||
'from': '/var/www/nailgun/{0}_bootstrap'.format(
|
||||
from_version),
|
||||
'to': '/var/www/nailgun/bootstrap',
|
||||
'undo': [],
|
||||
'overwrite': True
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'name': 'symlink',
|
||||
'from': '/var/www/nailgun/{0}_bootstrap'.format(from_version),
|
||||
'to': '/var/www/nailgun/bootstrap',
|
||||
'undo': []
|
||||
},
|
||||
{
|
||||
'name': 'copy',
|
||||
'from': join(update_path, 'bootstrap'),
|
||||
'to': '/var/www/nailgun/{0}_bootstrap'.format(new_version),
|
||||
},
|
||||
{
|
||||
'name': 'symlink',
|
||||
'from': '/var/www/nailgun/{0}_bootstrap'.format(new_version),
|
||||
'to': '/var/www/nailgun/bootstrap',
|
||||
'undo': []
|
||||
}
|
||||
]}
|
||||
|
||||
targetimages = {
|
||||
'actions': [
|
||||
{
|
||||
'name': 'copy',
|
||||
'from': join(update_path, 'targetimages'),
|
||||
'to': '/var/www/nailgun/{0}_targetimages'.format(new_version),
|
||||
},
|
||||
{
|
||||
'name': 'symlink',
|
||||
'from': '/var/www/nailgun/{0}_targetimages'.format(
|
||||
new_version),
|
||||
'to': '/var/www/nailgun/targetimages',
|
||||
'undo': [
|
||||
{
|
||||
'name': 'symlink_if_src_exists',
|
||||
'from': '/var/www/nailgun/{0}_targetimages'.format(
|
||||
from_version),
|
||||
'to': '/var/www/nailgun/targetimages'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return locals()
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from fuel_upgrade.actions import ActionManager
|
||||
from fuel_upgrade.engines.base import UpgradeEngine
|
||||
from fuel_upgrade.utils import get_required_size_for_actions
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BootstrapUpgrader(UpgradeEngine):
|
||||
"""Bootstrap Upgrader.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BootstrapUpgrader, self).__init__(*args, **kwargs)
|
||||
|
||||
#: an action manager instance
|
||||
self._action_manager = ActionManager(self.config.bootstrap['actions'])
|
||||
|
||||
def upgrade(self):
|
||||
logger.info('bootstrap upgrader: starting...')
|
||||
|
||||
self._action_manager.do()
|
||||
|
||||
logger.info('bootstrap upgrader: done')
|
||||
|
||||
def rollback(self):
|
||||
logger.info('bootstrap upgrader: rollbacking...')
|
||||
|
||||
self._action_manager.undo()
|
||||
|
||||
logger.info('bootstrap upgrader: rollbacked')
|
||||
|
||||
@property
|
||||
def required_free_space(self):
|
||||
return get_required_size_for_actions(
|
||||
self.config.bootstrap['actions'], self.config.update_path)
|
||||
|
||||
def on_success(self):
|
||||
"""Do nothing for this engine
|
||||
"""
|
|
@ -62,6 +62,9 @@ class HostSystemUpgrader(UpgradeEngine):
|
|||
#: dst repository path
|
||||
self.repo_dst = self.host_system_config['repo_path']['dst']
|
||||
|
||||
#: packages to be installed before running puppet
|
||||
self.packages = self.host_system_config['install_packages']
|
||||
|
||||
@property
|
||||
def required_free_space(self):
|
||||
"""Required free space to run upgrade
|
||||
|
@ -79,6 +82,7 @@ class HostSystemUpgrader(UpgradeEngine):
|
|||
"""
|
||||
self.copy_repo()
|
||||
self.update_repo()
|
||||
self.install_packages()
|
||||
self.run_puppet()
|
||||
|
||||
def rollback(self):
|
||||
|
@ -107,6 +111,13 @@ class HostSystemUpgrader(UpgradeEngine):
|
|||
self.repo_config_path,
|
||||
{'version': self.version,
|
||||
'repo_path': self.repo_dst})
|
||||
utils.exec_cmd('yum clean all')
|
||||
|
||||
def install_packages(self):
|
||||
"""Install packages for new release
|
||||
"""
|
||||
for package in self.packages:
|
||||
utils.exec_cmd('yum install -v -y {0}'.format(package))
|
||||
|
||||
def run_puppet(self):
|
||||
"""Run puppet to upgrade host system
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from fuel_upgrade.actions import ActionManager
|
||||
from fuel_upgrade.engines.base import UpgradeEngine
|
||||
from fuel_upgrade.utils import get_required_size_for_actions
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TargetImagesUpgrader(UpgradeEngine):
|
||||
"""TargetImagesUpgrader.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TargetImagesUpgrader, self).__init__(*args, **kwargs)
|
||||
|
||||
#: an action manager instance
|
||||
self._action_manager = ActionManager(
|
||||
self.config.targetimages['actions'])
|
||||
|
||||
def upgrade(self):
|
||||
logger.info('targetimages upgrader: starting...')
|
||||
|
||||
self._action_manager.do()
|
||||
|
||||
logger.info('targetimages upgrader: done')
|
||||
|
||||
def rollback(self):
|
||||
logger.info('targetimages upgrader: rollbacking...')
|
||||
|
||||
self._action_manager.undo()
|
||||
|
||||
logger.info('targetimages upgrader: rollbacked')
|
||||
|
||||
@property
|
||||
def required_free_space(self):
|
||||
return get_required_size_for_actions(
|
||||
self.config.targetimages['actions'], self.config.update_path)
|
||||
|
||||
def on_success(self):
|
||||
"""Do nothing for this engine
|
||||
"""
|
|
@ -77,10 +77,6 @@ class WrongVersionError(FuelUpgradeException):
|
|||
pass
|
||||
|
||||
|
||||
class UnsupportedActionTypeError(FuelUpgradeException):
|
||||
pass
|
||||
|
||||
|
||||
class NailgunIsNotRunningError(FuelUpgradeException):
|
||||
pass
|
||||
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
|
||||
import mock
|
||||
|
||||
from fuel_upgrade import actions
|
||||
from fuel_upgrade.tests.base import BaseTestCase
|
||||
|
||||
|
||||
class TestActionManager(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.manager = actions.ActionManager([
|
||||
{
|
||||
'name': 'copy',
|
||||
'from': 'from_path',
|
||||
'to': 'to_path',
|
||||
},
|
||||
{
|
||||
'name': 'move',
|
||||
'from': 'from_path',
|
||||
'to': 'to_path',
|
||||
},
|
||||
{
|
||||
'name': 'symlink',
|
||||
'from': 'from_path',
|
||||
'to': 'to_path',
|
||||
}
|
||||
])
|
||||
|
||||
def test_constructor(self):
|
||||
self.assertEqual(len(self.manager._actions), 3)
|
||||
self.assertEqual(len(self.manager._history), 0)
|
||||
|
||||
self.assertTrue(
|
||||
isinstance(self.manager._actions[0], actions.Copy))
|
||||
self.assertTrue(
|
||||
isinstance(self.manager._actions[1], actions.Move))
|
||||
self.assertTrue(
|
||||
isinstance(self.manager._actions[2], actions.Symlink))
|
||||
|
||||
def test_do(self):
|
||||
self.assertEqual(len(self.manager._history), 0)
|
||||
|
||||
for action in self.manager._actions:
|
||||
action.do = mock.Mock()
|
||||
|
||||
self.manager.do()
|
||||
|
||||
for action in self.manager._actions:
|
||||
self.called_once(action.do)
|
||||
|
||||
self.assertEqual(len(self.manager._history), 3)
|
||||
|
||||
def test_undo(self):
|
||||
self.manager._history = self.manager._actions
|
||||
for action in self.manager._history:
|
||||
action.undo = mock.Mock()
|
||||
|
||||
self.manager.undo()
|
||||
|
||||
for action in self.manager._history:
|
||||
self.called_once(action.undo)
|
||||
|
||||
self.assertEqual(len(self.manager._history), 0)
|
||||
|
||||
def test_complex_undo(self):
|
||||
self.action = actions.Copy(**{
|
||||
'from': 'path/to/src',
|
||||
'to': 'path/to/dst',
|
||||
'undo': [
|
||||
{
|
||||
'name': 'move',
|
||||
'from': 'one',
|
||||
'to': 'two',
|
||||
},
|
||||
{
|
||||
'name': 'copy',
|
||||
'from': 'one',
|
||||
'to': 'two',
|
||||
}
|
||||
]
|
||||
})
|
||||
self.assertTrue(
|
||||
isinstance(self.action.undo.__self__, actions.ActionManager))
|
||||
self.assertEqual(len(self.action.undo.im_self._actions), 2)
|
||||
|
||||
mocks = [mock.Mock(), mock.Mock()]
|
||||
self.action.undo.im_self._actions = mocks
|
||||
self.action.undo()
|
||||
|
||||
for action in mocks:
|
||||
self.called_once(action.do)
|
||||
|
||||
|
||||
class TestCopyAction(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.action = actions.Copy(**{
|
||||
'from': 'path/to/src',
|
||||
'to': 'path/to/dst',
|
||||
})
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.copy')
|
||||
def test_do(self, copy):
|
||||
self.action.do()
|
||||
copy.assert_called_once_with('path/to/src', 'path/to/dst', True, True)
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.copy')
|
||||
def test_do_with_overwrite_false(self, copy):
|
||||
self.action._overwrite = False
|
||||
self.action.do()
|
||||
copy.assert_called_once_with('path/to/src', 'path/to/dst', False, True)
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.copy')
|
||||
def test_do_with_symlink_false(self, copy):
|
||||
self.action._symlinks = False
|
||||
self.action.do()
|
||||
copy.assert_called_once_with('path/to/src', 'path/to/dst', True, False)
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.remove')
|
||||
def test_undo(self, remove):
|
||||
self.action.undo()
|
||||
remove.assert_called_once_with('path/to/dst', ignore_errors=True)
|
||||
|
||||
|
||||
class TestMoveAction(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.action = actions.Move(**{
|
||||
'from': 'path/to/src',
|
||||
'to': 'path/to/dst',
|
||||
'overwrite': False
|
||||
})
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.rename')
|
||||
def test_do(self, rename):
|
||||
self.action.do()
|
||||
rename.assert_called_once_with('path/to/src', 'path/to/dst', False)
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.rename')
|
||||
def test_undo(self, rename):
|
||||
self.action.undo()
|
||||
rename.assert_called_once_with('path/to/dst', 'path/to/src', False)
|
||||
|
||||
|
||||
class TestSymlinkAction(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.action = actions.Symlink(**{
|
||||
'from': 'path/to/src',
|
||||
'to': 'path/to/dst',
|
||||
})
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.symlink')
|
||||
def test_do(self, symlink):
|
||||
self.action.do()
|
||||
symlink.assert_called_once_with('path/to/src', 'path/to/dst', True)
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.remove')
|
||||
def test_undo(self, remove):
|
||||
self.action.undo()
|
||||
remove.assert_called_once_with('path/to/dst')
|
||||
|
||||
|
||||
class TestSymlinkIfSrcExistsAction(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.action = actions.SymlinkIfSrcExists(**{
|
||||
'from': 'path/to/src',
|
||||
'to': 'path/to/dst',
|
||||
})
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.symlink_if_src_exists')
|
||||
def test_do(self, symlink):
|
||||
self.action.do()
|
||||
symlink.assert_called_once_with('path/to/src', 'path/to/dst', True)
|
||||
|
||||
@mock.patch('fuel_upgrade.actions.remove')
|
||||
def test_undo(self, remove):
|
||||
self.action.undo()
|
||||
remove.assert_called_once_with('path/to/dst')
|
|
@ -1,50 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from fuel_upgrade.engines.bootstrap import BootstrapUpgrader
|
||||
from fuel_upgrade.tests.base import BaseTestCase
|
||||
|
||||
|
||||
class TestBootstrapUpgrader(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.upgrader = BootstrapUpgrader(self.fake_config)
|
||||
|
||||
def test_constructor(self):
|
||||
self.assertEqual(len(self.upgrader._action_manager._actions), 4)
|
||||
|
||||
def test_upgrade(self):
|
||||
self.upgrader._action_manager.do = mock.Mock()
|
||||
self.upgrader.upgrade()
|
||||
|
||||
self.called_once(self.upgrader._action_manager.do)
|
||||
|
||||
def test_rollback(self):
|
||||
self.upgrader._action_manager.undo = mock.Mock()
|
||||
self.upgrader.rollback()
|
||||
|
||||
self.called_once(self.upgrader._action_manager.undo)
|
||||
|
||||
def test_on_success_does_not_raise_exceptions(self):
|
||||
self.upgrader.on_success()
|
||||
|
||||
@mock.patch('fuel_upgrade.utils.os.path.isdir', return_value=True)
|
||||
@mock.patch('fuel_upgrade.utils.dir_size', return_value=42)
|
||||
def test_required_free_space(self, _, __):
|
||||
result = self.upgrader.required_free_space
|
||||
self.assertEqual(result, {'/var/www/nailgun/9999_bootstrap': 42})
|
|
@ -41,6 +41,8 @@ class TestHostSystemUpgrader(BaseTestCase):
|
|||
'/var/www/nailgun/2014.1.1-5.1/centos/x86_64')
|
||||
self.called_once(run_puppet_mock)
|
||||
self.called_once(update_repo_mock)
|
||||
mock_utils.exec_cmd.assert_called_with(
|
||||
'yum install -v -y fuel-release-9999.0.0')
|
||||
|
||||
@mock.patch('fuel_upgrade.engines.host_system.utils')
|
||||
def test_update_repo(self, utils_mock):
|
||||
|
@ -58,9 +60,9 @@ class TestHostSystemUpgrader(BaseTestCase):
|
|||
self.upgrader.run_puppet()
|
||||
utils_mock.exec_cmd.assert_called_once_with(
|
||||
'puppet apply -d -v '
|
||||
'/tmp/upgrade_path/puppet/2014.1.1-5.1/modules/nailgun/examples'
|
||||
'/etc/puppet/2014.1.1-5.1/modules/nailgun/examples'
|
||||
'/host-upgrade.pp '
|
||||
'--modulepath=/tmp/upgrade_path/puppet/2014.1.1-5.1/modules')
|
||||
'--modulepath=/etc/puppet/2014.1.1-5.1/modules')
|
||||
|
||||
@mock.patch(
|
||||
'fuel_upgrade.engines.host_system.'
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from fuel_upgrade.engines.targetimages import TargetImagesUpgrader
|
||||
from fuel_upgrade.tests.base import BaseTestCase
|
||||
|
||||
|
||||
class TestTargetImagesUpgrader(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.upgrader = TargetImagesUpgrader(self.fake_config)
|
||||
|
||||
def test_constructor(self):
|
||||
self.assertEqual(len(self.upgrader._action_manager._actions), 2)
|
||||
|
||||
def test_upgrade(self):
|
||||
self.upgrader._action_manager.do = mock.Mock()
|
||||
self.upgrader.upgrade()
|
||||
|
||||
self.called_once(self.upgrader._action_manager.do)
|
||||
|
||||
def test_rollback(self):
|
||||
self.upgrader._action_manager.undo = mock.Mock()
|
||||
self.upgrader.rollback()
|
||||
|
||||
self.called_once(self.upgrader._action_manager.undo)
|
||||
|
||||
def test_on_success_does_not_raise_exceptions(self):
|
||||
self.upgrader.on_success()
|
||||
|
||||
@mock.patch('fuel_upgrade.utils.os.path.isdir', return_value=True)
|
||||
@mock.patch('fuel_upgrade.utils.dir_size', return_value=42)
|
||||
def test_required_free_space(self, _, __):
|
||||
result = self.upgrader.required_free_space
|
||||
self.assertEqual(result, {'/var/www/nailgun/9999_targetimages': 42})
|
|
@ -593,6 +593,20 @@ class TestVersionedFile(BaseTestCase):
|
|||
self.versioned_file.sorted_files(),
|
||||
['/tmp/path.ext.10', '/tmp/path.ext.6'])
|
||||
|
||||
def test_normversion(self):
|
||||
cases = [
|
||||
# (input, output)
|
||||
('6', '6.0.0'),
|
||||
('6.0', '6.0.0'),
|
||||
('6.1', '6.1.0'),
|
||||
('6.1.0', '6.1.0'),
|
||||
('6.1.1', '6.1.1'),
|
||||
('6.1.1.1', '6.1.1.1'),
|
||||
]
|
||||
|
||||
for input_, output in cases:
|
||||
self.assertEqual(utils.normversion(input_), output)
|
||||
|
||||
|
||||
class TestSanitizer(BaseTestCase):
|
||||
original = {
|
||||
|
|
|
@ -31,6 +31,7 @@ from copy import deepcopy
|
|||
from distutils.version import StrictVersion
|
||||
|
||||
from mako.template import Template
|
||||
from six.moves import range
|
||||
import yaml
|
||||
|
||||
from fuel_upgrade import errors
|
||||
|
@ -752,6 +753,21 @@ def iterfiles_filter(dir_path, file_pattern):
|
|||
yield file_path
|
||||
|
||||
|
||||
def normversion(version):
|
||||
"""Normalize a given version to have exactly three components.
|
||||
|
||||
:param version: a version to be normalized
|
||||
:returns: a normalized version
|
||||
"""
|
||||
components = version.split('.')
|
||||
|
||||
if len(components) < 3:
|
||||
for _ in range(0, 3 - len(components)):
|
||||
components.append('0')
|
||||
|
||||
return '.'.join(components)
|
||||
|
||||
|
||||
class VersionedFile(object):
|
||||
"""Set of methods for versioned files.
|
||||
If `basename` is '/tmp/file.ext' it allows
|
||||
|
|
Loading…
Reference in New Issue