Пример #1
0
def migrate(name, target=''):
    '''
    Migrate a vm from one hypervisor to another. This routine will just start
    the migration and display information on how to look up the progress
    '''
    client = salt.client.LocalClient(__opts__['conf_file'])
    data = query(quiet=True)
    origin_data = _find_vm(name, data, quiet=True)
    try:
        origin_hyper = origin_data.keys()[0]
    except IndexError:
        print('Named vm {0} was not found to migrate'.format(name))
        return ''
    disks = origin_data[origin_hyper][name]['disks']
    if not origin_data:
        print('Named vm {0} was not found to migrate'.format(name))
        return ''
    if not target:
        target = _determine_hyper(data, origin_hyper)
    if target not in data:
        print('Target hypervisor {0} not found'.format(origin_data))
        return ''
    client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True])
    print client.cmd_async(origin_hyper, 'virt.migrate_non_shared',
                           [name, target])
Пример #2
0
def migrate(name, target=''):
    '''
    Migrate a vm from one hypervisor to another. This routine will just start
    the migration and display information on how to look up the progress
    '''
    client = salt.client.LocalClient(__opts__['conf_file'])
    data = query(quiet=True)
    origin_data = _find_vm(name, data, quiet=True)
    try:
        origin_hyper = origin_data.keys()[0]
    except IndexError:
        print('Named vm {0} was not found to migrate'.format(name))
        return ''
    disks = origin_data[origin_hyper][name]['disks']
    if not origin_data:
        print('Named vm {0} was not found to migrate'.format(name))
        return ''
    if not target:
        target = _determine_hyper(data, origin_hyper)
    if target not in data:
        print('Target hypervisor {0} not found'.format(origin_data))
        return ''
    client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True])
    print client.cmd_async(origin_hyper,
                           'virt.migrate_non_shared',
                           [name, target])
Пример #3
0
def ping_all_connected_minions(opts):
    client = salt.client.LocalClient()
    if opts['minion_data_cache']:
        tgt = list(salt.utils.minions.CkMinions(opts).connected_ids())
        form = 'list'
    else:
        tgt = '*'
        form = 'glob'
    client.cmd_async(tgt, 'test.ping', tgt_type=form)
Пример #4
0
def ping_all_connected_minions(opts):
    client = salt.client.LocalClient()
    if opts["minion_data_cache"]:
        tgt = list(salt.utils.minions.CkMinions(opts).connected_ids())
        form = "list"
    else:
        tgt = "*"
        form = "glob"
    client.cmd_async(tgt, "test.ping", tgt_type=form)
Пример #5
0
    def delete_key(self,
                   match=None,
                   match_dict=None,
                   preserve_minions=None,
                   revoke_auth=False):
        """
        Delete public keys. If "match" is passed, it is evaluated as a glob.
        Pre-gathered matches can also be passed via "match_dict".

        To preserve the master caches of minions who are matched, set preserve_minions
        """
        if match is not None:
            matches = self.name_match(match)
        elif match_dict is not None and isinstance(match_dict, dict):
            matches = match_dict
        else:
            matches = {}
        with salt.client.get_local_client(mopts=self.opts) as client:
            for status, keys in matches.items():
                for key in keys:
                    try:
                        if revoke_auth:
                            if self.opts.get("rotate_aes_key") is False:
                                print(
                                    "Immediate auth revocation specified but AES key"
                                    " rotation not allowed. Minion will not be"
                                    " disconnected until the master AES key is rotated."
                                )
                            else:
                                try:
                                    client.cmd_async(key,
                                                     "saltutil.revoke_auth")
                                except salt.exceptions.SaltClientError:
                                    print(
                                        "Cannot contact Salt master. "
                                        "Connection for {} will remain up until "
                                        "master AES key is rotated or auth is revoked "
                                        "with 'saltutil.revoke_auth'.".format(
                                            key))
                        os.remove(
                            os.path.join(self.opts["pki_dir"], status, key))
                        eload = {"result": True, "act": "delete", "id": key}
                        self.event.fire_event(
                            eload, salt.utils.event.tagify(prefix="key"))
                    except OSError:
                        pass
        if self.opts.get("preserve_minions") is True:
            self.check_minion_cache(
                preserve_minions=matches.get("minions", []))
        else:
            self.check_minion_cache()
        if self.opts.get("rotate_aes_key"):
            salt.crypt.dropfile(self.opts["cachedir"], self.opts["user"])
        return self.name_match(
            match) if match is not None else self.dict_match(matches)
Пример #6
0
def highstate_accepted_minion(name,
                              database_location=DEFAULT_DATABASE_LOCATION,
                              registry_script=DEFAULT_REGISTRY_SCRIPT):
    """
  Highstate a previously accepted minion.

  Highstating is done asynchronously to not block the reactor.
  """
    registry_call = _registry_call(database_location, registry_script)
    if _key_submitted_and_autoscaled(registry_call, name):
        client = salt.client.LocalClient(__opts__['conf_file'])
        client.cmd_async(name, 'state.highstate')
Пример #7
0
    def delete_key(self,
                   match=None,
                   match_dict=None,
                   preserve_minions=None,
                   revoke_auth=False):
        '''
        Delete public keys. If "match" is passed, it is evaluated as a glob.
        Pre-gathered matches can also be passed via "match_dict".

        To preserve the master caches of minions who are matched, set preserve_minions
        '''
        if match is not None:
            matches = self.name_match(match)
        elif match_dict is not None and isinstance(match_dict, dict):
            matches = match_dict
        else:
            matches = {}
        for status, keys in six.iteritems(matches):
            for key in keys:
                try:
                    if revoke_auth:
                        if self.opts.get('rotate_aes_key') is False:
                            print(
                                'Immediate auth revocation specified but AES key rotation not allowed. '
                                'Minion will not be disconnected until the master AES key is rotated.'
                            )
                        else:
                            try:
                                client = salt.client.get_local_client(
                                    mopts=self.opts)
                                client.cmd_async(key, 'saltutil.revoke_auth')
                            except salt.exceptions.SaltClientError:
                                print(
                                    'Cannot contact Salt master. '
                                    'Connection for {0} will remain up until '
                                    'master AES key is rotated or auth is revoked '
                                    'with \'saltutil.revoke_auth\'.'.format(
                                        key))
                    os.remove(os.path.join(self.opts['pki_dir'], status, key))
                    eload = {'result': True, 'act': 'delete', 'id': key}
                    self.event.fire_event(
                        eload, salt.utils.event.tagify(prefix='key'))
                except (OSError, IOError):
                    pass
        if self.opts.get('preserve_minions') is True:
            self.check_minion_cache(
                preserve_minions=matches.get('minions', []))
        else:
            self.check_minion_cache()
        if self.opts.get('rotate_aes_key'):
            salt.crypt.dropfile(self.opts['cachedir'], self.opts['user'])
        return (self.name_match(match)
                if match is not None else self.dict_match(matches))
Пример #8
0
def submit_job(target, action, params, audit_params=None, **kwargs):
    """ Submit an async Salt Job and return the job ID and the client instance

        Arguments:
        target       -- the Salt target hosts pattern
        action       -- the Salt module.function to call as string
        params       -- a list of parameters to pass to the module.function
        audit_params -- the parameters cleaned for logging purposes
        **kwargs     -- additional parameter for the Salt cmd_async function
    """
    # Checking multiple Job results in non-blocking mode is not supported
    # within the same client
    client = salt.client.LocalClient()

    # Returns int 0 if fails, str with Job ID on success
    jid = client.cmd_async(target, action, params, **kwargs)

    if jid == 0:
        logger.warning(("Unable to submit job to run '{action}' on target "
                        "'{target}'").format(action=action, target=target))
    else:
        if audit_params is None:
            audit_params = params

        logger.info(
            ("Submitted job '{jid}' on target '{target}' with action "
             "'{action}' and params '{params}'").format(jid=jid,
                                                        target=target,
                                                        action=action,
                                                        params=audit_params))

    return (jid, client)
Пример #9
0
def migrate(name, target=''):
    '''
    Migrate a vm from one hypervisor to another. This routine will just start
    the migration and display information on how to look up the progress.
    '''
    client = salt.client.get_local_client(__opts__['conf_file'])
    data = query(quiet=True)
    origin_data = _find_vm(name, data, quiet=True)
    try:
        origin_hyper = origin_data.iterkeys().next()
    except StopIteration:
        print('Named vm {0} was not found to migrate'.format(name))
        return ''
    disks = origin_data[origin_hyper][name]['disks']
    if not origin_data:
        print('Named vm {0} was not found to migrate'.format(name))
        return ''
    if not target:
        target = _determine_hyper(data, origin_hyper)
    if target not in data:
        print('Target hypervisor {0} not found'.format(origin_data))
        return ''
    client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True])
    jid = client.cmd_async(origin_hyper,
                           'virt.migrate_non_shared',
                           [name, target])

    msg = ('The migration of virtual machine {0} to hypervisor {1} has begun, '
           'and can be tracked via jid {2}. The ``salt-run virt.query`` '
           'runner can also be used, the target vm will be shown as paused '
           'until the migration is complete.').format(name, target, jid)
    print(msg)
Пример #10
0
def _async(fun, arg=[], tgt=None):
    """
    Helper method for asynchronous Salt calls
    """
    if not tgt:
        tgt = "master"

    client = salt.client.LocalClient()
    client.cmd_async(
        tgt=tgt,
        fun=fun,
        arg=arg,
        username=app.config["SALT_CLOUD_USERNAME"],
        password=app.config["SALT_CLOUD_PASSWORD"],
        eauth="pam",
    )
Пример #11
0
def migrate(name, target=""):
    """
    Migrate a vm from one hypervisor to another. This routine will just start
    the migration and display information on how to look up the progress.
    """
    client = salt.client.get_local_client(__opts__["conf_file"])
    data = query(quiet=True)
    origin_data = _find_vm(name, data, quiet=True)
    try:
        origin_hyper = origin_data.iterkeys().next()
    except StopIteration:
        print("Named vm {0} was not found to migrate".format(name))
        return ""
    disks = origin_data[origin_hyper][name]["disks"]
    if not origin_data:
        print("Named vm {0} was not found to migrate".format(name))
        return ""
    if not target:
        target = _determine_hyper(data, origin_hyper)
    if target not in data:
        print("Target hypervisor {0} not found".format(origin_data))
        return ""
    client.cmd(target, "virt.seed_non_shared_migrate", [disks, True])
    jid = client.cmd_async(origin_hyper, "virt.migrate_non_shared", [name, target])

    msg = (
        "The migration of virtual machine {0} to hypervisor {1} has begun, "
        "and can be tracked via jid {2}. The ``salt-run virt.query`` "
        "runner can also be used, the target vm will be shown as paused "
        "until the migration is complete."
    ).format(name, target, jid)
    print(msg)
Пример #12
0
def migrate(name, target=''):
    '''
    Migrate a vm from one hypervisor to another. This routine will just start
    the migration and display information on how to look up the progress.
    '''
    client = salt.client.get_local_client(__opts__['conf_file'])
    data = query(quiet=True)
    origin_data = _find_vm(name, data, quiet=True)
    try:
        origin_hyper = list(origin_data.keys())[0]
    except IndexError:
        __jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress')
        return ''
    disks = origin_data[origin_hyper][name]['disks']
    if not origin_data:
        __jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress')
        return ''
    if not target:
        target = _determine_hyper(data, origin_hyper)
    if target not in data:
        __jid_event__.fire_event({'error': 'Target hypervisor {0} not found'.format(origin_data)}, 'progress')
        return ''
    try:
        client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True])
        jid = client.cmd_async(origin_hyper,
                               'virt.migrate_non_shared',
                               [name, target])
    except SaltClientError as client_error:
        return 'Virtual machine {0} could not be migrated: {1}'.format(name, client_error)

    msg = ('The migration of virtual machine {0} to hypervisor {1} has begun, '
           'and can be tracked via jid {2}. The ``salt-run virt.query`` '
           'runner can also be used, the target vm will be shown as paused '
           'until the migration is complete.').format(name, target, jid)
    __jid_event__.fire_event({'message': msg}, 'progress')
Пример #13
0
def deploy(tgt_selector='haproxy',
           backend_selector='nodes',
           beta_backend_selector='beta_nodes',
           enable='webB(\d+)',
           disable=None):
    """
    """
    client = salt.client.LocalClient(__opts__['conf_file'])

    backends = client.cmd(tgt_selector,
                          'haproxy.list_servers', [backend_selector],
                          kwarg={'objectify': True})

    if not backends:
        logger.warn('No backends could be selected: {} {}'.format(
            tgt_selector, backend_selector))

    for backend in sorted(backends.get('haproxy')):
        # set to drain in LB
        logger.info('Starting HAPROXY deploy on %s' % backend)

        server_line = server_list_pattern.search(backend).groupdict()
        name = server_line.get('name')

        if bool(re.search(enable, name)):
            # enable
            logger.info('Enable %s on %s' % (name, backend))
            client.cmd_async(tgt_selector, 'haproxy.set_state',
                             [name, backend_selector, 'ready'])

        elif disable is not None and bool(re.search(disable,
                                                    name)) or disable is None:
            # disable
            logger.info('Disable %s on %s' % (name, backend))
            client.cmd_async(tgt_selector, 'haproxy.set_state',
                             [name, backend_selector, 'drain'])

    backends = client.cmd(tgt_selector,
                          'haproxy.list_servers', [backend_selector],
                          kwarg={'objectify': True})
    backends = client.cmd(tgt_selector,
                          'haproxy.list_servers', [beta_backend_selector],
                          kwarg={'objectify': True})
    pp.pprint(backends)
    return True
Пример #14
0
def call_highstate(minion_id):
    '''execute an async salt call to a minion to run state.highstate asynchronously'''
    client = salt.client.LocalClient()
    minions = client.cmd_async(tgt=minion_id,
                               fun='state.highstate',
                               arg=[],
                               timeout=1,
                               expr_form='compound')
    return
Пример #15
0
def saltcmdrun(ip,command,args):
    '''
    command 是命令脚本,调用远程服务器脚本(带绝对路径)
    '''
    #ip = ['172.17.62.43','172.17.62.42']
    client = salt.client.LocalClient()
    #res = client.cmd(ip, 'cmd.run',[command],timeout=86400,expr_form='list')
    #res = client.cmd(ip, 'cmd.script',[command],kwarg=args,timeout=86400,expr_form='list')
    res = client.cmd_async(ip, 'cmd.script',[command],timeout=86400,expr_form='list')
    return res
Пример #16
0
def pollpush():
    '''
    Run the monitoring command and return to carbon
    '''
    client = salt.client.LocalClient(__opts__['conf_file'])
    cmds = ('ps.physical_memory_usage', 'ps.cpu_percent')
    nodes = '*'

    for cmd in cmds:
        jid = client.cmd_async(nodes, cmd, ret='carbon', timeout=__opts__['timeout'])
Пример #17
0
 def run_async(self):
     client = salt.client.LocalClient()
     task_id = client.cmd_async(
         self.salt_target,
         self.salt_function,
         [a.value for a in self.saltarg_set.all()]
     )
     if self.hipchat_notification_msg:
         rendered_msg = self.hipchat_notification_msg.format(cmd=self, id=task_id)
         msg = '{msg} View state log on {saltobserver_url}/jobs/{id} after state has finished.'.format(
             saltobserver_url=settings.SALTOBSERVER_URL,
             msg=rendered_msg,
             id=task_id)
         notify_hipchat(msg)
         return task_id
Пример #18
0
def cmd(name,
        tgt,
        func,
        arg=(),
        tgt_type="glob",
        ret="",
        kwarg=None,
        **kwargs):
    """
    Execute a remote execution command

    USAGE:

    .. code-block:: yaml

        run_remote_ex:
          local.cmd:
            - tgt: '*'
            - func: test.ping

        run_remote_ex:
          local.cmd:
            - tgt: '*'
            - func: test.sleep
            - arg:
              - 30

        run_remote_ex:
          local.cmd:
            - tgt: '*'
            - func: test.sleep
            - kwarg:
              length: 30
    """
    ret = {"name": name, "changes": {}, "comment": "", "result": True}
    with salt.client.get_local_client(mopts=__opts__) as client:
        jid = client.cmd_async(tgt,
                               func,
                               arg,
                               tgt_type=tgt_type,
                               ret=ret,
                               kwarg=kwarg,
                               **kwargs)
        ret["changes"]["jid"] = jid
    return ret
Пример #19
0
def migrate(name, target=""):
    """
    Migrate a VM from one host to another. This routine will just start
    the migration and display information on how to look up the progress.
    """
    with salt.client.get_local_client(__opts__["conf_file"]) as client:
        data = query(quiet=True)
        origin_data = _find_vm(name, data, quiet=True)
        try:
            origin_host = next(iter(origin_data))
        except StopIteration:
            __jid_event__.fire_event(
                {"error": "Named VM {} was not found to migrate".format(name)},
                "progress",
            )
            return ""
        disks = origin_data[origin_host][name]["disks"]
        if not origin_data:
            __jid_event__.fire_event(
                {"error": "Named VM {} was not found to migrate".format(name)},
                "progress",
            )
            return ""
        if not target:
            target = _determine_host(data, origin_host)
        if target not in data:
            __jid_event__.fire_event(
                {"error": "Target host {} not found".format(origin_data)},
                "progress")
            return ""
        try:
            client.cmd(target, "virt.seed_non_shared_migrate", [disks, True])
            jid = client.cmd_async(origin_host, "virt.migrate_non_shared",
                                   [name, target])
        except SaltClientError as client_error:
            return "Virtual machine {} could not be migrated: {}".format(
                name, client_error)

        msg = (
            "The migration of virtual machine {} to host {} has begun, "
            "and can be tracked via jid {}. The ``salt-run virt.query`` "
            "runner can also be used, the target VM will be shown as paused "
            "until the migration is complete.".format(name, target, jid))
        __jid_event__.fire_event({"message": msg}, "progress")
Пример #20
0
def execute(**kwargs):
    return client.cmd_async(**kwargs)
Пример #21
0
def rerun():
    inflight = {}   # a dictionary for jobs with pending returned results
    repeat_count = 0
    m = None
    client = salt.client.LocalClient('/etc/salt/minion')
    for data in event.iter_events(tag='rerun', full=True):
        # this is the inner event loop...
        #
        print 'data =', (data)
        target = data['data']['id']
        fun = data['data']['data']['fun']
        fun_args = data['data']['data']['fun_args']
        RERUN_IT = True
        REDUCER_CALLBACK = True
        if fun == 'test.arg':
            # Interactive commands for controlling the mapper enter here...
            # We repurpose the existing salt test.arg command
            #
            # >>> salt "test.arg <command> <args> <kwargs> --return=rerun"
            #
            # to control the runner
            #
            RERUN_IT = False
                # ...don't rerun control commands
            REDUCER_CALLBACK = False    # don't callback results from control commands
            command = fun_args[0].lower()
            if command == 'abort':
                print "\"abort\" received, now terminating runner..."
                return False
            elif command == 'reset':
                print "\"reset\" received, now restarting..."
                return True
            elif command == 'run':
                print "run"
                RERUN_IT = True
            elif command == 'stop':
                print "stop"
            elif command == 'pause':
                print "pause"
            elif command == 'stats':
                print "repeat_count = ", (repeat_count)
                print "results = ", (m.statit())
            elif command == 'mapit':
                print "mapit"
                if not m:
                    # run this only once...
                    try:
                        module_name = fun_args[1].split('.')[0]
                        # from module_name import _mapper
                        mod = __import__(module_name)
                        mod = getattr(mod, '_mapper')
                        # this module has a "_mapper" class so use it...
                        m = mod(fun_args[1])
                        repeat = m.partializer(fun_args[2:])
                    except:
                        # not a map-reduce style module, so use base mapper class
                        m = mapper(fun_args[1])
                        repeat = m.partializer(fun_args[2:])
                # RERUN_IT = True
                # # ...causes the initial "partializer" command to be run

        if REDUCER_CALLBACK:
            # only callback the reducer if we got "real" results from a salt
            # execution module
            if inflight[data['data']['data']['jid']]:
                # TODO: This should not happen. Investigate why and prevent it
                m.reducer(data['data']['data']['return'])
                inflight.pop(data['data']['data']['jid'])
                try:
                    mod
                except:
                    RERUN_IT = False
                    # This is NOT a MR enabled salt execution module so don't rerun it
            else:
                RERUN_IT = False    # ...ignore this spurious event


        if RERUN_IT:
            try:
                my_fun = m.module_name
                my_fun_args = repeat.next()
                print "my_fun_args = ", (my_fun_args)
                minions = client.cmd_async(target, my_fun, my_fun_args, ret='rerun')
                inflight[minions] = True
                print "sending...", (my_fun), (my_fun_args), (minions)
                repeat_count += 1
                print 'repeat =', (repeat_count)
            except StopIteration:
                print "done."
                if len(inflight) == 0:
                    # all the results in, ok to terminate
                    exit([m.statit()])
Пример #22
0
def call_highstate(minion_id):
  '''execute an async salt call to a minion to run state.highstate asynchronously'''
  client = salt.client.LocalClient()
  minions = client.cmd_async(tgt=minion_id, fun='state.highstate', arg=[], timeout=1, expr_form='compound')
  return 
Пример #23
0
def execute(**kwargs):
  return client.cmd_async(**kwargs)
Пример #24
0
    def run(self, params, args):
        hosts = self.getHostnames(args, managed_only=True)

        (function, name, sls, test,
         timeout) = self.fillParams([('function', None), ('name', None),
                                     ('sls', None), ('test', None),
                                     ('timeout', 30)])

        test = self.str2bool(test)

        self.beginOutput()

        client = salt.client.LocalClient()
        if sls:
            job = client.cmd_async(hosts,
                                   fun='state.sls',
                                   arg=[sls],
                                   expr_form='list')
        elif function or name:
            if not (function and name):
                raise ParamRequired(self, ('function', 'name'))
            job = client.cmd_async(
                hosts,
                fun='state.single',
                arg=[function, 'name=%s' % name,
                     'test=%s' % test],
                expr_form='list')
        else:
            job = client.cmd_async(hosts,
                                   fun='state.highstate',
                                   arg=['test=%s' % test],
                                   expr_form='list')

        if job:
            while timeout:
                result = client.get_cache_returns(job)
                if result and len(result.keys()) == len(hosts):
                    break
                time.sleep(1)
                timeout -= 1

        for host in hosts:
            if result.has_key(host):
                if result[host].has_key('ret'):
                    ret = result[host]['ret']
                    if ret:
                        for key in ret.keys():
                            list = key.split('_|-')
                            function = '%s.%s' % (list[0], list[3])
                            id = list[1]
                            name = None
                            if ret[key].has_key('name'):
                                name = ret[key]['name']
                            self.addOutput(host, [
                                name, function, ret[key]['result'],
                                ret[key]['comment']
                            ])
            else:
                self.addOutput(host, [None, None, False, 'Command not run'])

        self.endOutput(
            header=['host', 'name', 'function', 'result', 'comment'],
            trimOwner=False)
Пример #25
0
def rerun():
    inflight = {}  # a dictionary for jobs with pending returned results
    repeat_count = 0
    m = None
    client = salt.client.LocalClient('/etc/salt/minion')
    for data in event.iter_events(tag='rerun', full=True):
        # this is the inner event loop...
        #
        print 'data =', (data)
        target = data['data']['id']
        fun = data['data']['data']['fun']
        fun_args = data['data']['data']['fun_args']
        RERUN_IT = True
        REDUCER_CALLBACK = True
        if fun == 'test.arg':
            # Interactive commands for controlling the mapper enter here...
            # We repurpose the existing salt test.arg command
            #
            # >>> salt "test.arg <command> <args> <kwargs> --return=rerun"
            #
            # to control the runner
            #
            RERUN_IT = False
            # ...don't rerun control commands
            REDUCER_CALLBACK = False  # don't callback results from control commands
            command = fun_args[0].lower()
            if command == 'abort':
                print "\"abort\" received, now terminating runner..."
                return False
            elif command == 'reset':
                print "\"reset\" received, now restarting..."
                return True
            elif command == 'run':
                print "run"
                RERUN_IT = True
            elif command == 'stop':
                print "stop"
            elif command == 'pause':
                print "pause"
            elif command == 'stats':
                print "repeat_count = ", (repeat_count)
                print "results = ", (m.statit())
            elif command == 'mapit':
                print "mapit"
                if not m:
                    # run this only once...
                    try:
                        module_name = fun_args[1].split('.')[0]
                        # from module_name import _mapper
                        mod = __import__(module_name)
                        mod = getattr(mod, '_mapper')
                        # this module has a "_mapper" class so use it...
                        m = mod(fun_args[1])
                        repeat = m.partializer(fun_args[2:])
                    except:
                        # not a map-reduce style module, so use base mapper class
                        m = mapper(fun_args[1])
                        repeat = m.partializer(fun_args[2:])
                # RERUN_IT = True
                # # ...causes the initial "partializer" command to be run

        if REDUCER_CALLBACK:
            # only callback the reducer if we got "real" results from a salt
            # execution module
            if inflight[data['data']['data']['jid']]:
                # TODO: This should not happen. Investigate why and prevent it
                m.reducer(data['data']['data']['return'])
                inflight.pop(data['data']['data']['jid'])
                try:
                    mod
                except:
                    RERUN_IT = False
                    # This is NOT a MR enabled salt execution module so don't rerun it
            else:
                RERUN_IT = False  # ...ignore this spurious event

        if RERUN_IT:
            try:
                my_fun = m.module_name
                my_fun_args = repeat.next()
                print "my_fun_args = ", (my_fun_args)
                minions = client.cmd_async(target,
                                           my_fun,
                                           my_fun_args,
                                           ret='rerun')
                inflight[minions] = True
                print "sending...", (my_fun), (my_fun_args), (minions)
                repeat_count += 1
                print 'repeat =', (repeat_count)
            except StopIteration:
                print "done."
                if len(inflight) == 0:
                    # all the results in, ok to terminate
                    exit([m.statit()])