From 3cb520f37b53d23865bd09259b812d2591be769f Mon Sep 17 00:00:00 2001 From: Marta Carbone Date: Mon, 20 Apr 2009 14:41:48 +0000 Subject: [PATCH] Added a Method to generate dummynet box images. Fixed typo in the Get Users script. --- PLC/Methods/GetDummyBoxMedium.py | 168 +++++++++++++++++++++++++++++++ PLC/Methods/GetDummyBoxUsers.py | 3 +- PLC/Methods/__init__.py | 1 + 3 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 PLC/Methods/GetDummyBoxMedium.py diff --git a/PLC/Methods/GetDummyBoxMedium.py b/PLC/Methods/GetDummyBoxMedium.py new file mode 100644 index 0000000..2fb4e55 --- /dev/null +++ b/PLC/Methods/GetDummyBoxMedium.py @@ -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()) diff --git a/PLC/Methods/GetDummyBoxUsers.py b/PLC/Methods/GetDummyBoxUsers.py index d3236e7..3ef9dc9 100644 --- a/PLC/Methods/GetDummyBoxUsers.py +++ b/PLC/Methods/GetDummyBoxUsers.py @@ -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 diff --git a/PLC/Methods/__init__.py b/PLC/Methods/__init__.py index 0414099..f371aa6 100644 --- a/PLC/Methods/__init__.py +++ b/PLC/Methods/__init__.py @@ -91,6 +91,7 @@ GetAddresses GetBootMedium GetBootStates GetConfFiles +GetDummyBoxMedium GetDummyBoxUsers GetEventObjects GetEvents -- 2.43.0