typos
[plcapi.git] / PLC / Methods / GetDummyBoxMedium.py
1 #
2 # Marta Carbone - UniPi
3 # $Id$
4 #
5 # This class requires the rpm package containing
6 # the picobsd image to be installed
7 # on the Central Site system.
8 #
9
10 import base64
11 import os
12 import datetime
13
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
21
22 WORK_DIR = "/var/tmp/DummynetBoxMedium"
23 BASE_IMAGE = "/usr/share/dummynet/picobsd"
24
25 class GetDummyBoxMedium(Method):
26     """
27     This method is used to get a boot image for the DummyNetBox
28     with its configuration file embedded.
29
30     We need to provide the dummybox_id of the DummyNetBox
31     we want to generate.
32     Since every time a new configuration file will be generated,
33     THIS OPERATION WILL INVALIDATE ANY PREVIOUSLY DUMMYNETBOX BOOT MEDIUM.
34
35     Returns the iso image customized for the DummyNetBox with the new
36     key integrated in the image, and update the key fields in the database.
37     """
38     # I added the session role, because this method should be called from the web
39     roles = ['admin', 'pi', 'tech', 'session']
40
41     accepts = [
42         Auth(),
43         Parameter(int, "The dummybox_id"),
44         Parameter(str, "The image type (bin or iso)")
45     ]
46
47     returns = Parameter(str, "DummynetBox boot medium")
48
49     # XXX add checks for picobsd.bin existence
50
51     # Generate a new configuration file in the working directory
52     # input parameters follows:
53     # self is used to access instance data,
54     # dummybox is the dummybox_id,
55     # new_key is the new generated key,
56     # configfile is the output file of the configuration.
57     def generate_conf_file(self, dummybox, new_key, configfile):
58         
59         # Generate the dummynet box configuration file
60         today = datetime.date.today()
61         file = ""
62         file += "# This is the dummynetbox configuration file\n"
63         file += "# and was generated on %s\n" % str(today)
64         
65         host_domain = dummybox['hostname']
66         host_domain = host_domain.split('.', 1)
67         file += 'HOST_NAME="%s"\n' % host_domain[0]
68         file += 'DOMAIN_NAME="%s"\n' % host_domain[1]
69         
70         file += 'IP_ADDRESS="%s"\n' % dummybox['ip']
71         file += 'IP_NETMASK="%s"\n' % dummybox['netmask']
72         file += 'IP_GATEWAY="%s"\n' % dummybox['gateway']
73         file += 'IP_DNS1="%s"\n' % dummybox['dns1']
74         file += 'IP_DNS2="%s"\n' % dummybox['dns2']
75         file += 'DUMMYBOX_ID="%s"\n' % dummybox['node_id']
76         file += 'DUMMYBOX_KEY="%s"\n' % new_key
77         
78         file += 'CS_IP="%s"\n' % self.api.config.PLC_API_HOST
79
80         # write the configuration file
81         # WORK_DIR must be writable
82         FILE = open(configfile, "w")
83         FILE.write(file)
84         FILE.close()
85         
86         return
87         
88     # Here starts the execution of the call
89     def call(self, auth, dummybox_id, type):
90
91         # check for dummynet box existence and get dummyboxes information
92         dummybox_info = Nodes(self.api, {'node_id':dummybox_id, 'node_type':'dummynet'}, \
93                 ['hostname', 'interface_ids'])
94  
95         if dummybox_id != None and not dummybox_info:
96             raise PLCInvalidArgument, "No such DummyBox %s" % dummybox_id
97
98         # Get the dummynet box hostname
99         dummybox_hostname = dummybox_info[0]['hostname']
100         print "dummybox hostname %s" % dummybox_hostname
101
102         # get the node interface, if configured
103         interfaces = Interfaces(self.api, dummybox_info[0]['interface_ids'])
104         for i in interfaces:
105             if i['is_primary']:
106                 interface_info = i
107                 break
108
109         if not interface_info:
110             raise PLCInvalidArgument, "No primary network configured on %s" % dummybox_hostname
111
112         dummybox = interface_info
113         dummybox['hostname']=dummybox_hostname
114
115         # Select the base image, default to bin image
116         if type != 'iso':
117                 type="bin"
118         IMAGE_NAME = str(WORK_DIR) + "/dummybox_" + dummybox_hostname + str(type)
119         BASE_IMAGE = "/usr/share/dummynet/picobsd." + str(type)
120         configfile = WORK_DIR + '/dummybox.conf'
121         lockfile =  WORK_DIR + '/lockfile'
122
123         # Permission checks
124         assert self.caller is not None
125
126         # Start the generation of the image
127         # Generate a new key
128         new_key = compute_key()
129
130         # create working dir and lock file for concurrent runs
131         if not os.path.exists(WORK_DIR):
132             print "Creating working directory %s" % WORK_DIR
133             os.mkdir(WORK_DIR)
134
135         if os.path.exists(lockfile):
136             raise PLCInvalidArgument, "Lockfile %s exist, try again " % lockfile
137         else:
138             print "Executing "+"touch %s" % lockfile
139             os.system("touch %s" % lockfile)
140
141         # generate the configuration file
142         conf_file = self.generate_conf_file(dummybox, new_key, configfile)
143
144         # build the shell script to customize the dummynetbox image
145         # copy the raw file and find the configuration file position
146         shell_script = "(cp %s %s; export MATCH=`grep -abo START_USER_DATA %s | cut -d: -f1`; " \
147                            % (BASE_IMAGE, IMAGE_NAME, IMAGE_NAME)
148
149         # set permission file
150         shell_script += " chmod u+w %s; chmod u+w %s; " % (IMAGE_NAME, configfile)
151
152         # cat the configuration file in the raw image
153         shell_script += " cat %s | dd of=%s seek=$MATCH conv=notrunc bs=1)" \
154                            % (configfile, IMAGE_NAME)
155
156         # check returned values, 0 means OK, remove the lock file
157         os.system(shell_script)
158         os.system("rm %s" % (lockfile))
159
160         # if all goes fine store the key in the database
161         dummybox['key'] = new_key
162         dummybox.sync()
163
164         # return the file
165         #return IMAGE_NAME
166         return base64.b64encode(file(IMAGE_NAME).read())