Пример #1
0
def test_nr_diagram_IP_from_file():
    # collect and save commands output to files
    commands_output = runner.cmd(
        fun="nr.call",
        arg=["cli", "show run", "show ip arp"],
        kwarg={
            "FB": "ceos[12]",
            "tf": "ip_data",
            "tgt": "nrp1",
            "tgt_type": "glob",
        },
    )
    # build diagram out of files
    ret = runner.cmd(
        fun="nr.diagram",
        arg=["IP"],
        kwarg={
            "FB": "ceos[12]",
            "outfile": "/tmp/pytest/test_nr_diagram_IP_from_file.graphml",
            "filegroup": "ip_data",
            "last": 1,
            "tgt": "nrp1",
            "tgt_type": "glob",
        },
    )

    pprint.pprint(ret)
    with open("/tmp/pytest/test_nr_diagram_IP_from_file.graphml") as f:
        diagram_content = f.read()
        root = ET.fromstring(diagram_content)

    assert "/tmp/pytest/test_nr_diagram_IP_from_file.graphml" in ret and "saved" in ret
    assert "Traceback" not in diagram_content
    assert root and len(root) > 1
Пример #2
0
def winrepo_genrepo(name, cli=True):
    '''
    Execute the winrepo.genrepo runner

    Salter Example::
        
        init.winrepo:
          winrepo_genrep

    CLI Examples:

    .. code-block:: bash

        salt-run salter.winrepo_genrepo
    '''
    
    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}

    pillar = salt.client.Caller().sminion.functions['pillar.data']()
    runner = salt.runner.RunnerClient(pillar['master'])
    log.info('generating windows package repository')
    ret['changes'] = {'winrepo': runner.cmd('winrepo.genrepo', [])}
    if not ret['changes']:
        ret['result'] = False
        ret['comment'] = 'winrepo returned empty !'
        log.error(ret['comment'])

    if cli:
        _end_func_from_cli(ret)
    return ret
Пример #3
0
    def get_jobs_from_runner(self, outstanding_jids):
        """
        Given a list of job_ids, return a dictionary of those job_ids that have
        completed and their results.

        Query the salt event bus via the jobs runner. jobs.list_job will show
        a job in progress, jobs.lookup_jid will return a job that has
        completed.

        returns a dictionary of job id: result
        """
        # Can't use the runner because of https://github.com/saltstack/salt/issues/40671
        runner = salt.runner.RunnerClient(__opts__)
        source = __opts__.get("ext_job_cache")
        if not source:
            source = __opts__.get("master_job_cache")

        results = {}
        for jid in outstanding_jids:
            # results[jid] = runner.cmd('jobs.lookup_jid', [jid])
            if self.master_minion.returners["{}.get_jid".format(source)](jid):
                job_result = runner.cmd("jobs.list_job", [jid])
                jid_result = job_result.get("Result", {})
                jid_function = job_result.get("Function", {})
                # emulate lookup_jid's return, which is just minion:return
                results[jid] = {
                    "data": salt.utils.json.loads(salt.utils.json.dumps(jid_result)),
                    "function": jid_function,
                }

        return results
def check_compliance(hostname, test_file):
    opts = salt.config.master_config('/etc/salt/master')
    runner = salt.runner.RunnerClient(opts)
    pillar = runner.cmd('pillar.show_pillar', [hostname])
    config_file_object = {
        "hosts": [
            {
                "device":  pillar['proxy']['host'],
                "username": pillar['proxy']['username'],
                "passwd": pillar['proxy']['passwd']
            }
        ],
        "tests": [
            test_file
        ]
    }
    config_file = yaml.dump(config_file_object)
    js = SnapAdmin()
    snapcheck_output = js.snapcheck(config_file, "automatic_snapshot_from_saltstack")
    json_output = {}
    for item in snapcheck_output:
        json_output = {
            'jsnapy_device_name': hostname,
            'jsnapy_device_ip': item.device,
            'jsnapy_result': item.result,
            'jsnapy_nbr_passed': item.no_passed,
            'jsnapy_nbr_failed': item.no_failed,
            'jsnapy_test_file': test_file
            }
    if json_output['jsnapy_result'] == 'Failed':
        caller = salt.client.LocalClient()
        caller.cmd(hostname, 'event.send', ['jnpr/compliance/failed'], kwarg={'result': json_output})
    return json_output
Пример #5
0
def test_nr_diagram_IP_save_data_path():
    ret = runner.cmd(
        fun="nr.diagram",
        arg=["IP"],
        kwarg={
            "FB": "ceos[12]",
            "outfile": "/tmp/pytest/test_nr_diagram_IP_save_data_path.graphml",
            "save_data": "/tmp/pytest/test_nr_diagram_IP_save_data_path/",
            "tgt": "nrp1",
            "tgt_type": "glob",
        },
    )

    pprint.pprint(ret)
    with open("/tmp/pytest/test_nr_diagram_IP_save_data_path.graphml") as f:
        diagram_content = f.read()
        root = ET.fromstring(diagram_content)

    assert "/tmp/pytest/test_nr_diagram_IP_save_data_path.graphml" in ret and "saved" in ret
    assert "Traceback" not in diagram_content
    assert root and len(root) > 1
    assert "test_nr_diagram_IP_save_data_path" in os.listdir("/tmp/pytest/")
    assert "arista_eos" in os.listdir(
        "/tmp/pytest/test_nr_diagram_IP_save_data_path/")
    assert "ceos1.txt" in os.listdir(
        "/tmp/pytest/test_nr_diagram_IP_save_data_path/arista_eos/")
    assert "ceos2.txt" in os.listdir(
        "/tmp/pytest/test_nr_diagram_IP_save_data_path/arista_eos/")


# test_nr_diagram_IP_save_data_path()
Пример #6
0
def getGrainsFromCache(g, __opts__):

    runner = salt.runner.Runner(__opts__)

    stdout_bak = sys.stdout
    with open(os.devnull, 'wb') as f:
        sys.stdout = f
        items = runner.cmd("cache.grains", [g['salt_id']])
    sys.stdout = stdout_bak

    dc = ""
    env = ""
    version = ""

    if g['salt_id'] in items:
        if 'dc' in items[g['salt_id']]:
            dc = items[g['salt_id']]['dc']
        else:
            dc = 'null'
        if 'env' in items[g['salt_id']]:
            env = items[g['salt_id']]['env']
        else:
            env = 'null'
        if 'version' in items[g['salt_id']]:
            version = items[g['salt_id']]['version']
        else:
            version = 'null'

    return dc, env, version
Пример #7
0
def minions_list():

     runner = salt.runner.RunnerClient(opts)

     minions_list = runner.cmd('manage.up', [])

     return minions_list
Пример #8
0
def active_jobs():

    runner = salt.runner.RunnerClient(opts)

    
    active_task_list = []
 
    try:
 
        active_tasks_list = runner.cmd('jobs.active', [])

    except:

        raise exceptions.NotAvailable(_('Salt-master is not available'))
 

    active_task_list_converted  = []
    #  bug is here 

    for task_id in active_tasks_list.keys():

        single_active_task = active_tasks_list[task_id]

        active_task_list_converted.append( ActiveTask( id=task_id, 
                                                       function=single_active_task['Function'] , 
                                                       user=single_active_task['User'], 
                                                       target_type=single_active_task['Target-type'], 
                                                       returned=single_active_task['Returned'], 
                                                       running_on=single_active_task['Running'], 
                                                       arguments=single_active_task['Arguments'] ))


    return active_task_list_converted
Пример #9
0
def genrepo(name, force=False, allow_empty=False):
    '''
    Refresh the winrepo.p file of the repository (salt-run winrepo.genrepo)

    if force is True no checks will be made and the repository will be generated
    if allow_empty is True then the state will not return an error if there are 0 packages

    Example:

    .. code-block:: yaml

        winrepo:
          winrepo.genrepo
    '''

    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}

    master_config = salt.config.master_config(os.path.join(salt.syspaths.CONFIG_DIR, 'master'))
    win_repo = master_config['win_repo']
    win_repo_mastercachefile = master_config['win_repo_mastercachefile']

    # Check if the win_repo directory exists
    # if not search for a file with a newer mtime than the win_repo_mastercachefile file
    execute = False
    if not force:
        if not os.path.exists(win_repo):
            ret['result'] = False
            ret['comment'] = 'missing {0}'.format(win_repo)
            return ret
        elif not os.path.exists(win_repo_mastercachefile):
            execute = True
            ret['comment'] = 'missing {0}'.format(win_repo_mastercachefile)
        else:
            win_repo_mastercachefile_mtime = os.stat(win_repo_mastercachefile)[stat.ST_MTIME]
            for root, dirs, files in os.walk(win_repo):
                for name in itertools.chain(files, dirs):
                    full_path = os.path.join(root, name)
                    if os.stat(full_path)[stat.ST_MTIME] > win_repo_mastercachefile_mtime:
                        ret['comment'] = 'mtime({0}) < mtime({1})'.format(win_repo_mastercachefile, full_path)
                        execute = True
                        break

    if __opts__['test']:
        ret['result'] = None
        return ret

    if not execute and not force:
        return ret

    runner = salt.runner.RunnerClient(master_config)
    runner_ret = runner.cmd('winrepo.genrepo', [])
    ret['changes'] = {'winrepo': runner_ret}
    if isinstance(runner_ret, dict) and runner_ret == {} and not allow_empty:
        os.remove(win_repo_mastercachefile)
        ret['result'] = False
        ret['comment'] = 'winrepo.genrepo returned empty'
    return ret
Пример #10
0
def target(mod='test.ping'):
    ''' run exec module on random minion '''

    print 'execution module selected: {0}'.format(mod)

    # load master config
    opts = salt.config.master_config('/etc/salt/master')
    print "master config loaded"

    # load runner client with master config
    runner = salt.runner.RunnerClient(opts)

    print 'fetching minions'
    # run manage.up to fetch active minions
    list_of_minions = runner.cmd('manage.up', [])

    # let python randomly choose a minion
    random_target = choice(list_of_minions)
    print 'random minion chosen'

    # load the execution module client
    local = salt.client.LocalClient()
    print 'local client loaded'

    # run execution module on randomly targeted minion
    return local.cmd(random_target, mod)
Пример #11
0
def get_jobs_from_runner(outstanding_jids):
    """
    Given a list of job_ids, return a dictionary of those job_ids that have completed and their results.

    Query the salt event bus via the jobs runner.  jobs.list_job will show a job in progress,
    jobs.lookup_jid will return a job that has completed.

    returns a dictionary of job id: result
    """
    # Can't use the runner because of https://github.com/saltstack/salt/issues/40671
    runner = salt.runner.RunnerClient(__opts__)
    # log.debug("Getting job IDs {} will run via runner jobs.lookup_jid".format(outstanding_jids))
    mm = salt.minion.MasterMinion(__opts__)
    source = __opts__.get('ext_job_cache')
    if not source:
        source = __opts__.get('master_job_cache')

    results = dict()
    for jid in outstanding_jids:
        # results[jid] = runner.cmd('jobs.lookup_jid', [jid])
        if mm.returners['{}.get_jid'.format(source)](jid):
            jid_result = runner.cmd('jobs.list_job', [jid]).get('Result', {})
            # emulate lookup_jid's return, which is just minion:return
            # pylint is tripping
            # pylint: disable=missing-whitespace-after-comma
            job_data = json.dumps(
                {key: val['return']
                 for key, val in jid_result.items()})
            results[jid] = yaml.load(job_data)

    return results
Пример #12
0
def genrepo(name, force=False, allow_empty=False):
    '''
    Refresh the winrepo.p file of the repository (salt-run winrepo.genrepo)

    if force is True no checks will be made and the repository will be generated
    if allow_empty is True then the state will not return an error if there are 0 packages

    Example:

    .. code-block:: yaml

        winrepo:
          winrepo.genrepo
    '''

    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}

    master_config = salt.config.master_config(os.path.join(salt.syspaths.CONFIG_DIR, 'master'))
    win_repo = master_config['win_repo']
    win_repo_mastercachefile = master_config['win_repo_mastercachefile']

    # Check if the win_repo directory exists
    # if not search for a file with a newer mtime than the win_repo_mastercachefile file
    execute = False
    if not force:
        if not os.path.exists(win_repo):
            ret['result'] = False
            ret['comment'] = 'missing {0}'.format(win_repo)
            return ret
        elif not os.path.exists(win_repo_mastercachefile):
            execute = True
            ret['comment'] = 'missing {0}'.format(win_repo_mastercachefile)
        else:
            win_repo_mastercachefile_mtime = os.stat(win_repo_mastercachefile)[stat.ST_MTIME]
            for root, dirs, files in os.walk(win_repo):
                for name in itertools.chain(files, dirs):
                    full_path = os.path.join(root, name)
                    if os.stat(full_path)[stat.ST_MTIME] > win_repo_mastercachefile_mtime:
                        ret['comment'] = 'mtime({0}) < mtime({1})'.format(win_repo_mastercachefile, full_path)
                        execute = True
                        break

    if __opts__['test']:
        ret['result'] = None
        return ret

    if not execute and not force:
        return ret

    runner = salt.runner.RunnerClient(master_config)
    runner_ret = runner.cmd('winrepo.genrepo', [])
    ret['changes'] = {'winrepo': runner_ret}
    if isinstance(runner_ret, dict) and runner_ret == {} and not allow_empty:
        os.remove(win_repo_mastercachefile)
        ret['result'] = False
        ret['comment'] = 'winrepo.genrepo returned empty'
    return ret
Пример #13
0
def status(request):
    if request.method == "GET":
        #salt-run
        saltrun = request.GET.get('saltrun', None)
        if saltrun != None:
            runner = salt.runner.RunnerClient(master_opts)
            ret = runner.cmd(saltrun, [])
    return HttpResponse(json.dumps(ret), content_type="application/json")
Пример #14
0
def put_device_in_maintenance(dev):
    opts = salt.config.master_config('/etc/salt/master')
    caller = salt.client.Caller()
    local_minion_id = caller.cmd('grains.get', 'id')
    runner = salt.runner.RunnerClient(opts)
    pillar = runner.cmd('pillar.show_pillar', [local_minion_id])
    url = pillar['northstar']['url']
    maintenance_event_duration = pillar['northstar'][
        'maintenance_event_duration']
    url_base = pillar['northstar']['url_base']
    authuser = pillar['northstar']['authuser']
    authpwd = pillar['northstar']['authpwd']
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
    headers = {'content-type': 'application/json'}
    data_to_get_token = {
        "grant_type": "password",
        "username": authuser,
        "password": authpwd
    }
    r = requests.post(url,
                      data=json.dumps(data_to_get_token),
                      auth=(authuser, authpwd),
                      headers=headers,
                      verify=False)
    headers = {
        'Authorization': str('Bearer ' + r.json()['access_token']),
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
    url = url_base + '1/topology/1/nodes'
    r = requests.get(url, headers=headers, verify=False)
    for i in r.json():
        if i['hostName'] == dev:
            node_index = i['nodeIndex']
    maintenance_url = url_base + '1/topology/1/maintenances'
    maintenance_data = {
        "topoObjectType":
        "maintenance",
        "topologyIndex":
        1,
        "user":
        "******",
        "name":
        "event_" + dev,
        "startTime":
        datetime.now().isoformat(),
        "endTime": (datetime.now() +
                    timedelta(minutes=maintenance_event_duration)).isoformat(),
        "elements": [{
            "topoObjectType": "node",
            "index": node_index
        }]
    }
    m_res = requests.post(maintenance_url,
                          data=json.dumps(maintenance_data),
                          headers=headers,
                          verify=False)
    return "done"
Пример #15
0
def display_minions():
    jj = _load_environment()
    context = {}
    context['conductors'] = list(conductors.keys())
    key_states = wheel.cmd('key.list_all')
    context['key_states'] = key_states
    connected_minions = runner.cmd('manage.up')
    context['connected_minions'] = connected_minions
    page_template = jj.get_template('minions.j2')
    return page_template.render(context)
Пример #16
0
    def __call__(self, query):
        opts = salt.config.master_config(strongr.core.Core.config().clouddomain.OpenNebula.salt_config + '/master')
        opts['quiet'] = True
        runner = salt.runner.RunnerClient(opts)

        cache = strongr.core.gateways.Gateways.cache()

        if not cache.exists('clouddomain.jobs.running'):
            cache.set('clouddomain.jobs.running', runner.cmd('jobs.active'), 1)

        jobs = cache.get('clouddomain.jobs.running')

        if jobs is None:
            jobs = {}

        if query.jid not in jobs: # we only want to give status when the job is finished running
            result = runner.cmd('jobs.lookup_jid', [query.jid])
            return result
        return None
Пример #17
0
def checkTableJobs():
	opts = salt.config.master_config('/etc/salt/master')
        runner = salt.runner.RunnerClient(opts)
        ret = runner.cmd('jobs.active', print_event=False)
        activeJobs = set()
        for jobs in ret:
                for runs in ret[jobs]['Running']:
                        for tables in runs:
                                activeJobs.add(tables)
	return activeJobs
Пример #18
0
def test_nr_call_cli():
    ret = runner.cmd(
        fun="nr.call",
        full_return=True,
        arg=["cli", "show clock"],
        kwarg={"FB": "ceos[12]"},
    )
    # pprint.pprint(ret)
    assert ret["success"] == True
    assert isinstance(ret["return"]["ceos1"][0]["result"], str)
    assert isinstance(ret["return"]["ceos2"][0]["result"], str)
Пример #19
0
def test_nr_call_cli_ret_struct_list():
    ret = runner.cmd(
        fun="nr.call",
        arg=["cli", "show clock"],
        kwarg={"FB": "ceos[12]", "ret_struct": "list"},
    )
    pprint.pprint(ret)
    for i in ret:
        assert i["name"] == "show clock"
        assert "Traceback" not in i["result"]
        assert "minion_id" in i
        assert "host" in i
Пример #20
0
def test_nr_call_cli_non_existing_minions():
    """
    This call should return results for nrp1 only, as this is the minion
    that manages ceos1 and 2.
    """
    ret = runner.cmd(
        fun="nr.call",
        arg=["cli", "show clock", "show hostname"],
        kwarg={"FB": "ceos*", "tgt": "foo", "tgt_type": "glob"}
    )
    pprint.pprint(ret)
    assert "CommandExecutionError: No minions matched" in ret
Пример #21
0
def test_nr_call_cli_non_existing_hosts():
    """
    This call should return results for nrp1 only, as this is the minion
    that manages ceos1 and 2.
    """
    ret = runner.cmd(
        fun="nr.call",
        arg=["cli", "show clock", "show hostname"],
        kwarg={"FB": "ceos-foo"},
    )
    pprint.pprint(ret)
    assert "CommandExecutionError: Hosts not found" in ret
Пример #22
0
def test_nr_call_cfg():
    ret = runner.cmd(
        fun="nr.call",
        full_return=True,
        arg=["cfg", "logging host 1.2.3.4", "logging host 1.2.3.5"],
        kwarg={"plugin": "netmiko", "progress": False, "FB": "ceos[12]"},
    )
    # pprint.pprint(ret)
    assert ret["success"] == True
    assert ret["return"]["ceos1"][0]["failed"] == False
    assert ret["return"]["ceos2"][0]["failed"] == False
    assert isinstance(ret["return"]["ceos1"][0]["result"], str) 
    assert isinstance(ret["return"]["ceos2"][0]["result"], str) 
Пример #23
0
def test_nr_call_cli_multiple_commands_ret_struct_dict():
    ret = runner.cmd(
        fun="nr.call",
        arg=["cli", "show clock", "show hostname"],
        kwarg={"FB": "ceos[12]", "ret_struct": "dictionary"},
    )
    pprint.pprint(ret)
    for hostname, results in ret.items():
        assert len(results) == 2
        for item in results:
            assert "Traceback" not in item["result"]
            assert "minion_id" in item
            assert item["name"] in ["show clock", "show hostname"]
Пример #24
0
def salt_status():
    # __opts__ = salt.config.master_config('/etc/salt/master')
    # client = salt.client.LocalClient(__opts__['conf_file'])
    # minions = client.cmd('*', 'test.ping', timeout=__opts__['timeout'])
    # key = salt.key.Key(__opts__)
    # keys = key.list_keys()
    # ret = {}
    # ret['up'] = sorted(minions)
    # ret['down'] = sorted(set(keys['minions']) - set(minions))
    # return ret['down']
    opts = salt.config.master_config('/etc/salt/master')
    runner = salt.runner.RunnerClient(opts)
    ret = runner.cmd('manage.down', [])
    return ret
Пример #25
0
def test_nr_call_cli_table_brief_nrp1_only():
    """
    This call should return results for nrp1 only, as this is the minion
    that manages ceos1 and 2.
    """
    ret = runner.cmd(
        fun="nr.call",
        arg=["cli", "show clock", "show hostname"],
        kwarg={"FB": "ceos[12]", "ret_struct": "dictionary", "table": "brief"},
    )
    pprint.pprint(ret)
    assert len(ret) == 1
    assert isinstance(ret["nrp1"], str)
    assert "Traceback" not in ret["nrp1"]
Пример #26
0
def salt_status():
    # __opts__ = salt.config.master_config('/etc/salt/master')
    # client = salt.client.LocalClient(__opts__['conf_file'])
    # minions = client.cmd('*', 'test.ping', timeout=__opts__['timeout'])
    # key = salt.key.Key(__opts__)
    # keys = key.list_keys()
    # ret = {}
    # ret['up'] = sorted(minions)
    # ret['down'] = sorted(set(keys['minions']) - set(minions))
    # return ret['down']
    opts = salt.config.master_config('/etc/salt/master')
    runner = salt.runner.RunnerClient(opts)
    ret = runner.cmd('manage.down', [])
    return ret
Пример #27
0
def slave_list():
    slaves = []

    # under management
    nodes = runner.cmd('manage.status', [False])
    for s in nodes.values():
        for n in s:
            if n.startswith('mesoslave-'):
                slaves.append(n)

    # in cloud map
    with open(SLAVEYAML, 'r') as fh:
        d = yaml.load(fh)
    if not d:
        return slaves
    return list(set(d.get(SLAVEIMG, []) + slaves))
Пример #28
0
def getGrains(dc, env, __opts__):

    runner = salt.runner.Runner(__opts__)

    stdout_bak = sys.stdout
    with open(os.devnull, 'wb') as f:
        sys.stdout = f
        items = runner.cmd("cache.grains", "")
    sys.stdout = stdout_bak

    arr = []

    if len(dc) > 0 and len(env) > 0:
        i = 0
        for key in items:
            #matchObj = re.match( env, items[key]['env'], re.I)
            #if items[key]['dc'] == dc and matchObj:
            #print items[key]['dc'],  items[key]['env']
            if 'dc' in items[key]:
                itemdc = items[key]['dc'].lower()
            else:
                continue
            if 'env' in items[key]:
                itemenv = items[key]['env'].lower()
            else:
                continue
            dc = dc.lower()
            env = env.lower()
            if itemdc == dc and itemenv == env:
                arr.append(items[key]['id'])
                ++i
    elif len(dc) > 0:
        for key in items:
            if 'dc' in items[key]:
                itemdc = items[key]['dc'].lower()
            else:
                continue
            dc = dc.lower()
            if itemdc == dc:
                arr.append(items[key]['id'])
    else:
        for key in items:
            arr.append(items[key]['id'])

    return sorted(arr), items
Пример #29
0
def print_report(job_id):
    summary = runner.cmd('jobs.lookup_jid', arg=[job_id])
    report = []
    for minion in summary:
        #      print(len(summary[minion]))
        if len(summary[minion]) > 20:
            if '-' in minion:
                s_minion = minion.split('-')[-2] + '-' + minion.split('-')[-1]
            elif '.' in minion:
                s_minion = minion.split('.')[0]
            else:
                s_minion = minion
        else:
            s_minion = minion
        if 'linux' in nodegroup:
            if len(summary[minion]) == 0:
                info = "System is updated"
                report.append((s_minion, good_minions[minion]['ip'], info))
            else:
                patches = []
                for patch in summary[minion]:
                    patches.append(patch)
                report.append(
                    (s_minion, good_minions[minion]['ip'], '\n'.join(patches)))
        elif 'win' in nodegroup:
            if isinstance(summary[minion], dict):
                patches = []
                for patch in summary[minion].keys():
                    patches.append(summary[minion][patch]['Title'])
                report.append((s_minion, good_minions[minion]['ip'][0],
                               '\n'.join(patches)))
            else:
                info = "System is updated"
                report.append((s_minion, good_minions[minion]['ip'][0], info))
    #print(tabulate(report,headers=['minion id','info'],tablefmt="fancy_grid"))
    print colored(
        "======================================updateinfo===============================================",
        'green')
    print(
        tabulate(sorted(report, key=itemgetter(2)),
                 headers=['minion id', 'ip', 'update info'],
                 tablefmt="grid"))
    print colored(
        "============================================================================================",
        'green')
Пример #30
0
def test_nr_diagram_IP():
    ret = runner.cmd(
        fun="nr.diagram",
        arg=["IP"],
        kwarg={
            "FB": "ceos[12]",
            "outfile": "/tmp/pytest/test_nr_diagram_IP.graphml",
            "tgt": "nrp1",
            "tgt_type": "glob",
        },
    )
    pprint.pprint(ret)
    with open("/tmp/pytest/test_nr_diagram_IP.graphml") as f:
        diagram_content = f.read()
        root = ET.fromstring(diagram_content)

    assert "/tmp/pytest/test_nr_diagram_IP.graphml" in ret and "saved" in ret
    assert "Traceback" not in diagram_content
    assert root and len(root) > 1
Пример #31
0
def pytest_generate_tests(metafunc):
    if "_testinfra_host" in metafunc.fixturenames:
        if (metafunc.config.option.hosts == "*" and
                metafunc.config.option.connection == "salt"):
            import salt.runner
            opts = salt.config.master_config("/etc/salt/master")
            runner = salt.runner.RunnerClient(opts)
            minions_list = runner.cmd("manage.up", [])
            metafunc.config.option.hosts = ",".join(minions_list)
        if metafunc.config.option.hosts is not None:
            params = metafunc.config.option.hosts.split(",")
            ids = params
        elif hasattr(metafunc.module, "testinfra_hosts"):
            params = metafunc.module.testinfra_hosts
            ids = params
        else:
            params = [None]
            ids = ["local"]
        metafunc.parametrize(
            "_testinfra_host", params, ids=ids, scope="module")
Пример #32
0
def runner(fun, arg=None, timeout=5):
    '''
    Execute a runner on the master and return the data from the runnr function

    CLI Example:

    .. code-block:: bash

        salt-ssh '*' publish.runner jobs.lookup_jid 20140916125524463507
    '''
    # Form args as list
    if not isinstance(arg, list):
        arg = [salt.utils.args.yamlify_arg(arg)]
    else:
        arg = [salt.utils.args.yamlify_arg(x) for x in arg]
    if len(arg) == 1 and arg[0] is None:
        arg = []

    # Create and run the runner
    runner = salt.runner.RunnerClient(__opts__['__master_opts__'])
    return runner.cmd(fun, arg)
Пример #33
0
def runner(fun, arg=None, timeout=5):
    '''
    Execute a runner on the master and return the data from the runnr function

    CLI Example:

    .. code-block:: bash

        salt-ssh '*' publish.runner jobs.lookup_jid 20140916125524463507
    '''
    # Form args as list
    if not isinstance(arg, list):
        arg = [salt.utils.args.yamlify_arg(arg)]
    else:
        arg = [salt.utils.args.yamlify_arg(x) for x in arg]
    if len(arg) == 1 and arg[0] is None:
        arg = []

    # Create and run the runner
    runner = salt.runner.RunnerClient(__opts__['__master_opts__'])
    return runner.cmd(fun, arg)
Пример #34
0
def test_runner_nr_cfg_fromdir_ret_struct_list():
    ret = runner.cmd(
        fun="nr.cfg",
        arg=[],
        kwarg={
            "fromdir": "salt://templates/per_host_cfg_runner_cfg_test/",
            "plugin": "netmiko",
            "progress": False,
            "interactive": False,
            "FB": "ceos*",
            "ret_struct": "list",
        },
    )    
    pprint.pprint(ret)
    assert isinstance(ret, list)
    assert len(ret) == 2
    for result in ret:
        assert "host" in result
        assert not result["exception"]
        assert result["failed"] == False
        assert "minion_id" in result
Пример #35
0
def test_runner_nr_cfg_fromdir():
    ret = runner.cmd(
        fun="nr.cfg",
        arg=[],
        kwarg={
            "fromdir": "salt://templates/per_host_cfg_runner_cfg_test/",
            "plugin": "netmiko",
            "progress": False,
            "interactive": False,
            "FB": "ceos*"
        },
    )    
    pprint.pprint(ret)
    assert isinstance(ret, dict)
    assert len(ret) == 2
    for host_name, results in ret.items():
        assert len(results) == 1
        for result in results:
            assert "ceos" in result["result"]
            assert not result["exception"]
            assert result["failed"] == False
            assert "minion_id" in result
Пример #36
0
def test_runner_nr_cfg_fromdir_ret_struct_list_table():
    ret = runner.cmd(
        fun="nr.cfg",
        arg=[],
        kwarg={
            "fromdir": "salt://templates/per_host_cfg_runner_cfg_test/",
            "plugin": "netmiko",
            "progress": False,
            "interactive": False,
            "FB": "ceos*",
            "ret_struct": "list",
            "table": "brief",
            "tgt": "nrp1",
            "tgt_type": "glob",
        },
    )    
    pprint.pprint(ret)
    assert isinstance(ret, list)
    assert len(ret) == 1
    for result in ret:
        assert "Traceback" not in result
        assert isinstance(result, str)
Пример #37
0
def test_nr_diagram_IP_save_data_true():
    ret = runner.cmd(
        fun="nr.diagram",
        arg=["IP"],
        kwarg={
            "FB": "ceos[12]",
            "outfile": "/tmp/pytest/test_nr_diagram_IP_save_data_true.graphml",
            "save_data": True,
            "tgt": "nrp1",
            "tgt_type": "glob",
        },
    )

    pprint.pprint(ret)
    with open("/tmp/pytest/test_nr_diagram_IP_save_data_true.graphml") as f:
        diagram_content = f.read()
        root = ET.fromstring(diagram_content)

    assert "/tmp/pytest/test_nr_diagram_IP_save_data_true.graphml" in ret and "saved" in ret
    assert "Traceback" not in diagram_content
    assert root and len(root) > 1
    assert len(
        [i for i in os.listdir("/tmp/pytest/") if i.startswith("IP_Data")]) > 0
Пример #38
0
 def runOrch(self, runner, tmpData, count):
     with open('/srv/salt/loot.sls', 'w+') as tmpFile:
         yaml.dump(tmpData, tmpFile, default_flow_style=False)
     ret = None
     trys = 0
     while ret == None or trys < 3:
         try:
             ret = runner.cmd('state.orchestrate', ['loot'],
                              print_event=False)
         except:
             ret = None
         trys = trys + 1
         if ret == None or not self.isMinionConnected(ret, count):
             while table.checkTableJobs():
                 time.sleep(2)
         else:
             break
     if ret == None:
         self.writeOuput(
             "Salt Master disconnected, cannot complete installation")
         return False
     else:
         return self.checkSaltDeploy(ret, count)
Пример #39
0
def get_running_jobs_info():
    master_opts = salt.config.client_config('/etc/salt/master')
    runner= salt.runner.RunnerClient(master_opts)
    resp = runner.cmd('jobs.active',print_event=False)
    return len(resp),resp
Пример #40
0
def start(token,
          aliases,
          valid_users,
          valid_commands,
          control=False,
          tag='salt/engines/slack'):
    '''
    Listen to Slack events and forward them to Salt
    '''
    if __opts__.get('__role') == 'master':
        fire_master = salt.utils.event.get_master_event(
            __opts__,
            __opts__['sock_dir']).fire_event
    else:
        fire_master = None

    def fire(tag, msg):
        if fire_master:
            fire_master(msg, tag)
        else:
            __salt__['event.send'](tag, msg)

    if not token:
        log.debug('Slack Bot token not found')
        return
    all_users = _get_users(token)

    sc = slackclient.SlackClient(token)
    slack_connect = sc.rtm_connect()

    runner_functions = sorted(salt.runner.Runner(__opts__).functions)

    if slack_connect:
        while True:
            _msg = sc.rtm_read()
            for _m in _msg:
                if 'type' in _m:
                    if _m['type'] == 'message':
                        # Find the channel where the message came from
                        channel = sc.server.channels.find(_m['channel'])

                        # Edited messages have text in message
                        _text = _m.get('text', None) or _m.get('message', {}).get('text', None)
                        if _text:
                            if _text.startswith('!') and control:

                                # Ensure the user is allowed to run commands
                                if valid_users:
                                    log.debug('{0} {1}'.format(all_users, _m['user']))
                                    if _m['user'] not in valid_users and all_users.get(_m['user'], None) not in valid_users:
                                        channel.send_message('{0} not authorized to run Salt commands'.format(all_users[_m['user']]))
                                        return

                                # Trim the ! from the front
                                # cmdline = _text[1:].split(' ', 1)
                                cmdline = shlex.split(_text[1:])
                                cmd = cmdline[0]
                                args = []
                                kwargs = {}

                                # Ensure the command is allowed
                                if valid_commands:
                                    if cmd not in valid_commands:
                                        channel.send_message('Using {0} is not allowed.'.format(cmd))
                                        return

                                if len(cmdline) > 1:
                                    for item in cmdline[1:]:
                                        if '=' in item:
                                            (key, value) = item.split('=', 1)
                                            kwargs[key] = value
                                        else:
                                            args.append(item)

                                if 'target' not in kwargs:
                                    target = '*'
                                else:
                                    target = kwargs['target']
                                    del kwargs['target']

                                ret = {}
                                if aliases and isinstance(aliases, dict) and cmd in aliases.keys():
                                    salt_cmd = aliases[cmd].get('cmd')

                                    if 'type' in aliases[cmd]:
                                        if aliases[cmd]['type'] == 'runner':
                                            runner = salt.runner.RunnerClient(__opts__)
                                            ret = runner.cmd(salt_cmd, arg=args, kwarg=kwargs)
                                    else:
                                        local = salt.client.LocalClient()
                                        ret = local.cmd('{0}'.format(target), salt_cmd, args, kwargs)

                                elif cmd in runner_functions:
                                    runner = salt.runner.RunnerClient(__opts__)
                                    ret = runner.cmd(cmd, arg=args, kwarg=kwargs)

                                # default to trying to run as a client module.
                                else:
                                    local = salt.client.LocalClient()
                                    ret = local.cmd('{0}'.format(target), cmd, args, kwargs)

                                if ret:
                                    pp = pprint.PrettyPrinter(indent=4)
                                    return_text = pp.pformat(ret)
                                    # Slack messages need to be under 4000 characters.
                                    length = 4000
                                    if len(return_text) >= length:
                                        channel.send_message(return_text[0:3999])
                                        channel.send_message('Returned first 4k characters.')
                                    else:
                                        channel.send_message(return_text)
                            else:
                                # Fire event to event bus
                                fire('{0}/{1}'.format(tag, _m['type']), _m)
                    else:
                        # Fire event to event bus
                        fire('{0}/{1}'.format(tag, _m['type']), _m)
Пример #41
0
def start(token,
          room='salt',
          aliases=None,
          valid_users=None,
          valid_commands=None,
          control=False,
          trigger="!",
          tag='salt/engines/hipchat/incoming'):
    '''
    Listen to Hipchat messages and forward them to Salt
    '''
    target_room = None

    if __opts__.get('__role') == 'master':
        fire_master = salt.utils.event.get_master_event(
            __opts__,
            __opts__['sock_dir']).fire_event
    else:
        fire_master = None

    def fire(tag, msg):
        '''
        fire event to salt bus
        '''

        if fire_master:
            fire_master(msg, tag)
        else:
            __salt__['event.send'](tag, msg)

    def _eval_bot_mentions(all_messages, trigger):
        ''' yield partner message '''
        for message in all_messages:
            message_text = message['message']
            if message_text.startswith(trigger):
                fire(tag, message)
                text = message_text.replace(trigger, '').strip()
                yield message['from']['mention_name'], text

    if not token:
        raise UserWarning("Hipchat token not found")

    runner_functions = sorted(salt.runner.Runner(__opts__).functions)

    hipc = hypchat.HypChat(token)
    if not hipc:
        raise UserWarning("Unable to connect to hipchat")

    log.debug('Connected to Hipchat')
    all_rooms = hipc.rooms(max_results=1000)['items']
    for a_room in all_rooms:
        if a_room['name'] == room:
            target_room = a_room
    if not target_room:
        log.debug("Unable to connect to room {0}".format(room))
        # wait for a bit as to not burn through api calls
        time.sleep(30)
        raise UserWarning("Unable to connect to room {0}".format(room))

    after_message_id = target_room.latest(maxResults=1)['items'][0]['id']

    while True:
        try:
            new_messages = target_room.latest(
                not_before=after_message_id)['items']
        except hypchat.requests.HttpServiceUnavailable:
            time.sleep(15)
            continue

        after_message_id = new_messages[-1]['id']
        for partner, text in _eval_bot_mentions(new_messages[1:], trigger):
            # bot summoned by partner

            if not control:
                log.debug("Engine not configured for control")
                return

            # Ensure the user is allowed to run commands
            if valid_users:
                if partner not in valid_users:
                    target_room.message('{0} not authorized to run Salt commands'.format(partner))
                    return

            args = []
            kwargs = {}

            cmdline = salt.utils.shlex_split(text)
            cmd = cmdline[0]

            # Evaluate aliases
            if aliases and isinstance(aliases, dict) and cmd in aliases.keys():
                cmdline = aliases[cmd].get('cmd')
                cmdline = salt.utils.shlex_split(cmdline)
                cmd = cmdline[0]

            # Parse args and kwargs
            if len(cmdline) > 1:
                for item in cmdline[1:]:
                    if '=' in item:
                        (key, value) = item.split('=', 1)
                        kwargs[key] = value
                    else:
                        args.append(item)

            # Check for target. Otherwise assume *
            if 'target' not in kwargs:
                target = '*'
            else:
                target = kwargs['target']
                del kwargs['target']

            # Ensure the command is allowed
            if valid_commands:
                if cmd not in valid_commands:
                    target_room.message('Using {0} is not allowed.'.format(cmd))
                    return

            ret = {}
            if cmd in runner_functions:
                runner = salt.runner.RunnerClient(__opts__)
                ret = runner.cmd(cmd, arg=args, kwarg=kwargs)

            # Default to trying to run as a client module.
            else:
                local = salt.client.LocalClient()
                ret = local.cmd('{0}'.format(target), cmd, args, kwargs)

            tmp_path_fn = salt.utils.files.mkstemp()
            with salt.utils.fopen(tmp_path_fn, 'w+') as fp_:
                fp_.write(json.dumps(ret, sort_keys=True, indent=4))
            message_string = '@{0} Results for: {1} {2} {3} on {4}'.format(partner, cmd, args, kwargs, target)
            _publish_file(token, room, tmp_path_fn, message=message_string)
            salt.utils.safe_rm(tmp_path_fn)
        time.sleep(5)
Пример #42
0
def start(token,
          aliases=None,
          valid_users=None,
          valid_commands=None,
          control=False,
          trigger="!",
          tag='salt/engines/slack'):
    '''
    Listen to Slack events and forward them to Salt
    '''
    if __opts__.get('__role') == 'master':
        fire_master = salt.utils.event.get_master_event(
            __opts__,
            __opts__['sock_dir']).fire_event
    else:
        fire_master = None

    def fire(tag, msg):
        '''
        Fire event to salt bus
        '''
        if fire_master:
            fire_master(msg, tag)
        else:
            __salt__['event.send'](tag, msg)

    if not token:
        raise UserWarning('Slack Bot token not found')

    all_users = _get_users(token)

    sc = slackclient.SlackClient(token)
    slack_connect = sc.rtm_connect()
    log.debug('connected to slack')

    runner_functions = sorted(salt.runner.Runner(__opts__).functions)

    if slack_connect:
        while True:
            _msg = sc.rtm_read()
            for _m in _msg:
                if 'type' in _m:
                    if _m['type'] == 'message':
                        # Find the channel where the message came from
                        channel = sc.server.channels.find(_m['channel'])

                        # Edited messages have text in message
                        _text = _m.get('text', None) or _m.get('message', {}).get('text', None)

                        # Convert UTF to string
                        _text = json.dumps(_text)
                        _text = yaml.safe_load(_text)

                        if _text:
                            if _text.startswith(trigger) and control:

                                # Ensure the user is allowed to run commands
                                if valid_users:
                                    log.debug('{0} {1}'.format(all_users, _m['user']))
                                    if _m['user'] not in valid_users and all_users.get(_m['user'], None) not in valid_users:
                                        channel.send_message('{0} not authorized to run Salt commands'.format(all_users[_m['user']]))
                                        return

                                # Trim the ! from the front
                                # cmdline = _text[1:].split(' ', 1)
                                cmdline = salt.utils.shlex_split(_text[len(trigger):])

                                # Remove slack url parsing
                                #  Translate target=<http://host.domain.net|host.domain.net>
                                #  to target=host.domain.net
                                cmdlist = []
                                for cmditem in cmdline:
                                    pattern = r'(?P<begin>.*)(<.*\|)(?P<url>.*)(>)(?P<remainder>.*)'
                                    m = re.match(pattern, cmditem)
                                    if m:
                                        origtext = m.group('begin') + m.group('url') + m.group('remainder')
                                        cmdlist.append(origtext)
                                    else:
                                        cmdlist.append(cmditem)
                                cmdline = cmdlist

                                cmd = cmdline[0]
                                args = []
                                kwargs = {}

                                # Ensure the command is allowed
                                if valid_commands:
                                    if cmd not in valid_commands:
                                        channel.send_message('Using {0} is not allowed.'.format(cmd))
                                        return

                                # Evaluate aliases
                                if aliases and isinstance(aliases, dict) and cmd in aliases.keys():
                                    cmdline = aliases[cmd].get('cmd')
                                    cmdline = salt.utils.shlex_split(cmdline)
                                    cmd = cmdline[0]

                                # Parse args and kwargs
                                if len(cmdline) > 1:
                                    for item in cmdline[1:]:
                                        if '=' in item:
                                            (key, value) = item.split('=', 1)
                                            kwargs[key] = value
                                        else:
                                            args.append(item)

                                # Check for target. Otherwise assume *
                                if 'target' not in kwargs:
                                    target = '*'
                                else:
                                    target = kwargs['target']
                                    del kwargs['target']

                                ret = {}

                                if cmd in runner_functions:
                                    runner = salt.runner.RunnerClient(__opts__)
                                    ret = runner.cmd(cmd, arg=args, kwarg=kwargs)

                                # Default to trying to run as a client module.
                                else:
                                    local = salt.client.LocalClient()
                                    ret = local.cmd('{0}'.format(target), cmd, args, kwargs)

                                if ret:
                                    return_text = json.dumps(ret, sort_keys=True, indent=1)
                                    ts = time.time()
                                    st = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d%H%M%S%f')
                                    filename = 'salt-results-{0}.yaml'.format(st)
                                    result = sc.api_call(
                                        "files.upload", channels=_m['channel'], filename=filename,
                                        content=return_text
                                    )
                                    # Handle unicode return
                                    result = json.dumps(result)
                                    result = yaml.safe_load(result)
                                    if 'ok' in result and result['ok'] is False:
                                        channel.send_message('Error: {0}'.format(result['error']))
                            else:
                                # Fire event to event bus
                                fire('{0}/{1}'.format(tag, _m['type']), _m)
                    else:
                        # Fire event to event bus
                        fire('{0}/{1}'.format(tag, _m['type']), _m)
    else:
        raise UserWarning("Could not connect to slack")
Пример #43
0
def _salt(fun, *args, **kw):
    '''Execute a salt function on a specific minion

    Special kwargs:

            salt_target
                target to exec things on
            salt_timeout
                timeout for jobs
            salt_job_poll
                poll interval to wait for job finish result
    '''
    try:
        poll = kw.pop('salt_job_poll')
    except KeyError:
        poll = 0.1
    try:
        target = kw.pop('salt_target')
    except KeyError:
        target = None
    try:
        timeout = int(kw.pop('salt_timeout'))
    except (KeyError, ValueError):
        # try to has some low timeouts for very basic commands
        timeout = __FUN_TIMEOUT.get(
            fun,
            900  # wait up to 15 minutes for the default timeout
        )
    try:
        kwargs = kw.pop('kwargs')
    except KeyError:
        kwargs = {}
    if not target:
        infos = get_configured_provider()
        if not infos:
            return
        target = infos['target']
    laps = time.time()
    cache = False
    if fun in __CACHED_FUNS:
        cache = True
        laps = laps // __CACHED_FUNS[fun]
    try:
        sargs = json.dumps(args)
    except TypeError:
        sargs = ''
    try:
        skw = json.dumps(kw)
    except TypeError:
        skw = ''
    try:
        skwargs = json.dumps(kwargs)
    except TypeError:
        skwargs = ''
    cache_key = (laps, target, fun, sargs, skw, skwargs)
    if not cache or (cache and (not cache_key in __CACHED_CALLS)):
        conn = _client()
        runner = _runner()
        rkwargs = kwargs.copy()
        rkwargs['timeout'] = timeout
        rkwargs.setdefault('expr_form', 'list')
        kwargs.setdefault('expr_form', 'list')
        jid = conn.cmd_async(tgt=target,
                             fun=fun,
                             arg=args,
                             kwarg=kw,
                             **rkwargs)
        cret = conn.cmd(tgt=target,
                        fun='saltutil.find_job',
                        arg=[jid],
                        timeout=10,
                        **kwargs)
        running = bool(cret.get(target, False))
        endto = time.time() + timeout
        while running:
            rkwargs = {
                'tgt': target,
                'fun': 'saltutil.find_job',
                'arg': [jid],
                'timeout': 10
            }
            cret = conn.cmd(**rkwargs)
            running = bool(cret.get(target, False))
            if not running:
                break
            if running and (time.time() > endto):
                raise Exception('Timeout {0}s for {1} is elapsed'.format(
                    timeout, pformat(rkwargs)))
            time.sleep(poll)
        # timeout for the master to return data about a specific job
        wait_for_res = float({
            'test.ping': '5',
        }.get(fun, '120'))
        while wait_for_res:
            wait_for_res -= 0.5
            cret = runner.cmd(
                'jobs.lookup_jid',
                [jid, {'__kwarg__': True, 'output': False}])
            if target in cret:
                ret = cret[target]
                break
            # special case, some answers may be crafted
            # to handle the unresponsivness of a specific command
            # which is also meaningfull, eg a minion not yet provisionned
            if fun in ['test.ping'] and not wait_for_res:
                ret = {
                    'test.ping': False,
                }.get(fun, False)
            time.sleep(0.5)
        try:
            if 'is not available.' in ret:
                raise SaltCloudSystemExit(
                    'module/function {0} is not available'.format(fun))
        except SaltCloudSystemExit:
            raise
        except TypeError:
            pass
        if cache:
            __CACHED_CALLS[cache_key] = ret
    elif cache and cache_key in __CACHED_CALLS:
        ret = __CACHED_CALLS[cache_key]
    return ret
Пример #44
0
 def _get_up_minions():
     up_minions = set(runner.cmd("manage.up", []))
     if minion_set:
         return up_minions.intersection(minion_set)
     else:
         return up_minions
Пример #45
0
Файл: lxc.py Проект: DaveQB/salt
def _salt(fun, *args, **kw):
    '''Execute a salt function on a specific minion

    Special kwargs:

            salt_target
                target to exec things on
            salt_timeout
                timeout for jobs
            salt_job_poll
                poll interval to wait for job finish result
    '''
    try:
        poll = kw.pop('salt_job_poll')
    except KeyError:
        poll = 0.1
    try:
        target = kw.pop('salt_target')
    except KeyError:
        target = None
    try:
        timeout = int(kw.pop('salt_timeout'))
    except (KeyError, ValueError):
        # try to has some low timeouts for very basic commands
        timeout = __FUN_TIMEOUT.get(
            fun,
            900  # wait up to 15 minutes for the default timeout
        )
    try:
        kwargs = kw.pop('kwargs')
    except KeyError:
        kwargs = {}
    if not target:
        infos = get_configured_provider()
        if not infos:
            return
        target = infos['target']
    laps = time.time()
    cache = False
    if fun in __CACHED_FUNS:
        cache = True
        laps = laps // __CACHED_FUNS[fun]
    try:
        sargs = json.dumps(args)
    except TypeError:
        sargs = ''
    try:
        skw = json.dumps(kw)
    except TypeError:
        skw = ''
    try:
        skwargs = json.dumps(kwargs)
    except TypeError:
        skwargs = ''
    cache_key = (laps, target, fun, sargs, skw, skwargs)
    if not cache or (cache and (cache_key not in __CACHED_CALLS)):
        conn = _client()
        runner = _runner()
        rkwargs = kwargs.copy()
        rkwargs['timeout'] = timeout
        rkwargs.setdefault('expr_form', 'list')
        kwargs.setdefault('expr_form', 'list')
        ping_retries = 0
        # the target(s) have environ one minute to respond
        # we call 60 ping request, this prevent us
        # from blindly send commands to unmatched minions
        ping_max_retries = 60
        ping = True
        # do not check ping... if we are pinguing
        if fun == 'test.ping':
            ping_retries = ping_max_retries + 1
        # be sure that the executors are alive
        while ping_retries <= ping_max_retries:
            try:
                if ping_retries > 0:
                    time.sleep(1)
                pings = conn.cmd(tgt=target,
                                 timeout=10,
                                 fun='test.ping')
                values = list(pings.values())
                if not values:
                    ping = False
                for v in values:
                    if v is not True:
                        ping = False
                if not ping:
                    raise ValueError('Unreachable')
                break
            except Exception:
                ping = False
                ping_retries += 1
                log.error('{0} unreachable, retrying'.format(target))
        if not ping:
            raise SaltCloudSystemExit('Target {0} unreachable'.format(target))
        jid = conn.cmd_async(tgt=target,
                             fun=fun,
                             arg=args,
                             kwarg=kw,
                             **rkwargs)
        cret = conn.cmd(tgt=target,
                        fun='saltutil.find_job',
                        arg=[jid],
                        timeout=10,
                        **kwargs)
        running = bool(cret.get(target, False))
        endto = time.time() + timeout
        while running:
            rkwargs = {
                'tgt': target,
                'fun': 'saltutil.find_job',
                'arg': [jid],
                'timeout': 10
            }
            cret = conn.cmd(**rkwargs)
            running = bool(cret.get(target, False))
            if not running:
                break
            if running and (time.time() > endto):
                raise Exception('Timeout {0}s for {1} is elapsed'.format(
                    timeout, pformat(rkwargs)))
            time.sleep(poll)
        # timeout for the master to return data about a specific job
        wait_for_res = float({
            'test.ping': '5',
        }.get(fun, '120'))
        while wait_for_res:
            wait_for_res -= 0.5
            cret = runner.cmd(
                'jobs.lookup_jid',
                [jid, {'__kwarg__': True}])
            if target in cret:
                ret = cret[target]
                break
            # recent changes
            elif 'data' in cret and 'outputter' in cret:
                ret = cret['data']
                break
            # special case, some answers may be crafted
            # to handle the unresponsivness of a specific command
            # which is also meaningful, e.g. a minion not yet provisioned
            if fun in ['test.ping'] and not wait_for_res:
                ret = {
                    'test.ping': False,
                }.get(fun, False)
            time.sleep(0.5)
        try:
            if 'is not available.' in ret:
                raise SaltCloudSystemExit(
                    'module/function {0} is not available'.format(fun))
        except SaltCloudSystemExit:
            raise
        except TypeError:
            pass
        if cache:
            __CACHED_CALLS[cache_key] = ret
    elif cache and cache_key in __CACHED_CALLS:
        ret = __CACHED_CALLS[cache_key]
    return ret
Пример #46
0
def genrepo(name, force=False, allow_empty=False):
    '''
    Refresh the winrepo.p file of the repository (salt-run winrepo.genrepo)

    If ``force`` is ``True`` no checks will be made and the repository will be
    generated if ``allow_empty`` is ``True`` then the state will not return an
    error if there are 0 packages,

    .. note::

        This state only loads on minions that have the ``roles: salt-master``
        grain set.

    Example:

    .. code-block:: yaml

        winrepo:
          winrepo.genrepo
    '''

    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}

    master_config = salt.config.master_config(
        os.path.join(salt.syspaths.CONFIG_DIR, 'master')
    )

    if 'win_repo' in master_config:
        salt.utils.warn_until(
            'Nitrogen',
            'The \'win_repo\' config option is deprecated, please use '
            '\'winrepo_dir\' instead.'
        )
        winrepo_dir = master_config['win_repo']
    else:
        winrepo_dir = master_config['winrepo_dir']

    if 'win_repo_mastercachefile' in master_config:
        salt.utils.warn_until(
            'Nitrogen',
            'The \'win_repo_mastercachefile\' config option is deprecated, '
            'please use \'winrepo_cachefile\' instead.'
        )
        winrepo_cachefile = master_config['win_repo_mastercachefile']
    else:
        winrepo_cachefile = master_config['winrepo_cachefile']

    # We're actually looking for the full path to the cachefile here, so
    # prepend the winrepo_dir
    winrepo_cachefile = os.path.join(winrepo_dir, winrepo_cachefile)

    # Check if the winrepo directory exists
    # if not search for a file with a newer mtime than the winrepo_cachefile file
    execute = False
    if not force:
        if not os.path.exists(winrepo_dir):
            ret['result'] = False
            ret['comment'] = '{0} is missing'.format(winrepo_dir)
            return ret
        elif not os.path.exists(winrepo_cachefile):
            execute = True
            ret['comment'] = '{0} is missing'.format(winrepo_cachefile)
        else:
            winrepo_cachefile_mtime = os.stat(winrepo_cachefile)[stat.ST_MTIME]
            for root, dirs, files in os.walk(winrepo_dir):
                for name in itertools.chain(files, dirs):
                    full_path = os.path.join(root, name)
                    if os.stat(full_path)[stat.ST_MTIME] > winrepo_cachefile_mtime:
                        ret['comment'] = 'mtime({0}) < mtime({1})'.format(winrepo_cachefile, full_path)
                        execute = True
                        break

    if __opts__['test']:
        ret['result'] = None
        return ret

    if not execute and not force:
        return ret

    runner = salt.runner.RunnerClient(master_config)
    runner_ret = runner.cmd('winrepo.genrepo', [])
    ret['changes'] = {'winrepo': runner_ret}
    if isinstance(runner_ret, dict) and runner_ret == {} and not allow_empty:
        os.remove(winrepo_cachefile)
        ret['result'] = False
        ret['comment'] = 'winrepo.genrepo returned empty'
    return ret