773b199ae7
No need to import print_function from __future__ Change-Id: I1e07fdb667935feacf84270871cb9677b0deae4c
126 lines
4.3 KiB
Python
126 lines
4.3 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.
|
|
|
|
"""Migrate introspected data between Swift and database."""
|
|
|
|
import sys
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log
|
|
from oslo_utils import encodeutils
|
|
|
|
from ironic_inspector.common.i18n import _
|
|
from ironic_inspector.conf import opts
|
|
from ironic_inspector import node_cache
|
|
from ironic_inspector.plugins import base as plugins_base
|
|
from ironic_inspector import utils
|
|
|
|
LOG = log.getLogger(__name__)
|
|
CONF = cfg.CONF
|
|
|
|
_AVAILABLE_STORAGES = [('database', _('The database storage backend')),
|
|
('swift', _('The Swift storage backend'))]
|
|
_OPTS = [
|
|
cfg.StrOpt('from',
|
|
dest='source_storage',
|
|
required=True,
|
|
choices=_AVAILABLE_STORAGES,
|
|
help=_('The source storage where the introspected data will be '
|
|
'read from.')),
|
|
cfg.StrOpt('to',
|
|
dest='target_storage',
|
|
required=True,
|
|
choices=_AVAILABLE_STORAGES,
|
|
help=_('The target storage where the introspected data will be '
|
|
'saved to.'))
|
|
]
|
|
|
|
# Migration result
|
|
RESULT_NOCONTENT = 'no content'
|
|
RESULT_FAILED = 'failed'
|
|
RESULT_SUCCESS = 'success'
|
|
|
|
|
|
def _setup_logger(args=None):
|
|
args = [] if args is None else args
|
|
log.register_options(CONF)
|
|
opts.set_config_defaults()
|
|
opts.parse_args(args)
|
|
log.setup(CONF, 'ironic_inspector')
|
|
|
|
|
|
class MigrationTool(object):
|
|
|
|
def _migrate_one(self, node, processed):
|
|
LOG.debug('Starting to migrate introspection data for node '
|
|
'%(node)s (processed %(processed)s)',
|
|
{'node': node.uuid, 'processed': processed})
|
|
try:
|
|
data = self.ext_src.get(node.uuid, processed=processed,
|
|
get_json=True)
|
|
if not data:
|
|
return RESULT_NOCONTENT
|
|
self.ext_tgt.save(node.uuid, data, processed=processed)
|
|
except Exception as e:
|
|
LOG.error('Migrate introspection data failed for node '
|
|
'%(node)s (processed %(processed)s), error: '
|
|
'%(error)s', {'node': node.uuid, 'processed': processed,
|
|
'error': e})
|
|
return RESULT_FAILED
|
|
|
|
return RESULT_SUCCESS
|
|
|
|
def main(self):
|
|
CONF.register_cli_opts(_OPTS)
|
|
_setup_logger(sys.argv[1:])
|
|
|
|
if CONF.source_storage == CONF.target_storage:
|
|
raise utils.Error(_('Source and destination can not be the same.'))
|
|
|
|
introspection_data_manager = plugins_base.introspection_data_manager()
|
|
self.ext_src = introspection_data_manager[CONF.source_storage].obj
|
|
self.ext_tgt = introspection_data_manager[CONF.target_storage].obj
|
|
|
|
nodes = node_cache.get_node_list()
|
|
migration_list = [(n, p) for n in nodes for p in [True, False]]
|
|
failed_records = []
|
|
for node, processed in migration_list:
|
|
result = self._migrate_one(node, processed)
|
|
if result == RESULT_FAILED:
|
|
failed_records.append((node.uuid, processed))
|
|
|
|
msg = ('Finished introspection data migration, total records: %d. '
|
|
% len(migration_list))
|
|
if failed_records:
|
|
msg += 'Failed to migrate:\n' + '\n'.join([
|
|
'%s(processed=%s)' % (record[0], record[1])
|
|
for record in failed_records])
|
|
elif len(migration_list) > 0:
|
|
msg += 'all records are migrated successfully.'
|
|
print(msg)
|
|
|
|
|
|
def main():
|
|
|
|
try:
|
|
MigrationTool().main()
|
|
except KeyboardInterrupt:
|
|
print(_("... terminating migration tool"), file=sys.stderr)
|
|
return 130
|
|
except Exception as e:
|
|
print(encodeutils.safe_encode(str(e)), file=sys.stderr)
|
|
return 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|