Python django.core.management.base.BaseCommand() Examples

The following are 29 code examples of django.core.management.base.BaseCommand(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module django.core.management.base , or try the search function .
Example #1
Source File: scale_message_handler.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the command.
        """

        logger.info('Command starting: scale_message_handler')

        self.running = True

        logger.info('Initializing message handler')
        logger.info('Caching builtin errors...')
        Error.objects.cache_builtin_errors()
        logger.info('Initialization complete, ready to process messages')
        
        # Set the signal handler
        signal.signal(signal.SIGINT, self.interupt)
        signal.signal(signal.SIGTERM, self.interupt)

        manager = CommandMessageManager()

        while self.running:
            manager.receive_messages()

        logger.info('Command completed: scale_message_handler') 
Example #2
Source File: edit_named_options.py    From maas with GNU Affero General Public License v3.0 6 votes vote down vote up
def handle(self, *args, **options):
        """Entry point for BaseCommand."""
        config_path = options.get("config_path")
        dry_run = options.get("dry_run")
        force = options.get("force")
        stdout = options.get("stdout")
        if stdout is None:
            stdout = sys.stdout

        def options_handler(options_block):
            self.migrate_forwarders(options_block, dry_run, stdout)
            self.migrate_dnssec_validation(options_block, dry_run, stdout)

        try:
            edit_options(config_path, stdout, dry_run, force, options_handler)
        except ValueError as exc:
            raise CommandError(str(exc)) from None 
Example #3
Source File: scale_roulette.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.
        """

        logger.info('Spinning roulette wheel...')
        time.sleep(1)  # One second
        random.seed()
        result = random.randint(0, 1)

        try:
            if result:
                logger.info('Landed on black')
            else:
                logger.error('Landed on red')
                raise TestException()
        except ScaleError as err:
            sys.exit(err.exit_code) 
Example #4
Source File: scale_move_file.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the file move process.
        """

        logger.info('Command starting: scale_move_file')

        file_id = options.get('file_id')
        remote_path = options.get('remote_path')
        
        # Attempt to fetch the file model
        try:
            scale_file = ScaleFile.objects.get(pk=file_id)
        except ScaleFile.DoesNotExist:
            logger.exception('Stored file does not exist: %s', file_id)
            sys.exit(1)

        try:
            ScaleFile.objects.move_files([FileMove(scale_file, remote_path)])
        except:
            logger.exception('Unknown error occurred, exit code 1 returning')
            sys.exit(1)
        logger.info('Command completed: scale_move_file') 
Example #5
Source File: scale_delete_file.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the file delete process.
        """

        logger.info('Command starting: scale_delete_file')

        file_id = options.get('file_id')

        # Attempt to fetch the file model
        try:
            scale_file = ScaleFile.objects.get(pk=file_id)
        except ScaleFile.DoesNotExist:
            logger.exception('Stored file does not exist: %s', file_id)
            sys.exit(1)

        try:
            ScaleFile.objects.delete_files([scale_file])
        except:
            logger.exception('Unknown error occurred, exit code 1 returning')
            sys.exit(1)
        logger.info('Command completed: scale_delete_file') 
Example #6
Source File: scale_send_message.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the command.
        """

        body = options.get('body')
        type = options.get('type')
        count = options.get('count')
        if not count:
            count = 1

        logger.info('Command starting: scale_send_message')

        Message = get_message_type(type)

        manager = CommandMessageManager()
        messages = [Message.from_json(body) for _ in range(count)]
        manager.send_messages(messages)

        logger.info('Command completed: scale_send_message') 
Example #7
Source File: scale_echo_message.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the command.
        """

        count = options.get('count')
        if not count:
            count = 1

        logger.info('Command starting: scale_echo_message - sending {} message(s)'.format(count))

        manager = CommandMessageManager()
        messages = []
        for x in range(count):
            messages.append(EchoCommandMessage.from_json(
                {'message': 'Greetings, this is echo #{} at {}!'.format(x + 1, datetime.utcnow())}))
                
        
        manager.send_messages(messages)

        logger.info('Command completed: scale_echo_message') 
Example #8
Source File: scale_scheduler.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the scheduler.
        """

        # Register a listener to handle clean shutdowns
        signal.signal(signal.SIGTERM, self._onsigterm)

        # Set up global shutdown
        global GLOBAL_SHUTDOWN
        GLOBAL_SHUTDOWN = self._shutdown

        logger.info('Scale Scheduler %s', settings.VERSION)

        self.run_scheduler(settings.MESOS_MASTER) 
Example #9
Source File: scale_batch_creator.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the Scale batch creation process.
        """

        batch_id = options.get('batch_id')

        logger.info('Command starting: scale_batch_creator - Batch ID: %i', batch_id)

        # Schedule all the batch recipes
        try:
            batch = Batch.objects.get(id=batch_id)
            CommandMessageManager().send_messages([create_batch_recipes_message(batch_id)])
        except Batch.DoesNotExist:
            logger.exception('Unable to find batch: %i', batch_id)
            sys.exit(1)

        logger.info('Command completed: scale_batch_creator') 
Example #10
Source File: __init__.py    From django-tenants with MIT License 6 votes vote down vote up
def __new__(cls, *args, **kwargs):
        """
        Sets option_list and help dynamically.
        """
        obj = super().__new__(cls, *args, **kwargs)

        app_name = get_commands()[obj.COMMAND_NAME]
        if isinstance(app_name, BaseCommand):
            # If the command is already loaded, use it directly.
            cmdclass = app_name
        else:
            cmdclass = load_command_class(app_name, obj.COMMAND_NAME)

        # prepend the command's original help with the info about schemata iteration
        obj.help = "Calls %s for all registered schemata. You can use regular %s options. " \
                   "Original help for %s: %s" % (obj.COMMAND_NAME, obj.COMMAND_NAME, obj.COMMAND_NAME,
                                                 getattr(cmdclass, 'help', 'none'))
        return obj 
Example #11
Source File: scale_superuser.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.
        """

        new_password = options.get('password')

        try:
            user = User.objects.get(username='admin')
            if options.get('force'):
                user.first_name = 'Admin'
                user.last_name = 'User'
                user.set_password(new_password)
                user.save()
            else:
                user = None
                print('Existing admin user password left unchanged. Use --force flag to reset.')
        except User.DoesNotExist:
            user = User.objects.create_superuser(username='admin', first_name='Admin', last_name='User', email='',
                                                 password=new_password)

        if user:
            print('Superuser admin password: %s' % (new_password,)) 
Example #12
Source File: scale_ingest.py    From scale with Apache License 2.0 6 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the ingest process.
        """

        # Register a listener to handle clean shutdowns
        signal.signal(signal.SIGTERM, self._onsigterm)

        ingest_id = options.get('ingest_id')

        logger.info('Command starting: scale_ingest')
        logger.info('Ingest ID: %i', ingest_id)
        try:
            ingest_job.perform_ingest(ingest_id)
        except:
            logger.exception('Ingest caught unexpected error, exit code 1 returning')
            sys.exit(1)
        logger.info('Command completed: scale_ingest') 
Example #13
Source File: scale_download_file.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the file download process.
        """

        logger.info('Command starting: scale_download_file')
        
        file_id = options.get('file_id')
        local_path = options.get('local_path')

        # Validate the file paths
        if os.path.exists(local_path):
            logger.exception('Local file already exists: %s', local_path)
            sys.exit(1)

        # Attempt to fetch the file model
        try:
            scale_file = ScaleFile.objects.get(pk=file_id)
        except ScaleFile.DoesNotExist:
            logger.exception('Stored file does not exist: %s', file_id)
            sys.exit(1)

        try:
            ScaleFile.objects.download_files([FileDownload(scale_file, local_path)])
        except:
            logger.exception('Unknown error occurred, exit code 1 returning')
            sys.exit(1)
        logger.info('Command completed: scale_download_file') 
Example #14
Source File: base_command.py    From djongo with GNU Affero General Public License v3.0 5 votes vote down vote up
def handle(self, *labels, **options):
        print('EXECUTE:BaseCommand labels=%s, options=%s' % (labels, sorted(options.items()))) 
Example #15
Source File: mixins.py    From django-mmc with GNU General Public License v2.0 5 votes vote down vote up
def inject_management():
    monkey_mix(BaseCommandOrigin, BaseCommandMixin) 
Example #16
Source File: tenant_command.py    From django-tenants with MIT License 5 votes vote down vote up
def run_from_argv(self, argv):
        """
        Changes the option_list to use the options from the wrapped command.
        Adds schema parameter to specify which schema will be used when
        executing the wrapped command.
        """
        # load the command object.
        if len(argv) <= 2:
            return

        try:
            app_name = get_commands()[argv[2]]
        except KeyError:
            raise CommandError("Unknown command: %r" % argv[2])

        if isinstance(app_name, BaseCommand):
            # if the command is already loaded, use it directly.
            klass = app_name
        else:
            klass = load_command_class(app_name, argv[2])

        # Ugly, but works. Delete tenant_command from the argv, parse the schema manually
        # and forward the rest of the arguments to the actual command being wrapped.
        del argv[1]
        schema_parser = argparse.ArgumentParser()
        schema_parser.add_argument("-s", "--schema", dest="schema_name", help="specify tenant schema")
        schema_namespace, args = schema_parser.parse_known_args(argv)

        tenant = self.get_tenant_from_options_or_interactive(schema_name=schema_namespace.schema_name)
        connection.set_tenant(tenant)
        klass.run_from_argv(args) 
Example #17
Source File: scale_hello.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.
        """

        print('Hello Scale! (stderr)', file=sys.stderr)
        print('Hello Scale! (stdout)', file=sys.stdout) 
Example #18
Source File: scale_bake.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.
        """

        logger.info('Cookies are in the oven, setting the timer for 15 minutes...')
        time.sleep(FIFTEEN_MIN)
        logger.info('DING! Cookies are done.') 
Example #19
Source File: all_tenants_command.py    From django-tenants with MIT License 5 votes vote down vote up
def run_from_argv(self, argv):
        """
        Changes the option_list to use the options from the wrapped command.
        """
        # load the command object.
        if len(argv) <= 2:
            return
        try:
            app_name = get_commands()[argv[2]]
        except KeyError:
            raise CommandError("Unknown command: %r" % argv[2])

        if isinstance(app_name, BaseCommand):
            # if the command is already loaded, use it directly.
            klass = app_name
        else:
            klass = load_command_class(app_name, argv[2])

        # Ugly, but works. Delete tenant_command from the argv, parse the schema manually
        # and forward the rest of the arguments to the actual command being wrapped.
        del argv[1]
        schema_parser = argparse.ArgumentParser()
        schema_namespace, args = schema_parser.parse_known_args(argv)
        print(args)

        tenant_model = get_tenant_model()
        tenants = tenant_model.objects.all()
        for tenant in tenants:
            self.stdout.write("Applying command to: %s" % tenant.schema_name)
            connection.set_tenant(tenant)
            klass.run_from_argv(args) 
Example #20
Source File: scale_delete_files.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the file destruction process.
        """

        # Register a listener to handle clean shutdowns
        signal.signal(signal.SIGTERM, self._onsigterm)

        files_list = json.loads(os.environ.get('FILES'))
        workspaces_list = json.loads(os.environ.get('WORKSPACES'))
        job_id = int(os.environ.get('JOB_ID'))
        trigger_id = int(os.environ.get('TRIGGER_ID'))
        source_file_id = int(os.environ.get('SOURCE_FILE_ID'))
        purge = os.environ.get('PURGE', 'true').lower() in ('yes', 'true', 't', '1')

        workspaces = self._configure_workspaces(workspaces_list)
        files = self._configure_files(files_list, workspaces)

        logger.info('Command starting: scale_delete_files')
        logger.info('File IDs: %s', [x.id for x in files])

        for wrkspc_name, wrkspc in workspaces.iteritems():
            delete_files_job.delete_files(files=[f for f in files if f.workspace == wrkspc_name],
                                          broker=wrkspc['broker'], volume_path=wrkspc['volume_path'])

        messages = create_delete_files_messages(files=files, job_id=job_id, trigger_id=trigger_id,
                                                source_file_id=source_file_id, purge=purge)
        CommandMessageManager().send_messages(messages)

        logger.info('Command completed: scale_delete_files')

        sys.exit(0) 
Example #21
Source File: scale_list_files.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method will list the entire contents of a workspace.
        """

        logger.info('Command starting: scale_list_files')

        if 'workspace_id' in options:
            workspace_id = options['workspace_id']
        else:
            logger.error('Workspace ID must be specified.')
            sys.exit(1)

        # Attempt to fetch the workspace model by workspace id
        try:
            workspace = Workspace.objects.get(pk=workspace_id)
        except Workspace.DoesNotExist:
            logger.exception('Workspace does not exist: %s', workspace_id)
            sys.exit(1)

        try:
            conf = workspace.json_config
            # Patch _get_volume_path for local testing outside of docker.
            # This is useful for testing when Scale isn't managing mounts.
            if options['local'] and 'broker' in conf and 'host_path' in conf['broker']:
                with patch.object(Workspace, '_get_volume_path',
                                  return_value=conf['broker']['host_path']) as mock_method:
                    results = workspace.list_files(options['recursive'])
            else:
                results = workspace.list_files(options['recursive'])
                
            for result in results:
                logger.info(file)
        except:
            logger.exception('Unknown error occurred, exit code 1 returning')
            sys.exit(1)
        logger.info('Command completed: scale_list_files') 
Example #22
Source File: scale_move_files.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the file move process.
        """

        logger.info('Command starting: scale_move_files')
        # Register a listener to handle clean shutdowns
        signal.signal(signal.SIGTERM, self._onsigterm)

        file_ids = json.loads(os.environ.get('FILE_IDS'))
        new_workspace_name = json.loads(os.environ.get('NEW_WORKSPACE'))
        uri = json.loads(os.environ.get('NEW_PATH'))

        new_workspace = None
        if new_workspace_name:
            try:
                new_workspace = Workspace.objects.get(name=new_workspace_name)
            except Workspace.DoesNotExist:
                logger.error('Error running command scale_move_files: Workspace %s does not exist' % new_workspace_name)
                sys.exit(1)

        logger.info('Command starting: scale_move_files')
        logger.info('File IDs: %s', file_ids)
        
        move_files_job.move_files(file_ids=file_ids, new_workspace=new_workspace, new_file_path=uri)

        logger.info('Command completed: scale_move_files')

        sys.exit(0) 
Example #23
Source File: scale_clock.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the Scale clock.
        """
        self.running = True

        # Register a listener to handle clean shutdowns
        signal.signal(signal.SIGTERM, self._onsigterm)

        logger.info('Command starting: scale_clock')
        while self.running:
            secs_passed = 0
            try:
                if not self.job_id:
                    self._init_clock()
                else:
                    self._check_clock()

                started = now()
                clock.perform_tick()
                ended = now()

                secs_passed = (ended - started).total_seconds()
            except:
                logger.exception('Clock encountered error')
            finally:
                if self.running:
                    # If process time takes less than throttle time, throttle
                    if secs_passed < self.throttle:
                        # Delay until full throttle time reached
                        delay = math.ceil(self.throttle - secs_passed)
                        logger.debug('Pausing for %i seconds', delay)
                        time.sleep(delay)
        logger.info('Command completed: scale_clock')

        # Clock never successfully finishes, it should always run
        sys.exit(1) 
Example #24
Source File: django_micro.py    From django-micro with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def command(name=None, command_cls=None):
    if not getattr(management.get_commands, 'patched', False):
        _patch_get_commands()

    if inspect.isfunction(name):
        # Shift arguments if decroator called without brackets
        command_cls = name
        name = None

    def decorator(command_cls):
        command_name = name

        if inspect.isclass(command_cls):
            command_instance = command_cls()
        else:
            # transform function-based command to class
            command_name = name or command_cls.__name__
            command_instance = type('Command', (BaseCommand,), {'handle': command_cls})()

        if not command_name:
            raise DjangoMicroException("Class-based commands requires name argument.")

        # Hack for extracting app name from command (https://goo.gl/1c1Irj)
        command_instance.rpartition = lambda x: [_app_config.module]

        _commands[command_name] = command_instance
        return command_cls

    # allow use decorator directly
    # command('print_hello', PrintHelloCommand)
    if command_cls:
        return decorator(command_cls)

    return decorator 
Example #25
Source File: load_all_data.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method loads all of the fixtures into the database.
        """
        logger.info('Command starting: load_all_data')
        fixture_names = []
        manage_path = os.path.join(settings.BASE_DIR, 'manage.py')

        for app_dir in os.listdir(settings.BASE_DIR):
            app_dir_path = os.path.join(settings.BASE_DIR, app_dir)
            if not os.path.isdir(app_dir_path):
                continue
            sub_dirs = os.listdir(app_dir_path)
            if 'fixtures' in sub_dirs:
                fixture_dir_path = os.path.join(app_dir_path, 'fixtures')
                for entry in os.listdir(fixture_dir_path):
                    if os.path.isfile(os.path.join(fixture_dir_path, entry)):
                        if entry.endswith('.json'):
                            logger.info('Discovered: %s -> %s', app_dir, entry)
                            fixture_names.append(entry)

        for name in fixture_names:
            cmd_list = [manage_path, 'loaddata', name]
            logger.info('Executing: %s', ' '.join(cmd_list))
            execute_from_command_line(cmd_list)
        logger.info('Command completed: load_all_data') 
Example #26
Source File: scale_post_steps.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the command.
        """

        job_id = int(os.environ.get('SCALE_JOB_ID'))
        exe_num = int(os.environ.get('SCALE_EXE_NUM'))

        logger.info('Command starting: scale_post_steps - Job ID: %d, Execution Number: %d', job_id, exe_num)
        try:
            # Get the pre-loaded job_exe for efficiency
            job_exe = self._get_job_exe(job_id, exe_num)

            self._perform_post_steps(job_exe)
        except ScaleError as err:
            err.log()
            sys.exit(err.exit_code)
        except Exception as ex:
            exit_code = GENERAL_FAIL_EXIT_CODE
            err = get_error_by_exception(ex.__class__.__name__)
            if err:
                err.log()
                exit_code = err.exit_code
            else:
                logger.exception('Error performing post-job steps')
            sys.exit(exit_code)

        logger.info('Command completed: scale_post_steps') 
Example #27
Source File: scale_daily_metrics.py    From scale with Apache License 2.0 5 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the Scale daily metrics.
        """

        day = options.get('day')

        logger.info('Command starting: scale_daily_metrics')
        logger.info(' - Day: %s', day)

        logger.info('Generating metrics...')
        date = datetime.datetime.strptime(day, '%Y-%m-%d')

        # Run the calculations against each provider for the requested date
        failed = 0
        for provider in registry.get_providers():
            metrics_type = provider.get_metrics_type()
            try:
                logger.info('Starting: %s', metrics_type.name)
                self._calculate_metrics(provider, date)
                logger.info('Completed: %s', metrics_type.name)
            except:
                failed += 1
                logger.exception('Unable to calculate metrics: %s', metrics_type.name)

        logger.info('Command completed: scale_daily_metrics')
        if failed:
            logger.info('Metric providers failed: %i', failed)
            sys.exit(failed) 
Example #28
Source File: scale_pre_steps.py    From scale with Apache License 2.0 4 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the command.
        """

        job_id = int(os.environ.get('SCALE_JOB_ID'))
        exe_num = int(os.environ.get('SCALE_EXE_NUM'))
        logger.info('Command starting: scale_pre_steps - Job ID: %d, Execution Number: %d', job_id, exe_num)
        try:
            job_exe = self._get_job_exe(job_id, exe_num)

            job_interface = job_exe.job_type.get_job_interface()
            exe_config = job_exe.get_execution_configuration()
            logger.info('Validating mounts...')
            job_interface.validate_populated_mounts(exe_config)
            logger.info('Validating settings...')
            job_interface.validate_populated_settings(exe_config)
            logger.info('Validating outputs and workspaces...')
            job_interface.validate_workspace_for_outputs(exe_config)

            self._generate_input_metadata(job_exe)

            job_data = job_exe.job.get_job_data()
            job_data = JobData(job_data.get_dict())
            logger.info('Setting up input files...')

            job_interface.perform_pre_steps(job_data)

            logger.info('Ready to execute job: %s', exe_config.get_args('main'))
        except ScaleError as err:
            err.log()
            sys.exit(err.exit_code)
        except Exception as ex:
            exit_code = GENERAL_FAIL_EXIT_CODE
            err = get_error_by_exception(ex.__class__.__name__)
            if err:
                err.log()
                exit_code = err.exit_code
            else:
                logger.exception('Error performing pre-job steps')

            sys.exit(exit_code)

        logger.info('Command completed: scale_pre_steps') 
Example #29
Source File: scale_scan.py    From scale with Apache License 2.0 4 votes vote down vote up
def handle(self, *args, **options):
        """See :meth:`django.core.management.base.BaseCommand.handle`.

        This method starts the Scan processor.
        """

        # Register a listener to handle clean shutdowns
        signal.signal(signal.SIGTERM, self._onsigterm)

        scan_id = options.get('scan_id')
        dry_run = bool(strtobool(options.get('dry_run')))
        local = options.get('local')

        if not scan_id:
            logger.error('-i or --scan-id parameter must be specified for Scan configuration.')
            sys.exit(1)

        logger.info('Command starting: scale_scan')
        logger.info('Scan ID: %i', scan_id)
        logger.info('Dry Run: %s', str(dry_run))
        logger.info('Local Test: %s', local)

        logger.info('Querying database for Scan configuration')
        scan = Scan.objects.select_related('job').get(pk=scan_id)
        self._scanner = scan.get_scan_configuration().get_scanner()
        self._scanner.scan_id = scan_id

        logger.info('Starting %s scanner', self._scanner.scanner_type)

        # Patch _get_volume_path for local testing outside of docker.
        # This is useful for testing when Scale isn't managing mounts.
        if options['local'] and patch:
            workspace = self._scanner._scanned_workspace
            if 'broker' in workspace.json_config and 'host_path' in workspace.json_config['broker']:
                with patch.object(Workspace, '_get_volume_path',
                                  return_value=workspace.json_config['broker']['host_path']) as mock_method:
                    self._scanner.run(dry_run=dry_run)
                    logger.info('Scanner has stopped running')
                    logger.info('Command completed: scale_scan')
                    return

        self._scanner.run(dry_run=dry_run)
        logger.info('Scanner has stopped running')

        logger.info('Command completed: scale_scan')