TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | import argparse |
| 3 | import sys |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 4 | import subprocess |
| 5 | import ipaddress |
| 6 | import time |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 7 | import logging |
Bartek Grzybowski | 8200d2a | 2020-05-05 03:50:38 -0700 | [diff] [blame] | 8 | from requests import get |
Bartek Grzybowski | 937fe44 | 2020-05-07 04:28:13 -0700 | [diff] [blame] | 9 | from json import dumps |
Bartek Grzybowski | 8200d2a | 2020-05-05 03:50:38 -0700 | [diff] [blame] | 10 | from requests.exceptions import MissingSchema, InvalidSchema, InvalidURL, ConnectionError, ConnectTimeout |
| 11 | |
| 12 | def validate_url(url): |
| 13 | '''Helper function to perform --urlves input param validation''' |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 14 | logger = logging.getLogger("urllib3") |
| 15 | logger.setLevel(logging.WARNING) |
Bartek Grzybowski | 8200d2a | 2020-05-05 03:50:38 -0700 | [diff] [blame] | 16 | try: |
| 17 | get(url, timeout=0.001) |
| 18 | except (MissingSchema, InvalidSchema, InvalidURL): |
| 19 | raise argparse.ArgumentTypeError(f'{url} is not a valid URL') |
| 20 | except (ConnectionError, ConnectTimeout): |
| 21 | pass |
| 22 | return url |
| 23 | |
| 24 | def validate_ip(ip): |
| 25 | '''Helper function to validate input param is a vaild IP address''' |
| 26 | try: |
| 27 | ip_valid = ipaddress.ip_address(ip) |
| 28 | except ValueError: |
| 29 | raise argparse.ArgumentTypeError(f'{ip} is not a valid IP address') |
| 30 | else: |
| 31 | return ip_valid |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 32 | |
Bartek Grzybowski | 879d567 | 2020-05-06 03:37:23 -0700 | [diff] [blame] | 33 | if sys.stdout.isatty(): |
| 34 | logging.basicConfig(level=logging.INFO, format='\033[92m[%(levelname)s]\033[0m %(message)s') |
| 35 | else: |
| 36 | logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(message)s') |
| 37 | |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 38 | parser = argparse.ArgumentParser() |
Bartek Grzybowski | 70c116f | 2020-05-05 04:27:25 -0700 | [diff] [blame] | 39 | parser.add_argument('--bootstrap', help='Bootstrap the system', type=int, metavar='COUNT') |
| 40 | parser.add_argument('--trigger', help='Trigger one single VES event from each simulator', type=int, |
| 41 | metavar='COUNT') |
| 42 | parser.add_argument('--triggerstart', help='Trigger only a subset of the simulators (note --triggerend)', type=int, |
| 43 | metavar='COUNT_START') |
| 44 | parser.add_argument('--triggerend', help='Last instance to trigger', type=int, metavar='COUNT_END') |
| 45 | parser.add_argument('--urlves', help='URL of the VES collector', type=validate_url, metavar='URL') |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 46 | parser.add_argument('--ipfileserver', help='Visible IP of the file server (SFTP/FTPS) to be included in the VES event', |
Bartek Grzybowski | 70c116f | 2020-05-05 04:27:25 -0700 | [diff] [blame] | 47 | type=validate_ip, metavar='IP') |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 48 | parser.add_argument('--typefileserver', help='Type of the file server (SFTP/FTPS) to be included in the VES event', |
| 49 | type=str, choices=['sftp', 'ftps']) |
Bartek Grzybowski | 70c116f | 2020-05-05 04:27:25 -0700 | [diff] [blame] | 50 | parser.add_argument('--ipstart', help='IP address range beginning', type=validate_ip, metavar='IP') |
Bartek Grzybowski | c29b946 | 2020-04-30 07:11:59 -0700 | [diff] [blame] | 51 | parser.add_argument('--clean', action='store_true', help='Clean work-dirs') |
Bartek Grzybowski | 70c116f | 2020-05-05 04:27:25 -0700 | [diff] [blame] | 52 | parser.add_argument('--start', help='Start instances', type=int, metavar='COUNT') |
| 53 | parser.add_argument('--status', help='Status', type=int, metavar='COUNT') |
| 54 | parser.add_argument('--stop', help='Stop instances', type=int, metavar='COUNT') |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 55 | parser.add_argument('--verbose', help='Verbosity level', choices=['info', 'debug'], |
| 56 | type=str, default='debug') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 57 | |
| 58 | args = parser.parse_args() |
Bartek Grzybowski | 879d567 | 2020-05-06 03:37:23 -0700 | [diff] [blame] | 59 | |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 60 | logger = logging.getLogger(__name__) |
| 61 | logger.setLevel(getattr(logging, args.verbose.upper())) |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 62 | |
TamasBakai | bab325b | 2019-03-26 09:20:16 +0000 | [diff] [blame] | 63 | if args.bootstrap and args.ipstart and args.urlves: |
Bartek Grzybowski | 937fe44 | 2020-05-07 04:28:13 -0700 | [diff] [blame] | 64 | logger.info("Bootstrapping PNF instances") |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 65 | |
Bartek Grzybowski | 8ec0816 | 2020-05-06 04:42:18 -0700 | [diff] [blame] | 66 | start_port = 2000 |
| 67 | ftps_pasv_port_start = 8000 |
| 68 | ftps_pasv_port_num_of_ports = 10 |
Bartek Grzybowski | 3d3d3c2 | 2020-03-05 10:28:03 +0100 | [diff] [blame] | 69 | |
Bartek Grzybowski | 8ec0816 | 2020-05-06 04:42:18 -0700 | [diff] [blame] | 70 | ftps_pasv_port_end = ftps_pasv_port_start + ftps_pasv_port_num_of_ports |
Bartek Grzybowski | 3d3d3c2 | 2020-03-05 10:28:03 +0100 | [diff] [blame] | 71 | |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 72 | for i in range(args.bootstrap): |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 73 | logger.info(f"PNF simulator instance: {i}") |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 74 | |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 75 | # The IP ranges are in distance of 16 compared to each other. |
| 76 | # This is matching the /28 subnet mask used in the dockerfile inside. |
Bartek Grzybowski | 937fe44 | 2020-05-07 04:28:13 -0700 | [diff] [blame] | 77 | instance_ip_offset = i * 16 |
| 78 | ip_properties = [ |
| 79 | 'subnet', |
| 80 | 'gw', |
| 81 | 'PnfSim', |
| 82 | 'ftps', |
| 83 | 'sftp' |
| 84 | ] |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 85 | |
Bartek Grzybowski | 937fe44 | 2020-05-07 04:28:13 -0700 | [diff] [blame] | 86 | ip_offset = 0 |
| 87 | ip = {} |
| 88 | for prop in ip_properties: |
| 89 | ip.update({prop: str(args.ipstart + ip_offset + instance_ip_offset)}) |
| 90 | ip_offset += 1 |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 91 | |
Bartek Grzybowski | 937fe44 | 2020-05-07 04:28:13 -0700 | [diff] [blame] | 92 | logger.debug(f'Instance #{i} properties:\n {dumps(ip, indent=4)}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 93 | |
Bartek Grzybowski | 8ec0816 | 2020-05-06 04:42:18 -0700 | [diff] [blame] | 94 | PortSftp = start_port + 1 |
| 95 | PortFtps = start_port + 2 |
| 96 | start_port += 2 |
Bartek Grzybowski | 3d3d3c2 | 2020-03-05 10:28:03 +0100 | [diff] [blame] | 97 | |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 98 | foldername = f"pnf-sim-lw-{i}" |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 99 | completed = subprocess.run('mkdir ' + foldername, shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 100 | logger.info(f'\tCreating folder: {completed.stdout}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 101 | completed = subprocess.run( |
| 102 | 'cp -r pnf-sim-lightweight/* ' + |
| 103 | foldername, |
| 104 | shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 105 | logger.info(f'\tCloning folder: {completed.stdout}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 106 | |
Bartek Grzybowski | 937fe44 | 2020-05-07 04:28:13 -0700 | [diff] [blame] | 107 | composercmd = " ".join([ |
| 108 | "./simulator.sh compose", |
| 109 | ip['gw'], |
| 110 | ip['subnet'], |
| 111 | str(i), |
| 112 | args.urlves, |
| 113 | ip['PnfSim'], |
| 114 | str(args.ipfileserver), |
| 115 | args.typefileserver, |
| 116 | str(PortSftp), |
| 117 | str(PortFtps), |
| 118 | ip['ftps'], |
| 119 | ip['sftp'], |
| 120 | str(ftps_pasv_port_start), |
| 121 | str(ftps_pasv_port_end) |
| 122 | ]) |
| 123 | logger.debug(f"Script cmdline: {composercmd}") |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 124 | |
| 125 | completed = subprocess.run( |
| 126 | 'set -x; cd ' + |
| 127 | foldername + |
| 128 | '; ' + |
| 129 | composercmd, |
| 130 | shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 131 | logger.info(f'Cloning: {completed.stdout}') |
Bartek Grzybowski | 3d3d3c2 | 2020-03-05 10:28:03 +0100 | [diff] [blame] | 132 | |
TamasBakai | e781c7c | 2019-07-11 11:26:20 +0000 | [diff] [blame] | 133 | ftps_pasv_port_start += ftps_pasv_port_num_of_ports + 1 |
Bartek Grzybowski | 8ec0816 | 2020-05-06 04:42:18 -0700 | [diff] [blame] | 134 | ftps_pasv_port_end += ftps_pasv_port_num_of_ports + 1 |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 135 | |
Bartek Grzybowski | 937fe44 | 2020-05-07 04:28:13 -0700 | [diff] [blame] | 136 | logger.info(f'Done setting up instance #{i}') |
| 137 | |
TamasBakai | bab325b | 2019-03-26 09:20:16 +0000 | [diff] [blame] | 138 | completed = subprocess.run('set -x; cd pnf-sim-lightweight; ./simulator.sh build ', shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 139 | logger.info(f"Build docker image: {completed.stdout}") |
TamasBakai | bab325b | 2019-03-26 09:20:16 +0000 | [diff] [blame] | 140 | |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 141 | sys.exit() |
| 142 | |
| 143 | if args.clean: |
| 144 | completed = subprocess.run('rm -rf ./pnf-sim-lw-*', shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 145 | logger.info(f'Deleting: {completed.stdout}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 146 | sys.exit() |
| 147 | |
| 148 | if args.start: |
| 149 | |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 150 | for i in range(args.start): |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 151 | foldername = f"pnf-sim-lw-{i}" |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 152 | |
| 153 | completed = subprocess.run( |
| 154 | 'set -x ; cd ' + |
| 155 | foldername + |
| 156 | "; bash -x ./simulator.sh start", |
| 157 | shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 158 | logger.info(f'Starting: {completed.stdout}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 159 | |
| 160 | time.sleep(5) |
| 161 | |
| 162 | if args.status: |
| 163 | |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 164 | for i in range(args.status): |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 165 | foldername = f"pnf-sim-lw-{i}" |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 166 | |
| 167 | completed = subprocess.run( |
| 168 | 'cd ' + |
| 169 | foldername + |
| 170 | "; ./simulator.sh status", |
| 171 | shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 172 | logger.info(f'Status: {completed.stdout}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 173 | |
| 174 | if args.stop: |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 175 | for i in range(args.stop): |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 176 | foldername = f"pnf-sim-lw-{i}" |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 177 | |
| 178 | completed = subprocess.run( |
| 179 | 'cd ' + |
| 180 | foldername + |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 181 | f"; ./simulator.sh stop {i}", |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 182 | shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 183 | logger.info(f'Stopping: {completed.stdout}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 184 | |
TamasBakai | b59bffb | 2019-03-22 09:52:03 +0000 | [diff] [blame] | 185 | |
| 186 | if args.trigger: |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 187 | logger.info("Triggering VES sending:") |
TamasBakai | b59bffb | 2019-03-22 09:52:03 +0000 | [diff] [blame] | 188 | |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 189 | for i in range(args.trigger): |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 190 | foldername = f"pnf-sim-lw-{i}" |
TamasBakai | b59bffb | 2019-03-22 09:52:03 +0000 | [diff] [blame] | 191 | |
| 192 | completed = subprocess.run( |
| 193 | 'cd ' + |
| 194 | foldername + |
| 195 | "; ./simulator.sh trigger-simulator", |
| 196 | shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 197 | logger.info(f'Status: {completed.stdout}') |
Bartek Grzybowski | 3d3d3c2 | 2020-03-05 10:28:03 +0100 | [diff] [blame] | 198 | |
TamasBakai | 34a6f11 | 2019-04-15 08:38:51 +0000 | [diff] [blame] | 199 | if args.triggerstart and args.triggerend: |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 200 | logger.info("Triggering VES sending by a range of simulators:") |
Bartek Grzybowski | 3d3d3c2 | 2020-03-05 10:28:03 +0100 | [diff] [blame] | 201 | |
Bartek Grzybowski | 32fb5ab | 2020-05-05 03:54:01 -0700 | [diff] [blame] | 202 | for i in range(args.triggerstart, args.triggerend+1): |
Bartek Grzybowski | c9514c7 | 2020-05-06 05:56:20 -0700 | [diff] [blame] | 203 | foldername = f"pnf-sim-lw-{i}" |
| 204 | logger.info(f"Instance being processed: {i}") |
Bartek Grzybowski | 3d3d3c2 | 2020-03-05 10:28:03 +0100 | [diff] [blame] | 205 | |
TamasBakai | 34a6f11 | 2019-04-15 08:38:51 +0000 | [diff] [blame] | 206 | completed = subprocess.run( |
| 207 | 'cd ' + |
| 208 | foldername + |
| 209 | "; ./simulator.sh trigger-simulator", |
| 210 | shell=True) |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 211 | logger.info(f'Status: {completed.stdout}') |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 212 | else: |
Bartek Grzybowski | 1f76234 | 2020-05-05 08:54:37 -0700 | [diff] [blame] | 213 | logger.warning("No instruction was defined") |
Bartek Grzybowski | c29b946 | 2020-04-30 07:11:59 -0700 | [diff] [blame] | 214 | parser.print_usage() |
TamasBakai | d38feb6 | 2019-02-28 09:06:19 +0000 | [diff] [blame] | 215 | sys.exit() |