Advertisement
moneron

Pnetlab Mikrotik script modified

Sep 3rd, 2021 (edited)
2,146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.47 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. # scripts/config_xrv.py
  4. #
  5. # Import/Export script for vIOS.
  6. #
  7. # @author Andrea Dainese <[email protected]>
  8. # @author Alain Degreffe <[email protected]>
  9. # @copyright 2014-2016 Andrea Dainese
  10. # @copyright 2017-2018 Alain Degreffe
  11. # @license BSD-3-Clause https://github.com/dainok/unetlab/blob/master/LICENSE
  12. # @link http://www.eve-ng.net/
  13. # @version 20181203
  14.  
  15. import getopt
  16. import multiprocessing
  17. import os
  18. import re
  19. import sys
  20. import time
  21.  
  22. import pexpect
  23.  
  24. OPTS = None
  25. ARGS = None
  26.  
  27. IP = '127.0.0.1'
  28. PORT = 23
  29.  
  30. USER_NAME = 'admin'
  31. USER_PASS = ''
  32.  
  33. CONTIMEOUT = 5 #Maximum time for console connection
  34. EXPTIMEOUT = 20 #Maximum time for each short expect
  35. LONGTIMEOUT = 30 # Maximum time for each long expect
  36. TIMEOUT = 60 # Maximum run time (CONTIMEOUT is included)
  37.  
  38. ACTION = None
  39. FILENAME = None
  40.  
  41. MTK_PROMPT = r"\]\s> "
  42.  
  43. def usage():
  44.     ' Usage '
  45.     print('Usage: %s <standard options>' %(sys.argv[0]));
  46.     print('Standard Options:');
  47.     print('-a <s>    *Action can be:')
  48.     print('           - get: get the startup-configuration and push it to a file')
  49.     print('           - put: put the file as startup-configuration')
  50.     print('-f <s>    *File');
  51.     print('-p <n>    *Console port');
  52.     print('-t <n>     Timeout (default = %i)' %(TIMEOUT));
  53.     print('-i <ip>    Router\'s ip (default = 127.0.0.1)');
  54.     print('* Mandatory option')
  55.  
  56. def now():
  57.     ' Return current UNIX time in milliseconds '
  58.     return int(round(time.time() * 1000))
  59.  
  60. def node_login(handler):
  61.     ' Send an empty line, and wait for the login prompt '
  62.     i = -1
  63.     while i == -1:
  64.         try:
  65.             handler.send('\r\n')
  66.             i = handler.expect(['Login: ', MTK_PROMPT], timeout=CONTIMEOUT)
  67.         except pexpect.exceptions.TIMEOUT:
  68.             i = -1
  69.     if i == 0:
  70.         # Need to send username and password
  71.         handler.send(USER_NAME + '+c512wt')
  72.         handler.send('\r\n')
  73.         try:
  74.             handler.expect('Password:', timeout=EXPTIMEOUT)
  75.         except pexpect.exceptions.TIMEOUT:
  76.             print('ERROR: error waiting for "Password:" prompt.')
  77.             node_quit(handler)
  78.             return False
  79.         handler.send(USER_PASS)
  80.         handler.send('\r\n')
  81.         try:
  82.             _license = handler.expect([MTK_PROMPT, r"\[Y/n\]"], timeout=EXPTIMEOUT)
  83.             if _license == 1:
  84.                 handler.send('n\r\n')
  85.                 time.sleep(3)
  86.                 handler.send('\x03')
  87.                 handler.expect(MTK_PROMPT, timeout=EXPTIMEOUT)
  88.         except pexpect.exceptions.TIMEOUT:
  89.             print('ERROR: error waiting for "%s" prompt.' % (MTK_PROMPT))
  90.             node_quit(handler)
  91.             return False
  92.         time.sleep(1)
  93.     elif i == 1:
  94.         #Already logged in on serial console
  95.         time.sleep(1)
  96.     else:
  97.         # Unexpected output
  98.         node_quit(handler)
  99.         return False
  100.     return True
  101.  
  102. def node_quit(handler):
  103.     ' Quit '
  104.     if handler.isalive():
  105.         handler.send('\x03\x04')
  106.         #handler.send('\r\n')
  107.     handler.close()
  108.  
  109. def clear_buffer(handler):
  110.     ' Clearing all "expect" buffer '
  111.     while True:
  112.         try:
  113.             handler.send("\r\n")
  114.             handler.expect(
  115.                 MTK_PROMPT, timeout=EXPTIMEOUT)
  116.             break
  117.         except pexpect.exceptions.TIMEOUT:
  118.             time.sleep(0.5)
  119.             continue
  120.  
  121. def config_get(handler):
  122.     ' Get '
  123.     clear_buffer(handler)
  124.     handler.send('/export terse\r')
  125.     #handler.send('\r\n')
  126.     time.sleep(5)
  127.     try:
  128.         handler.expect(
  129.             MTK_PROMPT, timeout=LONGTIMEOUT)
  130.     except pexpect.exceptions.TIMEOUT:
  131.         print('ERROR: error waiting for "end" marker.')
  132.         node_quit(handler)
  133.         return False
  134.     clear_buffer(handler)
  135.     _config = re.sub(r"^.*/export\sterse[\r\n]+#", "#", handler.before)
  136.     _config = re.sub(r"[\r\n]{2,}.+$", "\r\n\r\n", _config)
  137.     _config = re.sub(r"[\r\n]+", "\r\n", _config)
  138.     return _config
  139.  
  140. def config_put(handler):
  141.     """
  142.     ' Put '
  143.    clear_buffer(handler)
  144.     handler.send('/system reset-configuration no-defaults=yes')
  145.    handler.send('\r\n')
  146.    time.sleep(3)
  147.    handler.send('y\r\n')
  148.     time.sleep(5)
  149.    try:
  150.        handler.expect(['Login: ', MTK_PROMPT], timeout=LONGTIMEOUT)
  151.    except pexpect.exceptions.TIMEOUT:
  152.        return False
  153.     """
  154.     return True
  155.  
  156. def config_import(handler, config):
  157.     ' Import '
  158.     """
  159.     clear_buffer(handler)
  160.    handler.send('/ip dhcp-client remove numbers=0')
  161.    handler.send('\r\n')"""
  162.     try:
  163.         handler.expect(MTK_PROMPT, timeout=EXPTIMEOUT)
  164.     except pexpect.exceptions.TIMEOUT:
  165.         return False
  166.     configs = re.split(r"\n", config)
  167.     for cmd in configs:
  168.         if cmd == '':
  169.             continue
  170.         handler.send(cmd)
  171.         handler.send('\r\n')
  172.         time.sleep(0.1)
  173.     time.sleep(3)
  174.     handler.send('\x03\x04')
  175.     #handler.send('\r\n')
  176.     try:
  177.         handler.expect(MTK_PROMPT, timeout=EXPTIMEOUT)
  178.     except pexpect.exceptions.TIMEOUT:
  179.         return False
  180.     return True
  181.  
  182. def main(action, filename, port):
  183.     try:
  184.         tmp = CONTIMEOUT
  185.         handler = pexpect.spawnu('telnet %s %i' %(IP, port), maxread=100000)
  186.         handler.crlf = '\r\n'
  187.         while tmp > 0:
  188.             time.sleep(0.1)
  189.             tmp = tmp - 0.1
  190.             if handler.isalive():
  191.                 break
  192.         if action == 'get':
  193.             if handler.isalive() is False:
  194.                 print('ERROR: cannot connect to port "%i".' %(port))
  195.                 node_quit(handler)
  196.                 sys.exit(1)
  197.             lgst = node_login(handler)
  198.             if lgst is False:
  199.                 print('ERROR: failed to login.')
  200.                 node_quit(handler)
  201.                 sys.exit(1)
  202.             config = config_get(handler)
  203.             if config in [False, None]:
  204.                 print('ERROR: failed to retrieve config.')
  205.                 node_quit(handler)
  206.                 sys.exit(1)
  207.             try:
  208.                 fdc = open(filename, 'a')
  209.                 fdc.write(config)
  210.                 fdc.close()
  211.             except:
  212.                 print('ERROR: cannot write config to file.')
  213.                 node_quit(handler)
  214.                 sys.exit(1)
  215.         elif action == 'put':
  216.             if (handler.isalive() != True):
  217.                 print('ERROR: cannot connect to port "%i".' %(port))
  218.                 node_quit(handler)
  219.                 sys.exit(1)
  220.             lgst = node_login(handler)
  221.             if lgst is False:
  222.                 print('ERROR: failed to login.')
  223.                 node_quit(handler)
  224.                 sys.exit(1)
  225.             config_rsc = ''
  226.             with open(filename, 'r') as fileconf:
  227.                 config_rsc = fileconf.read()
  228.                 config_rsc = re.sub(r"\\\n\s+", "", config_rsc)
  229.             config = config_put(handler)
  230.             if config is False:
  231.                 print('ERROR: failed to push config.')
  232.                 node_quit(handler)
  233.                 sys.exit(1)
  234.             # Remove lock file
  235.             lock = '%s/.lock' %(os.path.dirname(filename))
  236.             if os.path.exists(lock):
  237.                 os.remove(lock)
  238.             # Mark as configured
  239.             configured = '%s/.configured' %(os.path.dirname(filename))
  240.             if not os.path.exists(configured):
  241.                 open(configured, 'a').close()
  242.             lgst = node_login(handler)
  243.             if lgst is False:
  244.                 print('ERROR: failed to login.')
  245.                 node_quit(handler)
  246.                 sys.exit(1)
  247.             lgst = config_import(handler, config_rsc)
  248.             if lgst is False:
  249.                 print('ERROR: failed to push config.')
  250.                 node_quit(handler)
  251.                 sys.exit(1)
  252.         node_quit(handler)
  253.         sys.exit(0)
  254.     except Exception as e:
  255.         print('ERROR: got an exception')
  256.         print(type(e)) # the exception instance
  257.         print(e.args) # arguments stored in .args
  258.         print(e) # __str__ allows args to be printed directly,
  259.         node_quit(handler)
  260.         sys.exit(1)
  261.  
  262. if __name__ == '__main__':
  263.     try:
  264.         OPTS, ARGS = getopt.getopt(
  265.             sys.argv[1:], 'a:p:t:f:i', ['action=', 'port=', 'timeout=', 'file=', 'address='])
  266.     except getopt.GetoptError:
  267.         usage()
  268.         sys.exit(3)
  269.  
  270.     for o, a in OPTS:
  271.         if o in ['-a', '--action']:
  272.             ACTION = a
  273.         elif o in ['-f', '--file']:
  274.             FILENAME = a
  275.         elif o in ['-p', '--port']:
  276.             try:
  277.                 PORT = int(a)
  278.             except TypeError:
  279.                 PORT = -1
  280.         elif o in ['-t', '--timeout']:
  281.             try:
  282.                 TIMEOUT = int(a)
  283.             except TypeError:
  284.                 TIMEOUT = -1
  285.         elif o in ['-i', '--address']:
  286.             IP = a
  287.         else:
  288.             print('ERROR: invalid parameter.')
  289.  
  290.     # Checking mandatory parameters
  291.     if ACTION is None or PORT is None or FILENAME is None:
  292.         usage()
  293.         print('ERROR: missing mandatory parameters.')
  294.         sys.exit(1)
  295.     if ACTION not in ['get', 'put']:
  296.         usage()
  297.         print('ERROR: invalid action.')
  298.         sys.exit(1)
  299.     if TIMEOUT < 0:
  300.         usage()
  301.         print('ERROR: timeout must be 0 or higher.')
  302.         sys.exit(1)
  303.     if PORT < 0:
  304.         usage()
  305.         print('ERROR: port must be 32768 or higher.')
  306.         sys.exit(1)
  307.     if ACTION == 'get' and os.path.exists(FILENAME):
  308.         usage()
  309.         print('ERROR: destination file already exists.')
  310.         sys.exit(1)
  311.     if ACTION == 'put' and not os.path.exists(FILENAME):
  312.         usage()
  313.         print('ERROR: source file does not already exist.')
  314.         sys.exit(1)
  315.     if ACTION == 'put':
  316.         try:
  317.             fd = open(FILENAME, 'r')
  318.             config = fd.read()
  319.             fd.close()
  320.         except:
  321.             usage()
  322.             print('ERROR: cannot read from file.')
  323.             sys.exit(1)
  324.  
  325.     # Backgrounding the script
  326.     END_BEFORE = now() + TIMEOUT * 1000
  327.     MAIN_PROCESS = multiprocessing.Process(
  328.         target=main, name="Main", args=(ACTION, FILENAME, PORT))
  329.     MAIN_PROCESS.start()
  330.  
  331.     while MAIN_PROCESS.is_alive() and now() < END_BEFORE:
  332.         # Waiting for the child process to end
  333.         time.sleep(1)
  334.     if MAIN_PROCESS.is_alive():
  335.         # Timeout occurred
  336.         print('ERROR: timeout occurred.')
  337.         MAIN_PROCESS.terminate()
  338.         sys.exit(127)
  339.     if MAIN_PROCESS.exitcode != 0:
  340.         sys.exit(127)
  341.     sys.exit(0)
  342.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement