2 # Marta Carbone - UniPi
6 # This class requires the rpm package containing
7 # the picobsd image to be installed
8 # on the Central Site system.
15 from PLC.Faults import * # faults library
16 from PLC.Method import Method # base class for methods
17 from PLC.Parameter import Parameter # use the Parameter wrapper
18 from PLC.Auth import Auth # import the Auth parameter
19 from PLC.Nodes import * # nodes functions
20 from PLC.Methods.GetBootMedium import compute_key # key generation function
21 from PLC.Accessors.Accessors_dummynetbox import * # import dummynet accessors
23 WORK_DIR = "/var/tmp/DummynetBoxMedium"
24 BASE_IMAGE = "/usr/share/dummynet/picobsd"
26 class GetDummyBoxMedium(Method):
28 This method is used to fetch a boot image for the DummyNetBox
29 with its configuration file embedded.
31 Every time this method is called, a new key is generated in the configuration file,
32 SO THIS OPERATION WILL INVALIDATE ANY PREVIOUSLY DUMMYNETBOX BOOT MEDIUM.
34 This method updates the key fields in the database.
35 It returns a base64-encoded boot image.
37 # I added the session role, because this method should be called from the web
38 roles = ['admin', 'pi', 'tech', 'session']
42 Parameter(int, "The dummybox_id"),
43 Parameter(str, "The image type (bin or iso)")
46 returns = Parameter(str, "DummynetBox boot medium")
48 # XXX add checks for picobsd.bin existence
50 # Generate a new configuration file in the working directory
51 # input parameters follows:
52 # self is used to access instance data,
53 # dummybox is the dummybox_id,
54 # new_key is the new generated key,
55 # configfile is the output file of the configuration.
56 def generate_conf_file(self, dummybox, new_key, configfile):
58 # Generate the dummynet box configuration file
59 today = datetime.date.today()
61 file += "# This is the dummynetbox configuration file\n"
62 file += "# and was generated on %s\n" % str(today)
64 host_domain = dummybox['hostname']
65 host_domain = host_domain.split('.', 1)
66 file += 'HOST_NAME="%s"\n' % host_domain[0]
67 file += 'DOMAIN_NAME="%s"\n' % host_domain[1]
69 file += 'IP_ADDRESS="%s"\n' % dummybox['ip']
70 file += 'IP_NETMASK="%s"\n' % dummybox['netmask']
71 file += 'IP_GATEWAY="%s"\n' % dummybox['gateway']
72 file += 'IP_DNS1="%s"\n' % dummybox['dns1']
73 file += 'IP_DNS2="%s"\n' % dummybox['dns2']
74 file += 'DUMMYBOX_ID="%s"\n' % dummybox['node_id']
75 file += 'DUMMYBOX_KEY="%s"\n' % new_key
77 file += 'CS_IP="%s"\n' % self.api.config.PLC_API_HOST
79 # write the configuration file
80 # WORK_DIR must be writable
81 FILE = open(configfile, "w")
87 # Here starts the execution of the call
88 def call(self, auth, dummybox_id, type):
90 # check for dummynet box existence and get dummyboxes information
91 dummybox_info = Nodes(self.api, {'node_id':dummybox_id, 'node_type':'dummynet'}, \
92 ['hostname', 'interface_ids'])
94 if dummybox_id != None and not dummybox_info:
95 raise PLCInvalidArgument, "No such DummyBox %s" % dummybox_id
97 # Get the dummynet box hostname
98 dummybox_hostname = dummybox_info[0]['hostname']
99 print "dummybox hostname %s" % dummybox_hostname
101 # get the node interface, if configured
102 interfaces = Interfaces(self.api, dummybox_info[0]['interface_ids'])
108 if not interface_info:
109 raise PLCInvalidArgument, "No primary network configured on %s" % dummybox_hostname
111 dummybox = interface_info
112 dummybox['hostname']=dummybox_hostname
114 # Select the base image, default to bin image
117 IMAGE_NAME = str(WORK_DIR) + "/dummybox_" + dummybox_hostname + str(type)
118 BASE_IMAGE = "/usr/share/dummynet/picobsd." + str(type)
119 configfile = WORK_DIR + '/dummybox.conf'
120 lockfile = WORK_DIR + '/lockfile'
123 assert self.caller is not None
125 # Start the generation of the image
127 new_key = compute_key()
129 # create working dir and lock file for concurrent runs
130 if not os.path.exists(WORK_DIR):
131 print "Creating working directory %s" % WORK_DIR
134 if os.path.exists(lockfile):
135 raise PLCInvalidArgument, "Lockfile %s exist, try again " % lockfile
137 print "Executing "+"touch %s" % lockfile
138 os.system("touch %s" % lockfile)
140 # generate the configuration file
141 conf_file = self.generate_conf_file(dummybox, new_key, configfile)
143 # build the shell script to customize the dummynetbox image
144 # copy the raw file and find the configuration file position
145 shell_script = "(cp %s %s; export MATCH=`grep -abo START_USER_DATA %s | cut -d: -f1`; " \
146 % (BASE_IMAGE, IMAGE_NAME, IMAGE_NAME)
148 # set permission file
149 shell_script += " chmod u+w %s; chmod u+w %s; " % (IMAGE_NAME, configfile)
151 # cat the configuration file in the raw image
152 shell_script += " cat %s | dd of=%s seek=$MATCH conv=notrunc bs=1)" \
153 % (configfile, IMAGE_NAME)
155 # check returned values, 0 means OK, remove the lock file
156 os.system(shell_script)
157 os.system("rm %s" % (lockfile))
159 # if all goes fine store the key in the database
160 nodes = Nodes(self.api, dummybox_id)
162 raise PLCInvalidArgument, "No such node %r"%node_id_or_hostname
163 nodes[0]['key'] = new_key
166 # return the file's content base64-encoded
167 result = file(IMAGE_NAME).read()
168 os.unlink(IMAGE_NAME)
169 return base64.b64encode(result)