def remove_subinterface(path): delete_commands = [] if (_platform == LINUX or _platform == LINUX2): if (os.geteuid() == 0): temp_path = os.path.join( pwd.getpwuid(os.getuid()).pw_dir, "netkit_temp/") hash_path = str(u.generate_urlsafe_hash(path)) if (os.path.exists(temp_path + hash_path + '_external_links')): if (os.stat(temp_path + hash_path + '_external_links').st_size != 0): with open(temp_path + hash_path + '_external_links', 'r') as external_file_temp: delete_commands.append( 'echo "\033[0;33mSubinterfaces will be deleted\033[0m"' ) for line in external_file_temp: subinterface = line.split()[0] delete_commands.append('sudo ip link set dev ' + subinterface + ' ' + 'down') delete_commands.append('sudo ip link delete ' + subinterface) delete_commands.append('echo ' + subinterface) os.remove(temp_path + hash_path + '_external_links') else: sys.stderr.write( "\033[0;33mPlease you started the lab with external.conf file, need root permission to clean current lab.\033[0m" + "\n") sys.exit(1) return delete_commands
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
DEBUG = nc.DEBUG nc.DEBUG = False parser = argparse.ArgumentParser(description='Create and start a Netkit Lab.') parser.add_argument('path') parser.add_argument('-d', '--directory', required=False, help='Folder contining the lab.') parser.add_argument( '--print', dest="print_only", required=False, action='store_true', help= 'Print commands used to start the containers to stderr (containers are not started).' ) args, unknown = parser.parse_known_args() lab_path = args.path.replace('"', '').replace("'", '').replace("//", '/') if args.directory: lab_path = args.directory.replace('"', '').replace("'", '').replace("//", '/') if args.print_only and nc.PLATFORM == nc.WINDOWS: #linux still needs the hash for the while statement print " " else: print u.generate_urlsafe_hash(lab_path)