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