def lab_create(commands, startup_commands, external_commands): lab_create_command_string = '' for command in commands: if nc.PLATFORM == nc.WINDOWS: lab_create_command_string += "CALL " + command + "\n" else: lab_create_command_string += command + "\n" if PRINT: if nc.PLATFORM == nc.WINDOWS: sys.stderr.write(lab_create_command_string + "\n") else: print(lab_create_command_string) else: if nc.PLATFORM == nc.WINDOWS: u.write_temp("@ECHO OFF \n\n" + lab_create_command_string, "last_lab_creation.bat", mode=nc.PLATFORM, file_mode="w") drive = u.get_temp_folder(mode=nc.PLATFORM).split(':')[0] + ': ' cu.run_command_detatched(drive + nc.BASH_SEPARATOR + ' cd "' + u.get_temp_folder(mode=nc.PLATFORM) + '"' + nc.BASH_SEPARATOR + "last_lab_creation.bat") else: u.write_temp("#!/bin/bash \n\n" + lab_create_command_string, "last_lab_creation.sh", mode=nc.PLATFORM, file_mode="w") os.chmod( os.path.join(u.get_temp_folder(mode=nc.PLATFORM), "last_lab_creation.sh"), 0o755) cu.run_command_detatched('cd "' + u.get_temp_folder(mode=nc.PLATFORM) + '"' + nc.BASH_SEPARATOR + "./last_lab_creation.sh") external_create(external_commands) for startup_command in startup_commands: if PRINT: if nc.PLATFORM == nc.WINDOWS: sys.stderr.write(startup_command + "\n") else: print(startup_command) else: cu.run_command_detatched(startup_command)
def external_commands(path, collision_domains, interfaces, execbash=False): lab_external_links_text = '' commands = [] prefix = 'netkit_' + str(os.getuid()) + '_' for (collision_domain, interface) in zip(collision_domains, interfaces): #check if paramater's interface have a vlan syntax if interface.__contains__("."): prefix_interface = interface.split(".")[0] vlan_id = interface.split(".")[1] if (len(interface) > 15): prefix_truncate_interface = prefix_interface[-9:] interface = prefix_truncate_interface + '.' + vlan_id lab_external_links_text += interface + '\n' commands.append(os.path.join(os.environ['NETKIT_HOME'],'brctl_config_external ' + prefix + collision_domain + ' ' + interface + ' ' + prefix_interface + ' ' + vlan_id)) else: commands.append(os.path.join(os.environ['NETKIT_HOME'],'brctl_config_external ' + prefix + collision_domain + ' ' + interface)) if not execbash: if not PRINT: u.write_temp(lab_external_links_text, str(u.generate_urlsafe_hash(path)) + '_external_links', PLATFORM, file_mode="w+") return commands
def create_commands(machines, links, options, metadata, path, execbash=False, no_machines_tmp=False): docker = DOCKER_BIN # deciding machine and network prefix in order to avoid conflicts with other users and containers if PLATFORM != WINDOWS: prefix = 'netkit_' + str(os.getuid()) + '_' else: prefix = 'netkit_nt_' # generating network create command and network names separated by spaces for the temp file lab_links_text = '' lab_machines_text = '' create_network_template = docker + ' network create ' create_network_commands = [] base_path = os.path.join(os.environ['NETKIT_HOME'], 'temp') if PLATFORM != WINDOWS: base_path = os.path.join(os.environ['HOME'], 'netkit_temp') network_counter = 0 if not os.path.exists(os.path.join(base_path, 'last_network_counter.txt')): last_network_counter = open( os.path.join(base_path, 'last_network_counter.txt'), 'w') last_network_counter.close() with open(os.path.join(base_path, 'last_network_counter.txt'), 'r') as last_network_counter: try: network_counter = int(last_network_counter.readline()) except: network_counter = 0 for link in links: create_network_commands.append(create_network_template + prefix + link + " --subnet=172." + str(19 + network_counter) + ".0.0/16 --gateway=172." + str(19 + network_counter) + ".0.1") lab_links_text += prefix + link + ' ' network_counter = (network_counter + 1) % 236 create_network_commands.append( os.path.join(os.environ['NETKIT_HOME'], 'brctl_config ' + prefix + link)) with open(os.path.join(base_path, 'last_network_counter.txt'), 'w') as last_network_counter: last_network_counter.write(str(network_counter)) # writing the network list in the temp file if not execbash: if not PRINT: u.write_temp(lab_links_text, str(u.generate_urlsafe_hash(path)) + '_links', PLATFORM, file_mode="w+") # generating commands for running the containers, copying the config folder and executing the terminals connected to the containers if PLATFORM != WINDOWS: create_machine_template = docker + ' run -tid --privileged=true --name ' + prefix + '{machine_name} --hostname={machine_name} --network=' + prefix + '{first_link} {machine_options} {image_name}' else: create_machine_template = docker + ' run --volume="' + os.path.expanduser( '~' ) + '":/hosthome -tid --privileged=true --name ' + prefix + '{machine_name} --hostname={machine_name} --network=' + prefix + '{first_link} {machine_options} {image_name}' # we could use -ti -a stdin -a stdout and then /bin/bash -c "commands;bash", # but that woult execute commands like ifconfig BEFORE all the networks are linked create_machine_commands = [] create_connection_template = docker + ' network connect ' + prefix + '{link} ' + prefix + '{machine_name}' create_bridge_connection_template = docker + ' network connect {link} ' + prefix + '{machine_name}' create_connection_commands = [] create_bridge_connection_commands = [] copy_folder_template = docker + ' cp "' + path + '{machine_name}/{folder_or_file}" ' + prefix + '{machine_name}:/{dest}' copy_folder_commands = [] exec_template = docker + ' exec {params} -i --privileged=true ' + prefix + '{machine_name} {command}' exec_commands = [] startup_commands = [] count = 0 for machine_name, interfaces in machines.items(): this_image = DOCKER_HUB_PREFIX + IMAGE_NAME this_shell = 'bash' # copying the hostlab directory if not execbash: copy_folder_commands.append(docker + ' cp "' + path + '" ' + prefix + machine_name + ':/hostlab') #get the shell we run inside docker if options.get(machine_name): matching = [s for s in options[machine_name] if "shell" in s] if len(matching) > 0: this_shell = matching[0][1] # applying docker patch for /proc and icmp repls = ('{machine_name}', machine_name), ( '{command}', this_shell + ' -c "sysctl net.ipv4.conf.all.rp_filter=0"'), ('{params}', '') startup_commands.insert(0, u.replace_multiple_items(repls, exec_template)) repls = ('{machine_name}', machine_name), ( '{command}', this_shell + ' -c "sysctl net.ipv4.conf.default.rp_filter=0"'), ('{params}', '') startup_commands.insert(1, u.replace_multiple_items(repls, exec_template)) repls = ('{machine_name}', machine_name), ( '{command}', this_shell + ' -c "sysctl net.ipv4.conf.lo.rp_filter=0"'), ('{params}', '') startup_commands.insert(2, u.replace_multiple_items(repls, exec_template)) repls = ('{machine_name}', machine_name), ( '{command}', this_shell + ' -c "sysctl net.ipv4.conf.eth0.rp_filter=0"'), ('{params}', '') startup_commands.insert(2, u.replace_multiple_items(repls, exec_template)) # Parsing options from lab.conf machine_option_string = " " if options.get(machine_name): for opt, val in options[machine_name]: if opt == 'mem' or opt == 'M': machine_option_string += '--memory=' + val.upper() + ' ' if opt == 'image' or opt == 'i' or opt == 'model-fs' or opt == 'm' or opt == 'f' or opt == 'filesystem': this_image = DOCKER_HUB_PREFIX + val if opt == 'eth': app = val.split(":") create_network_commands.append(create_network_template + prefix + app[1]) repls = ('{link}', app[1]), ('{machine_name}', machine_name) create_connection_commands.append( u.replace_multiple_items(repls, create_connection_template)) if not PRINT: u.write_temp(" " + prefix + app[1], u.generate_urlsafe_hash(path) + '_links', PLATFORM) repls = ('{machine_name}', machine_name), ('{command}', this_shell + ' -c "sysctl net.ipv4.conf.eth' + str(app[0]) + '.rp_filter=0"'), ('{params}', '') startup_commands.insert( 4, u.replace_multiple_items(repls, exec_template)) if opt == 'bridged': repls = ('{link}', "bridge"), ('{machine_name}', machine_name) create_bridge_connection_commands.append( u.replace_multiple_items( repls, create_bridge_connection_template)) if opt == 'e' or opt == 'exec': repls = ('{machine_name}', machine_name), ( '{command}', this_shell + ' -c "' + val.strip().replace('\\', r'\\').replace( '"', r'\\"').replace("'", r"\\'") + '"'), ('{params}', '-d') startup_commands.append( u.replace_multiple_items(repls, exec_template)) if opt == 'port': machine_option_string += '-p=' + val.upper( ) + ':3000' + ' ' repls = ('{machine_name}', machine_name), ('{number}', str(count)), ( '{first_link}', interfaces[0][0]), ('{image_name}', this_image), ('{machine_options}', machine_option_string) create_machine_commands.append( u.replace_multiple_items(repls, create_machine_template)) count += 1 eth_cnt = 1 for link, _ in interfaces[1:]: repls = ('{link}', link), ('{machine_name}', machine_name) create_connection_commands.append( u.replace_multiple_items(repls, create_connection_template)) repls = ('{machine_name}', machine_name), ('{command}', this_shell + ' -c "sysctl net.ipv4.conf.eth' + str(eth_cnt) + '.rp_filter=0"'), ('{params}', '') startup_commands.insert( 4, u.replace_multiple_items(repls, exec_template)) eth_cnt += 1 # convoluted method to copy MACHINE_NAME/etc folder to the etc of the container if os.path.exists(os.path.join(path, machine_name)) and not execbash: for folder_or_file in os.listdir(os.path.join(path, machine_name)): if folder_or_file == 'etc': repls = ('{machine_name}', machine_name), ('{machine_name}', machine_name), ( '{folder_or_file}', folder_or_file), ('{dest}', 'temp_etc') repls2 = ('{machine_name}', machine_name), ( '{command}', this_shell + ' -c "chmod -R 777 /temp_etc/*; cp -rfp /temp_etc/* /etc/; rm -rf /temp_etc; mkdir /var/log/zebra; chmod -R 777 /var/log/quagga; chmod -R 777 /var/log/zebra; chmod -R 777 /var/www/*"' ), ('{params}', '') startup_commands.insert( 0, u.replace_multiple_items(repls2, exec_template)) else: repls = ('{machine_name}', machine_name), ('{machine_name}', machine_name), ( '{folder_or_file}', folder_or_file), ('{dest}', '') copy_folder_commands.append( u.replace_multiple_items(repls, copy_folder_template)) if PLATFORM == WINDOWS: repls = ('{machine_name}', machine_name), ('{command}', this_shell + ' -c "echo -ne \'\033]0;' + machine_name + '\007\'; bash"'), ('{params}', '-t -e TERM=vt100') else: repls = ('{machine_name}', machine_name), ('{command}', this_shell), ('{params}', '-t -e TERM=vt100') exec_commands.append(u.replace_multiple_items(repls, exec_template)) lab_machines_text += prefix + machine_name + ' ' # writing the container list in the temp file if not no_machines_tmp: if not execbash: if not PRINT: u.write_temp(lab_machines_text, str(u.generate_urlsafe_hash(path)) + '_machines', PLATFORM) # for each machine we have to get the machine.startup file and insert every non empty line as a string inside an array of exec commands. We also replace escapes and quotes for machine_name, _ in machines.items(): startup_file = os.path.join(path, machine_name + '.startup') if os.path.exists(startup_file): f = open(startup_file, 'r') full_startup_command = '' for line in f: if line.strip() and (line.strip() not in [ '\n', '\r\n', '\n\r' ]) and (not line.startswith('#')): full_startup_command += line.strip().replace( '\\', r'\\').replace('"', r'\"').replace("'", r"\'") + ';' f.close() repls = ('{machine_name}', machine_name), ('{command}', this_shell + ' -c "' + full_startup_command + '"'), ('{params}', '-d') startup_commands.append( u.replace_multiple_items(repls, exec_template)) commands = create_network_commands + create_machine_commands + create_connection_commands + create_bridge_connection_commands + copy_folder_commands return commands, startup_commands, exec_commands