3-fold nodefamily now has fcdistro as well
[plcapi.git] / PLC / Methods / GetBootMedium.py
index e2d1ebf..e8e796d 100644 (file)
@@ -1,4 +1,5 @@
 # $Id$
+# $URL$
 import random
 import base64
 import os
@@ -13,6 +14,9 @@ from PLC.Auth import Auth
 from PLC.Nodes import Node, Nodes
 from PLC.Interfaces import Interface, Interfaces
 from PLC.InterfaceTags import InterfaceTag, InterfaceTags
+from PLC.NodeTags import NodeTag, NodeTags
+
+from PLC.Accessors.Accessors_standard import *                 # import node accessors
 
 # could not define this in the class..
 # create a dict with the allowed actions for each type of node
@@ -24,10 +28,6 @@ allowed_actions = {
                               'generic-iso',
                               'generic-usb',
                                ],
-                'dummynet' : [ 'node-preview',
-                               'dummynet-iso',
-                               'dummynet-usb',
-                             ],
                 }
 
 # compute a new key
@@ -46,7 +46,7 @@ class GetBootMedium(Method):
     This method is a redesign based on former, supposedly dedicated, 
     AdmGenerateNodeConfFile
 
-    As compared with its ancestor, this method provides a much more detailed
+    As compared with its ancestor, this method provides a much more 
     detailed interface, that allows to
     (*) either just preview the node config file -- in which case 
         the node key is NOT recomputed, and NOT provided in the output
@@ -68,11 +68,6 @@ class GetBootMedium(Method):
     (*) generic-iso
     (*) generic-usb
 
-    for a 'dummynet' node:
-    (*) node-preview
-    (*) dummynet-iso
-    (*) dummynet-usb
-
     Apart for the preview mode, this method generates a new node key for the
     specified node, effectively invalidating any old boot medium.
 
@@ -102,17 +97,23 @@ class GetBootMedium(Method):
 
     Options: an optional array of keywords. 
         options are not supported for generic images
-        options are not supported for dummynet boxes
-    Currently supported are
+      Currently supported are
         - 'partition' - for USB actions only
         - 'cramfs'
         - 'serial' or 'serial:<console_spec>'
-        - 'no-hangcheck'
         console_spec (or 'default') is passed as-is to bootcd/build.sh
         it is expected to be a colon separated string denoting
         tty - baudrate - parity - bits
         e.g. ttyS0:115200:n:8
-
+        - 'variant:<variantname>'
+        passed to build.sh as -V <variant> 
+        variants are used to run a different kernel on the bootCD
+        see kvariant.sh for how to create a variant
+        - 'no-hangcheck' - disable hangcheck
+
+    Tags: the following tags are taken into account when attached to the node:
+        'serial', 'cramfs', 'kvariant', 'kargs', 'no-hangcheck'
+        
     Security:
         - Non-admins can only generate files for nodes at their sites.
         - Non-admins, when they provide a filename, *must* specify it in the %d area
@@ -231,7 +232,7 @@ class GetBootMedium(Method):
             if category_settings:
                 file += '### Category : %s\n'%category
                 for setting in category_settings:
-                    file += '%s_%s="%s"\n'%(category.upper(),setting['name'].upper(),setting['value'])
+                    file += '%s_%s="%s"\n'%(category.upper(),setting['tagname'].upper(),setting['value'])
 
         for interface in interfaces:
             if interface['method'] == 'ipmi':
@@ -242,26 +243,27 @@ class GetBootMedium(Method):
 
         return file
 
-    # see also InstallBootstrapFS in bootmanager that does similar things
+    # see also GetNodeFlavour that does similar things
     def get_nodefamily (self, node):
-        # get defaults from the myplc build
-        try:
-            (pldistro,arch) = file("/etc/planetlab/nodefamily").read().strip().split("-")
-        except:
-            (pldistro,arch) = ("planetlab","i386")
-            
-        # with no valid argument, return system-wide defaults
+        pldistro = self.api.config.PLC_FLAVOUR_NODE_PLDISTRO
+        fcdistro = self.api.config.PLC_FLAVOUR_NODE_FCDISTRO
+        arch: arch = self.api.config.PLC_FLAVOUR_NODE_ARCH
         if not node:
-            return (pldistro,arch)
-
+            return (pldistro,fcdistro,arch)
+        
         node_id=node['node_id']
+        
+        # no support for deployment-based BootCD's, use kvariants instead
+        node_pldistro = GetNodePldistro (self.api).call(auth, node_id)
+        if node_pldistro: pldistro = node_pldistro
 
-        tag=Nodes(self.api,[node_id],['arch'])[0]['arch']
-        if tag: arch=tag
-        tag=Nodes(self.api,[node_id],['pldistro'])[0]['pldistro']
-        if tag: pldistro=tag
+        node_fcdistro = GetNodeFcdistro (self.api).call(auth, node_id)
+        if node_fcdistro: fcdistro = node_fcdistro
 
-        return (pldistro,arch)
+        node_arch = GetNodeArch (self.api).call(auth,node_id)
+        if node_arch: arch = node_arch
+        
+        return (pldistro,fcdistro,arch)
 
     def bootcd_version (self):
         try:
@@ -333,6 +335,8 @@ class GetBootMedium(Method):
                 type += "_cramfs"
             if "serial" in build_sh_spec: 
                 build_sh_options += " -s %s"%build_sh_spec['serial']
+            if "variant" in build_sh_spec:
+                build_sh_options += " -V %s"%build_sh_spec['variant']
             
             for karg in build_sh_spec['kargs']:
                 build_sh_options += ' -k "%s"'%karg
@@ -345,20 +349,6 @@ class GetBootMedium(Method):
                                                                  type,
                                                                  build_sh_options,
                                                                  log_file)
-        # dummynet node
-        elif node_type == 'dummynet':
-            # the build script expect the following parameters:
-            # the package base directory
-            # the working directory
-            # the full path of the configuration file
-            # the name of the resulting image file
-            # the type of the generated image
-            # the name of the log file
-            command = "%s -b %s -w %s -f %s -o %s -t %s -l %s" \
-                        % (self.BOOTCDBUILD, self.BOOTCDDIR, self.WORKDIR,
-                           floppy_file, node_image, type, log_file)
-            command = "touch %s %s; echo 'dummynet build script not yet supported'" \
-                        % (log_file, node_image)
 
         if self.DEBUG:
             print "The build command line is %s" % command
@@ -402,6 +392,25 @@ class GetBootMedium(Method):
         else:
             # create a dict for build.sh 
             build_sh_spec={'kargs':[]}
+            # use node tags as defaults
+            # check for node tag equivalents
+            tags = NodeTags(self.api, 
+                            {'node_id': node['node_id'], 
+                             'tagname': ['serial', 'cramfs', 'kvariant', 'kargs', 'no-hangcheck']},
+                            ['tagname', 'value'])
+            if tags:
+                for tag in tags:
+                    if tag['tagname'] == 'serial':
+                        build_sh_spec['serial'] = tag['value']
+                    if tag['tagname'] == 'cramfs':
+                        build_sh_spec['cramfs'] = True
+                    if tag['tagname'] == 'kvariant':
+                        build_sh_spec['variant'] = tag['value']
+                    if tag['tagname'] == 'kargs':
+                        build_sh_spec['kargs'].append(tag['value'].split())
+                    if tag['tagname'] == 'no-hangcheck':
+                        build_sh_spec['kargs'].append('hcheck_reboot0')
+            # then options can override tags
             for option in options:
                 if option == "cramfs":
                     build_sh_spec['cramfs']=True
@@ -414,13 +423,15 @@ class GetBootMedium(Method):
                     build_sh_spec['serial']='default'
                 elif option.find("serial:") == 0:
                     build_sh_spec['serial']=option.replace("serial:","")
+                elif option.find("variant:") == 0:
+                    build_sh_spec['variant']=option.replace("variant:","")
                 elif option == "no-hangcheck":
                     build_sh_spec['kargs'].append('hcheck_reboot0')
                 else:
                     raise PLCInvalidArgument, "unknown option %s"%option
 
         # compute nodename according the action
-        if action.find("node-") == 0 or action.find("dummynet-") == 0:
+        if action.find("node-") == 0:
             nodename = node['hostname']
         else:
             node = None
@@ -429,15 +440,9 @@ class GetBootMedium(Method):
             def hexa2 (c): return chr((c>>4)+65) + chr ((c&16)+65)
             nodename = "".join(map(hexa2,tempbytes))
 
-        # override some global definition, according node_type
-        if node_type == 'dummynet':
-            self.BOOTCDDIR = "/usr/share/dummynet"             # the base installation dir
-            self.BOOTCDBUILD = "/usr/share/dummynet/build.sh"  # dummynet build script
-            self.WORKDIR = "/var/tmp/DummynetBoxMedium"                # temporary working dir
-
         # get nodefamily
-        (pldistro,arch) = self.get_nodefamily(node)
-        self.nodefamily="%s-%s"%(pldistro,arch)
+        (pldistro,fcdistro,arch) = self.get_nodefamily(node)
+        self.nodefamily="%s-%s-%s"%(pldistro,fcdistro,arch)
 
         # apply on globals
         for attr in [ "BOOTCDDIR", "BOOTCDBUILD", "GENERICDIR" ]:
@@ -493,8 +498,7 @@ class GetBootMedium(Method):
         # - build and invoke the build command
         # - delivery the resulting image file
 
-        if action == 'node-iso' or action == 'node-usb' \
-                 or action == 'dummynet-iso' or action == 'dummynet-usb':
+        if action == 'node-iso' or action == 'node-usb':
 
             ### check we've got required material
             version = self.bootcd_version()