--- /dev/null
+#
+# Marta Carbone - UniPi
+# $Id$
+#
+# This class requires the rpm package containing
+# the picobsd image to be installed
+# on the Central Site system.
+#
+
+import base64
+import os
+import datetime
+
+from PLC.Faults import * # faults library
+from PLC.Method import Method # base class for methods
+from PLC.Parameter import Parameter # use the Parameter wrapper
+from PLC.Auth import Auth # import the Auth parameter
+from PLC.Nodes import * # nodes functions
+from PLC.Methods.GetBootMedium import compute_key # key generation function
+from PLC.Accessors.Accessors_dummynetbox import * # import dummynet accessors
+
+WORK_DIR = "/var/tmp/DummynetBoxMedium"
+BASE_IMAGE = "/usr/share/dummynet/picobsd"
+
+class GetDummyBoxMedium(Method):
+ """
+ This method is used to get a boot image of the DummyNetBox
+ equipped with the configuration file.
+
+ We need to provide the dummybox_id of the DummyNetBox
+ we want to generate.
+ Since every time a new configuration file will be generater,
+ THIS OPERATION WILL INVALIDATE ANY PREVIOUSLY DUMMYNETBOX BOOT MEDIUM.
+ # XXX add checks for picobsd.bin existence
+
+ Returns the iso image customized for the DummyNetBox with the new
+ key integrated in the image, and update the key fields in the database.
+ """
+ # I added the session role, because this method should be called from the web
+ roles = ['admin', 'pi', 'tech', 'session']
+
+ accepts = [
+ Auth(),
+ Parameter(int, "The dummybox_id"),
+ Parameter(str, "The image type (bin or iso)")
+ ]
+
+ returns = Parameter(str, "DummynetBox boot medium")
+
+ # Generate a new configuration file in the working directory
+ # input parameters follows:
+ # self is used to access instance data,
+ # dummybox is the dummybox_id,
+ # new_key is the new generated key,
+ # configfile is the output file of the configuration.
+ def generate_conf_file(self, dummybox, new_key, configfile):
+
+ # Generate the dummynet box configuration file
+ today = datetime.date.today()
+ file = ""
+ file += "# This is the dummynetbox configuration file\n"
+ file += "# and was generated the %s\n" % str(today)
+
+ host_domain = dummybox['hostname']
+ host_domain = host_domain.split('.', 1)
+ file += 'HOST_NAME="%s"\n' % host_domain[0]
+ file += 'DOMAIN_NAME="%s"\n' % host_domain[1]
+
+ file += 'IP_ADDRESS="%s"\n' % dummybox['ip']
+ file += 'IP_NETMASK="%s"\n' % dummybox['netmask']
+ file += 'IP_GATEWAY="%s"\n' % dummybox['gateway']
+ file += 'IP_DNS1="%s"\n' % dummybox['dns1']
+ file += 'IP_DNS2="%s"\n' % dummybox['dns2']
+ file += 'DUMMYBOX_ID="%s"\n' % dummybox['node_id']
+ file += 'DUMMYBOX_KEY="%s"\n' % new_key
+
+ file += 'CS_IP="%s"\n' % self.api.config.PLC_API_HOST
+
+ # write the configuration file
+ # WORK_DIR must be writable
+ FILE = open(configfile, "w")
+ FILE.write(file)
+ FILE.close()
+
+ return
+
+ # Here starts the execution of the call
+ def call(self, auth, dummybox_id, type):
+
+ # check for dummynet box existence and get dummyboxes information
+ dummybox_info = Nodes(self.api, {'node_id':dummybox_id, 'node_type':'dummynet'}, \
+ ['hostname', 'interface_ids'])
+
+ if dummybox_id != None and not dummybox_info:
+ raise PLCInvalidArgument, "No such DummyBox %s" % dummybox_id
+
+ # Get the dummynet box hostname
+ dummybox_hostname = dummybox_info[0]['hostname']
+ print "dummybox hostname %s" % dummybox_hostname
+
+ # get the node interface, if configured
+ interfaces = Interfaces(self.api, dummybox_info[0]['interface_ids'])
+ for i in interfaces:
+ if i['is_primary']:
+ interface_info = i
+ break
+
+ if not interface_info:
+ raise PLCInvalidArgument, "No primary network configured on %s" % dummybox_hostname
+
+ dummybox = interface_info
+
+ # Select the base image, default to bin image
+ if type != 'iso':
+ type="bin"
+ IMAGE_NAME = str(WORK_DIR) + "/dummybox_" + dummybox_hostname + str(type)
+ BASE_IMAGE = "/usr/share/dummynet/picobsd." + str(type)
+ configfile = WORK_DIR + '/dummybox.conf'
+ lockfile = WORK_DIR + '/lockfile'
+
+ # Permission checks
+ assert self.caller is not None
+ if 'admin' not in self.caller['roles']:
+ if dummybox['site_id'] not in self.caller['site_ids']:
+ raise PLCPermissionDenied, "Not allowed to generate an iso image for %s %s" % \
+ (dummybox['hostname'], dummybox_id)
+
+ # Start the generation of the image
+ # Generate a new key
+ new_key = compute_key()
+
+ # create working dir and lock file for concurrent runs
+ if not os.path.exists(WORK_DIR):
+ print "Creating working directory %s" % WORK_DIR
+ os.mkdir(WORK_DIR)
+
+ if os.path.exists(lockfile):
+ raise PLCInvalidArgument, "Lockfile %s exist, try again " % lockfile
+ else:
+ print "Executing "+"touch %s" % lockfile
+ os.system("touch %s" % lockfile)
+
+ # generate the configuration file
+ conf_file = self.generate_conf_file(dummybox, new_key, configfile)
+
+ # build the shell script to customize the dummynetbox image
+ # copy the raw file and find the configuration file position
+ shell_script = "(cp %s %s; export MATCH=`grep -abo START_USER_DATA %s | cut -d: -f1`; " \
+ % (BASE_IMAGE, IMAGE_NAME, IMAGE_NAME)
+
+ # set permission file
+ shell_script += " chmod u+w %s; chmod u+w %s; " % (IMAGE_NAME, configfile)
+
+ # cat the configuration file in the raw image
+ shell_script += "cat %s | dd of=%s seek=$MATCH conv=notrunc bs=1)" \
+ % (configfile, IMAGE_NAME)
+
+ # check returned values, 0 means OK, remove the lock file
+ os.system(shell_script)
+ os.system("rm %s" % (lockfile))
+
+ # if all goes fine store the key in the database
+ dummybox['key'] = new_key
+ dummybox.sync()
+
+ # return the file
+ return IMAGE_NAME
+ return base64.b64encode(file(IMAGE_NAME).read())