# Copyright 2014 Dell 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.

"""
Utility for cleaning up environment after Tempest test run

**Usage:** ``tempest cleanup [--help] [OPTIONS]``

If run with no arguments, ``tempest cleanup`` will query your OpenStack
deployment and build a list of resources to delete and destroy them. This list
will exclude the resources from ``saved_state.json`` and will include the
configured admin account if the ``--delete-tempest-conf-objects`` flag is
specified. By default the admin project is not deleted and the admin user
specified in ``tempest.conf`` is never deleted.

Example Run
-----------

.. warning::

    If step 1 is skipped in the example below, the cleanup procedure
    may delete resources that existed in the cloud before the test run. This
    may cause an unwanted destruction of cloud resources, so use caution with
    this command.

    Examples::

     $ tempest cleanup --init-saved-state
     $ # Actual running of Tempest tests
     $ tempest cleanup

Runtime Arguments
-----------------

* ``--init-saved-state``: Initializes the saved state of the OpenStack
  deployment and will output a ``saved_state.json`` file containing resources
  from your deployment that will be preserved from the cleanup command. This
  should be done prior to running Tempest tests.

* ``--delete-tempest-conf-objects``: If option is present, then the command
  will delete the admin project in addition to the resources associated with
  them on clean up. If option is not present, the command will delete the
  resources associated with the Tempest and alternate Tempest users and
  projects but will not delete the projects themselves.

* ``--dry-run``: Creates a report (``./dry_run.json``) of the projects that
  will be cleaned up (in the ``_projects_to_clean`` dictionary [1]_) and the
  global objects that will be removed (domains, flavors, images, roles,
  projects, and users). Once the cleanup command is executed (e.g. run without
  parameters), running it again with ``--dry-run`` should yield an empty
  report.

* ``--help``: Print the help text for the command and parameters.

.. [1] The ``_projects_to_clean`` dictionary in ``dry_run.json`` lists the
    projects that ``tempest cleanup`` will loop through to delete child
    objects, but the command will, by default, not delete the projects
    themselves. This may differ from the ``projects`` list as you can clean
    the Tempest and alternate Tempest users and projects but they will not be
    deleted unless the ``--delete-tempest-conf-objects`` flag is used to
    force their deletion.

.. note::

    If during execution of ``tempest cleanup`` NotImplemented exception
    occurres, ``tempest cleanup`` won't fail on that, it will be logged only.
    NotImplemented errors are ignored because they are an outcome of some
    extensions being disabled and ``tempest cleanup`` is not checking their
    availability as it tries to clean up as much as possible without any
    complicated logic.

"""
import sys
import traceback

from cliff import command
from oslo_log import log as logging
from oslo_serialization import jsonutils as json

from tempest import clients
from tempest.cmd import cleanup_service
from tempest.common import credentials_factory as credentials
from tempest.common import identity
from tempest import config
from tempest.lib import exceptions

SAVED_STATE_JSON = "saved_state.json"
DRY_RUN_JSON = "dry_run.json"
LOG = logging.getLogger(__name__)
CONF = config.CONF


class TempestCleanup(command.Command):

    GOT_EXCEPTIONS = []

    def take_action(self, parsed_args):
        try:
            self.init(parsed_args)
            if not parsed_args.init_saved_state:
                self._cleanup()
        except Exception:
            LOG.exception("Failure during cleanup")
            traceback.print_exc()
            raise
        # ignore NotImplemented errors as those are an outcome of some
        # extensions being disabled and cleanup is not checking their
        # availability as it tries to clean up as much as possible without
        # any complicated logic
        critical_exceptions = [ex for ex in self.GOT_EXCEPTIONS if
                               not isinstance(ex, exceptions.NotImplemented)]
        if critical_exceptions:
            raise Exception(self.GOT_EXCEPTIONS)

    def init(self, parsed_args):
        cleanup_service.init_conf()
        self.options = parsed_args
        self.admin_mgr = clients.Manager(
            credentials.get_configured_admin_credentials())
        self.dry_run_data = {}
        self.json_data = {}

        self.admin_id = ""
        self.admin_role_id = ""
        self.admin_project_id = ""
        self._init_admin_ids()

        # available services
        self.project_associated_services = (
            cleanup_service.get_project_associated_cleanup_services())
        self.resource_cleanup_services = (
            cleanup_service.get_resource_cleanup_services())
        self.global_services = cleanup_service.get_global_cleanup_services()

        if parsed_args.init_saved_state:
            self._init_state()
            return

        self._load_json()

    def _cleanup(self):
        print("Begin cleanup")
        is_dry_run = self.options.dry_run
        is_preserve = not self.options.delete_tempest_conf_objects
        is_save_state = False

        if is_dry_run:
            self.dry_run_data["_projects_to_clean"] = {}

        admin_mgr = self.admin_mgr
        # Always cleanup tempest and alt tempest projects unless
        # they are in saved state json. Therefore is_preserve is False
        kwargs = {'data': self.dry_run_data,
                  'is_dry_run': is_dry_run,
                  'saved_state_json': self.json_data,
                  'is_preserve': False,
                  'is_save_state': is_save_state}
        project_service = cleanup_service.ProjectService(admin_mgr, **kwargs)
        projects = project_service.list()
        print("Process %s projects" % len(projects))

        # Loop through list of projects and clean them up.
        for project in projects:
            self._clean_project(project)

        kwargs = {'data': self.dry_run_data,
                  'is_dry_run': is_dry_run,
                  'saved_state_json': self.json_data,
                  'is_preserve': is_preserve,
                  'is_save_state': is_save_state,
                  'got_exceptions': self.GOT_EXCEPTIONS}
        for service in self.global_services:
            svc = service(admin_mgr, **kwargs)
            svc.run()

        for service in self.resource_cleanup_services:
            svc = service(self.admin_mgr, **kwargs)
            svc.run()

        if is_dry_run:
            with open(DRY_RUN_JSON, 'w+') as f:
                f.write(json.dumps(self.dry_run_data, sort_keys=True,
                                   indent=2, separators=(',', ': ')))

    def _clean_project(self, project):
        print("Cleaning project:  %s " % project['name'])
        is_dry_run = self.options.dry_run
        dry_run_data = self.dry_run_data
        is_preserve = not self.options.delete_tempest_conf_objects
        project_id = project['id']
        project_name = project['name']
        project_data = None
        if is_dry_run:
            project_data = dry_run_data["_projects_to_clean"][project_id] = {}
            project_data['name'] = project_name

        kwargs = {'data': project_data,
                  'is_dry_run': is_dry_run,
                  'saved_state_json': self.json_data,
                  'is_preserve': is_preserve,
                  'is_save_state': False,
                  'project_id': project_id,
                  'got_exceptions': self.GOT_EXCEPTIONS}
        for service in self.project_associated_services:
            svc = service(self.admin_mgr, **kwargs)
            svc.run()

    def _init_admin_ids(self):
        pr_cl = self.admin_mgr.projects_client
        rl_cl = self.admin_mgr.roles_v3_client
        rla_cl = self.admin_mgr.role_assignments_client
        us_cl = self.admin_mgr.users_v3_client

        project = identity.get_project_by_name(pr_cl,
                                               CONF.auth.admin_project_name)
        self.admin_project_id = project['id']
        user = identity.get_user_by_project(us_cl, rla_cl,
                                            self.admin_project_id,
                                            CONF.auth.admin_username)
        self.admin_id = user['id']

        roles = rl_cl.list_roles()['roles']
        for role in roles:
            if role['name'] == CONF.identity.admin_role:
                self.admin_role_id = role['id']
                break

    def get_parser(self, prog_name):
        parser = super(TempestCleanup, self).get_parser(prog_name)
        parser.add_argument('--init-saved-state', action="store_true",
                            dest='init_saved_state', default=False,
                            help="Creates JSON file: " + SAVED_STATE_JSON +
                            ", representing the current state of your "
                            "deployment,  specifically object types "
                            "tempest creates and destroys during a run. "
                            "You must run with this flag prior to "
                            "executing cleanup in normal mode, which is with "
                            "no arguments.")
        parser.add_argument('--delete-tempest-conf-objects',
                            action="store_true",
                            dest='delete_tempest_conf_objects',
                            default=False,
                            help="Force deletion of the tempest and "
                            "alternate tempest users and projects.")
        parser.add_argument('--dry-run', action="store_true",
                            dest='dry_run', default=False,
                            help="Generate JSON file:" + DRY_RUN_JSON +
                            ", that reports the objects that would have "
                            "been deleted had a full cleanup been run.")
        return parser

    def get_description(self):
        return 'Cleanup after tempest run'

    def _init_state(self):
        print("Initializing saved state.")
        data = {}
        admin_mgr = self.admin_mgr
        kwargs = {'data': data,
                  'is_dry_run': False,
                  'saved_state_json': data,
                  'is_preserve': False,
                  'is_save_state': True,
                  'got_exceptions': self.GOT_EXCEPTIONS}
        for service in self.global_services:
            svc = service(admin_mgr, **kwargs)
            svc.run()

        for service in self.project_associated_services:
            svc = service(admin_mgr, **kwargs)
            svc.run()

        for service in self.resource_cleanup_services:
            svc = service(admin_mgr, **kwargs)
            svc.run()

        with open(SAVED_STATE_JSON, 'w+') as f:
            f.write(json.dumps(data, sort_keys=True,
                               indent=2, separators=(',', ': ')))

    def _load_json(self, saved_state_json=SAVED_STATE_JSON):
        try:
            with open(saved_state_json, 'rb') as json_file:
                self.json_data = json.load(json_file)

        except IOError as ex:
            LOG.exception("Failed loading saved state, please be sure you"
                          " have first run cleanup with --init-saved-state "
                          "flag prior to running tempest. Exception: %s", ex)
            sys.exit(ex)
        except Exception as ex:
            LOG.exception("Exception parsing saved state json : %s", ex)
            sys.exit(ex)
