Refactor working with Networks and Pinger class
- Mapper moved to separate module
- Other modules can use Mapper to get desired networks
- salt_master is now a separate single instance
- Updated file handling on salt
- ping.py, an scripted flexible interface to ping command
multithreaded ping execution, 15 at once
- New commands in network: 'ping' and 'list'
- New error when runtime has no network listed in reclass
Fixes:
- Master node code handling
- Unknown node codes detection
- Proper node code search and handling
- File upload procedures updated
- Packages report fix
Change-Id: I5959210aed53b20b04b05ea880218e93239bb661
Related-PROD: PROD-28199
diff --git a/scripts/ping.py b/scripts/ping.py
new file mode 100644
index 0000000..4e2778d
--- /dev/null
+++ b/scripts/ping.py
@@ -0,0 +1,159 @@
+import json
+import os
+import platform
+import sys
+from copy import deepcopy
+from multiprocessing.dummy import Pool
+from subprocess import PIPE, Popen
+
+_os = platform.system()
+_packets = {}
+
+_defaults = {
+ "ip": None,
+ "size": 0,
+ "fragmentation": False,
+ "count": 1,
+ "exit_timeout": 1,
+ "response_timeout": 1,
+ "numeric": True
+}
+
+_help_message = \
+ "Invalid parameters. Use: 'ping.py [PKT_SIZE] <IP>' or 'ping.py n.json'\n"
+
+_template = {
+ "returncode": -1,
+ "stdout": "",
+ "stderr": ""
+}
+
+
+def shell(command):
+ _ps = Popen(
+ " ".join(command),
+ shell=True,
+ stdout=PIPE,
+ stderr=PIPE
+ )
+ _out = _ps.communicate()
+ _err = _out[1]
+ _out = _out[0]
+ return _ps.returncode, _out, _err
+
+
+def write_help():
+ _t = deepcopy(_template)
+ _t["returncode"] = 1
+ _t["stderr"] = _help_message
+ write_outcome(_t)
+
+
+def write_outcome(_params):
+ sys.stdout.write(json.dumps(_params))
+
+
+def do_ping(_params):
+ # Load params and defaults
+ _d = deepcopy(_defaults)
+ for key in _params:
+ _d[key] = _params[key]
+
+ # Build cmd
+ _cmd = ["ping"]
+ if _os == "Darwin":
+ if not _d["fragmentation"]:
+ _cmd.append("-D")
+ if _d["exit_timeout"]:
+ _cmd += ["-t", str(_d["exit_timeout"])]
+ elif _os == "Linux":
+ if not _d["fragmentation"]:
+ _cmd += ["-M", "do"]
+ if _d["exit_timeout"]:
+ _cmd += ["-w", str(_d["exit_timeout"])]
+ else:
+ # Windows or other OS
+ _t = deepcopy(_template)
+ _t["returncode"] = 1
+ _t["stderr"] = \
+ "ping.py: '{}' support not implemented".format(_os)
+ write_outcome(_t)
+ sys.exit(1)
+
+ if _d["size"]:
+ _cmd += ["-s", str(_d["size"])]
+ if _d["count"]:
+ _cmd += ["-c", str(_d["count"])]
+ if _d["numeric"]:
+ _cmd.append("-n")
+ if _d["response_timeout"]:
+ _cmd += ["-W", str(_d["response_timeout"])]
+
+ _cmd.append(_d["ip"])
+ # sys.stdout.write("# {}\n".format(" ".join(_cmd)))
+ _r, _out, _err = shell(_cmd)
+
+ # TODO: parse results, latency, etc
+ _t = deepcopy(_template)
+ _t["returncode"] = _r
+ _t["stdout"] = _out
+ _t["stderr"] = _err
+ _params.update(_t)
+ return _params
+
+
+def load_targets(filename):
+ # load target ips from json
+ with open(filename, "r") as f:
+ j = json.load(f)
+
+ return j
+
+
+if len(sys.argv) < 2:
+ # no params given
+ write_help()
+elif len(sys.argv) < 3:
+ # one param: decide if it json file or IP
+ _arg = sys.argv[1]
+ if os.path.isfile(_arg):
+ _packets = load_targets(_arg)
+ # up to 15 packets at once
+ pool = Pool(15)
+ # prepare threaded map
+ _param_map = []
+ for _node, _data in _packets.iteritems():
+ if isinstance(_data, list):
+ for target in _data:
+ _param_map.append(target)
+ elif isinstance(_data, dict):
+ _param_map.append(_data)
+ else:
+ _t = deepcopy(_template)
+ _t["returncode"] = 1
+ _t["stderr"] = \
+ "TypeError: 'list' or 'dict' expected. " \
+ "Got '{}': '{}'".format(
+ type(_data).__name__,
+ _data
+ )
+ _packets[_node] = _t
+ _threaded_out = pool.map(do_ping, _param_map)
+ for _out in _threaded_out:
+ if isinstance(_packets[_out["tgt_host"]], dict):
+ _packets[_out["tgt_host"]] = _out
+ elif isinstance(_packets[_out["tgt_host"]], list):
+ _packets[_out["tgt_host"]][_out["ip_index"]] = _out
+ sys.stdout.write(json.dumps(_packets))
+ else:
+ # IP given
+ _ip = sys.argv[1]
+ write_outcome(do_ping(_ip))
+elif len(sys.argv) < 4:
+ # two params: size and IP
+ _s = sys.argv[1]
+ _ip = sys.argv[2]
+ write_outcome(do_ping(_ip, size=_s))
+else:
+ # too many params given
+ write_help()