fuel-octane/octane/commands/upgrade_db.py

138 lines
5.0 KiB
Python

# 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
import os.path
import shutil
import time
from cliff import command as cmd
from fuelclient.objects import environment as environment_obj
from octane import magic_consts
from octane.util import db
from octane.util import deployment as deploy
from octane.util import env as env_util
from octane.util import maintenance
LOG = logging.getLogger(__name__)
def upgrade_db(orig_id, seed_id, db_role_name):
orig_env = environment_obj.Environment(orig_id)
seed_env = environment_obj.Environment(seed_id)
env_util.delete_fuel_resources(seed_env)
# Wait for Neutron to reconfigure networks
time.sleep(7) # FIXME: Use more deterministic way
if db.does_perform_flavor_data_migration(orig_env):
db.nova_migrate_flavor_data(orig_env)
maintenance.disable_apis(orig_env)
maintenance.stop_corosync_services(seed_env)
maintenance.stop_upstart_services(seed_env)
expected_dbs = set(magic_consts.OS_SERVICES)
existing_dbs = set(db.get_databases(orig_env))
dbs = existing_dbs & expected_dbs
if len(dbs) < len(magic_consts.OS_SERVICES):
LOG.info('Skipping nonexistent tables: %s',
', '.join(expected_dbs - existing_dbs))
LOG.info('Will dump tables: %s', ', '.join(dbs))
fname = os.path.join(magic_consts.FUEL_CACHE, 'dbs.original.sql.gz')
db.mysqldump_from_env(orig_env, db_role_name, dbs, fname)
fname2 = os.path.join(
magic_consts.FUEL_CACHE,
'dbs.original.cluster_%s.sql.gz' % (orig_env.data['id'],),
)
shutil.copy(fname, fname2)
db.mysqldump_restore_to_env(seed_env, db_role_name, fname)
db.db_sync(seed_env)
if db.does_perform_cinder_volume_update_host(orig_env):
db.cinder_volume_update_host(orig_env, seed_env)
def add_upgrade_attrs_to_settings(orig_env, seed_env):
upgrade_hash = {
'relation_info': {
'orig_cluster_version': orig_env.data['fuel_version'],
'seed_cluster_version': seed_env.data['fuel_version']
}
}
orig_attrs = orig_env.get_settings_data()
orig_upgrade = orig_attrs['editable']['common'].get('upgrade', {})
orig_upgrade.update(upgrade_hash)
orig_attrs['editable']['common']['upgrade'] = orig_upgrade
orig_env.set_settings_data(orig_attrs)
seed_attrs = seed_env.get_settings_data()
seed_upgrade = seed_attrs['editable']['common'].get('upgrade', {})
seed_upgrade.update(upgrade_hash)
seed_attrs['editable']['common']['upgrade'] = seed_upgrade
seed_env.set_settings_data(seed_attrs)
def upgrade_db_with_graph(orig_id, seed_id):
"""Upgrade db using deployment graphs."""
orig_env = environment_obj.Environment(orig_id)
seed_env = environment_obj.Environment(seed_id)
add_upgrade_attrs_to_settings(orig_env, seed_env)
# Upload all graphs
deploy.upload_graphs(orig_id, seed_id)
# If any failure try to rollback ONLY original environment.
try:
deploy.execute_graph_and_wait("upgrade-db", orig_id)
deploy.execute_graph_and_wait("upgrade-db", seed_id)
except Exception:
cluster_graphs = deploy.get_cluster_graph_names(orig_id)
if "upgrade-db-rollback" in cluster_graphs:
LOG.info("Trying to rollback 'upgrade-db' on the "
"orig environment '%s'.", orig_id)
deploy.execute_graph_and_wait("upgrade-db-rollback", orig_id)
raise
class UpgradeDBCommand(cmd.Command):
"""Migrate and upgrade state databases data"""
def get_parser(self, prog_name):
parser = super(UpgradeDBCommand, self).get_parser(prog_name)
parser.add_argument(
'orig_id', type=int, metavar='ORIG_ID',
help="ID of original environment")
parser.add_argument(
'seed_id', type=int, metavar='SEED_ID',
help="ID of seed environment")
group = parser.add_argument_group()
group.add_argument(
'--db_role_name', type=str, metavar='DB_ROLE_NAME',
default="controller", help="Set not standard role name for DB "
"(default controller).")
group.add_argument(
'--without-graph', action='store_true',
help="Use python-based commands"
" instead of Fuel deployment graphs.")
return parser
def take_action(self, parsed_args):
if parsed_args.without_graph:
upgrade_db(parsed_args.orig_id, parsed_args.seed_id,
parsed_args.db_role_name)
else:
upgrade_db_with_graph(parsed_args.orig_id, parsed_args.seed_id)