Added a Method to generate dummynet box images.
authorMarta Carbone <marta@prova.iet.unipi.it>
Mon, 20 Apr 2009 14:41:48 +0000 (14:41 +0000)
committerMarta Carbone <marta@prova.iet.unipi.it>
Mon, 20 Apr 2009 14:41:48 +0000 (14:41 +0000)
Fixed typo in the Get Users script.

PLC/Methods/GetDummyBoxMedium.py [new file with mode: 0644]
PLC/Methods/GetDummyBoxUsers.py
PLC/Methods/__init__.py

diff --git a/PLC/Methods/GetDummyBoxMedium.py b/PLC/Methods/GetDummyBoxMedium.py
new file mode 100644 (file)
index 0000000..2fb4e55
--- /dev/null
@@ -0,0 +1,168 @@
+#
+# 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())
index d3236e7..3ef9dc9 100644 (file)
@@ -83,8 +83,7 @@ class GetDummyBoxUsers(Method):
 
                node_list = []
                for i in connected_nodes:
-                       node_list.append(i['node_id'])
-
+                       node_list.append(['node_id'])
 
                nodes = Nodes(self.api, node_list, ['node_id', 'hostname', 'slice_ids'])
                if not nodes: return 0
index 0414099..f371aa6 100644 (file)
@@ -91,6 +91,7 @@ GetAddresses
 GetBootMedium
 GetBootStates
 GetConfFiles
+GetDummyBoxMedium
 GetDummyBoxUsers
 GetEventObjects
 GetEvents