#!/usr/bin/env python # -*- coding: utf-8 -*- # TODO: dokoncaj! # kpov_random_helpers should be imported by add_assignment.py instructions = { 'si':u""" Postavi štiri navidezne računalnike - simpleArbiter, DHCP_server, BootableClientA ter BootableClientB. Na DHCP_server postavi DHCP strežnik s pomočjo ISC dhcp 3 na naslovu {IP_DHCP}. SimpleArbiter naj dobi {IP_GW}. DHCP_server naj ga uporabi kot gateway. Če se zaganja BootableClientB, naj se sistem zažene v datoteko z imenom {BOOT_FNAME}. Če se zaganja katerikoli drug, naj se sistem zažene z živega USB, ki ga predstavlja slika diska bootable_usb. Živi USB priklopite na na DHCP_server ter z njega poberite datoteke, potrebne za zagon. Datoteke z nastavitvami za PXELinux, ki jih najdete na živem USB, MORAJO biti dostopne na korenskem imeniku strežnika TFTP. Tako BootableClientA kot BootableClientB naj bosta brez diskov. """, # TODO: write a proper translation. The one that used to be here was just wrong. 'en': """Set up 4 virtual computers - simpleArbiter, DHCP_server, BootableClientA and BootableClientB. On DHCP_server, set up a DHCP server using ISC dhcp 3. Set the IP address of this server to {IP_DHCP}. If SimpleArbiter requests an IP, have the DHCP server serve it {IP_GW}. DHCP_server should use SimpleArbiter as it's gateway. If BootableClientB tries to boot over the network, have the DHCP server tell it to boot from the file {BOOT_FNAME}. If any other system tries to boot over the network, have it boot from a live USB drive represented by the disk image bootable_usb. Connect the live USB to DHCP_server and copy the files neccessarry for it to boot. The PXELinux configuration files must be the same as the ones found on the live USB and MUST be accessible on the TFTP server root. Both BootableCLientA and BootableClientB should be diskless. """ } computers = { 'DHCPServer': { 'disks': [ { 'name': 'student-DHCPServer', }, { 'name': 'bootable_usb', 'options':{'readonly': True}, 'parts': [ {'dev': 'sdb1', 'path':'/mnt'} ], }, #{ 'name': 'CDROM', # 'options':{'readonly': True}, # 'parts': [],# no parts, no mounting. #} ], 'network_interfaces': [{'network': 'net1'}], 'flavor': 'm1.tiny', 'config_drive': False }, 'BootableClientA': { 'disks': [ ], 'network_interfaces': [{'network': 'net1'}], 'flavor': 'm1.tiny', 'config_drive': False }, 'BootableClientB': { 'disks': [ ], 'network_interfaces': [{'network': 'net1'}], 'flavor': 'm1.tiny', 'config_drive': False }, 'SimpleArbiter': { 'disks': [ { 'name': 'simpleArbiterGW', }, #{ 'name': 'CDROM', # 'options': {'readonly': True}, # 'parts': [{'dev': 'b1', 'path': '/cdrom'}], #}, ], 'network_interfaces': [{'network': 'net1'}, {'network': 'test-net'}], 'flavor': 'm1.tiny', 'config_drive': False } } networks = { 'net1': {'public': False}, 'test-net': {'public': True} } params_meta = { 'IP_DHCP': {'descriptions': {'si': 'IP DHCP streznika'}, 'w': False, 'public': True, 'type':'IP', 'generated': True}, 'IP_GW': {'descriptions': {'si': 'IP SimpleArbiterja'}, 'w': False, 'public': True, 'type':'IP', 'generated': True}, 'MAC_BOOT': {'descriptions': {'si': 'MAC racunalnika, ki se zazene z ISO'}, 'w': True, 'public': True, 'type':'MAC', 'generated': False}, # 'IP_BOOT': {'descriptions': {'si': 'IP racunalnika, ki se zazene z ISO'}, 'w': True, 'public': True, 'type':'IP', 'generated': False}, 'TFTP_STRING': {'descriptions': {'si': 'vsebina'}, 'w': False, 'public': False, 'type':'short', 'generated': True}, 'BOOT_FNAME': {'descriptions': {'si': 'Ime datoteke'}, 'w': False, 'public': True, 'type': 'filename', 'generated': True}, } def task(IP_DHCP, IP_GW, MAC_BOOT, BOOT_FNAME): # check the IP # TODO (polz): Do not use tabs instead of spaces! import pexpect import re import tftpy import StringIO results={} # TODO (polz): Please use pexpect instead of os.system, it's much nicer. # Also, test your functions. This function was obviously never run. # # check whether the fname served by the dhcp server is # correct # you should check the DHCP response from the server. # You can use dhcpdump to get some packets, dhcping to create a # DHCP Request. You may also use any other tool. # If you choose to use dhcping, do not forget to set the hw address # and ip arguments. You can simply feed it MAC_BOOT and IP_BOOT. # dhcping -h MAC_BOOT -c IP_BOOT -V -r # could work (but you should test it) dhcpdump = pexpect.spawn("sudo dhcpdump -i eth1") mac_str = pexpect.run("ip link show eth1") mac_re = re.search(r"(([0-9a-f]{2}:){5}[0-9a-f]{2})", mac_str) mac_SA = mac_re.group(1) results['dhcping_other'] = pexpect.run('sudo dhcping -s {} -h {}'.format( IP_DHCP, MAC_BOOT)) dhcpdump.expect('---------------------------------------------------------------------------') results['dhcpdump_other_req'] = dhcpdump.before dhcpdump.expect('---------------------------------------------------------------------------') results['dhcpdump_other_reply'] = dhcpdump.before dhcpdump.expect('---------------------------------------------------------------------------') results['dhcpdump_other_release'] = dhcpdump.before results['dhcping_SA'] = pexpect.run('sudo dhcping -s {} -h {}'.format( IP_DHCP, mac_SA)) dhcpdump.expect('---------------------------------------------------------------------------') results['dhcpdump_SA_req'] = dhcpdump.before dhcpdump.expect('---------------------------------------------------------------------------') results['dhcpdump_SA_reply'] = dhcpdump.before dhcpdump.expect('---------------------------------------------------------------------------') results['dhcpdump_SA_release'] = dhcpdump.before dhcpdump.sendintr() tftp_client = pexpect.spawn('tftp {}'.format(IP_DHCP)) tftp_client.sendline('get pxelinux.cfg/default /dev/stdout') tftp_client.expect(r'Received \d* bytes in \d*\.\d* seconds') results['tftp_string'] = tftp_client.before # check whether the fname served by the dhcp server is correct # connect to the service in the special ISO # check the MAC of the server on IP_BOOT return results def gen_params(user_id, params_meta): params = dict() r = random.Random(user_id) net = kpov_random_helpers.IPv4_subnet_gen(r, '10.64.0.0/10', 24) params['IP_DHCP'], params['IP_GW'] = kpov_random_helpers.IPv4_addr_gen(r, net, 2) params['BOOTA_FNAME'] = kpov_random_helpers.fname_gen(r) params['TFTP_STRING'] = kpov_random_helpers.alnum_gen(r, 45) # IP_NM, DNS_NM, IP_static, DNS_static) return params def task_check(results, params): import re score = 0 hints = [] #TO FINISH SCORING WE REQUIRE DICT KEYS AND FUNCTIONS gen_params AND task TO BE FINISHED #POINTS FOR EACH TASK MAY BE ADJUSTED IN THE FUTURE if results['dhcping_other'].find(params['IP_DHCP']) >= 0: score += 1 else: hints += ["DHCP wrong"] if results['dhcping_SA'].find(params['IP_DHCP']) >= 0: score += 1 else: hints += ["DHCP wrong"] p = re.search(r"FNAME:(.*)\r", results['dhcpdump_other_reply']) other_fname = p.group(1) if other_fname == params['BOOT_FNAME']: score += 3 else: hints += ["special fname wrong"] p = re.search(r"FNAME:(.*)\r", results['dhcpdump_SA_reply']) sa_fname = p.group(1) if sa_fname == params['BOOT_FNAME']: score += 3 else: hints += ["fname wrong"] if results['tftp_string'].split('\r\r\n')[-2] == "# " + params['TFTP_STRING']: score += 2 else: hints += ["tftp wrong"] return score, hints def prepare_disks(templates, params): # d = templates['simpleArbiterDhcp'] d = templates['student-DHCPServer'] s = """# use this exact config for your booting clients. # search path for the c32 support libraries (libcom32, libutil etc.) path include menu.cfg default vesamenu.c32 prompt 0 timeout 0 # {}""".format(params['TFTP_STRING']) d.write('/mnt/syslinux.cfg', s) d = templates['simpleArbiterGW'] s = """auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp iface eth1 inet static address {} netmask 255.192.0.0 """.format(params['IP_GW']) d.write("/etc/interfaces", s)