30a7b8fb604cf4b9cd37e18fe9f78312033d914a
[plcapi.git] / PLC / Methods / GetNodeFlavour.py
1 import traceback
2
3 from PLC.Method import Method
4 from PLC.Auth import Auth
5 from PLC.Faults import *
6 from PLC.Parameter import *
7 from PLC.Nodes import Node, Nodes
8
9 from PLC.Accessors.Accessors_standard import *                  # import node accessors
10
11 class GetNodeFlavour(Method):
12     """
13     Returns detailed information on a given node's flavour, i.e. its
14     base installation.
15
16     This depends on the global PLC settings in the PLC_FLAVOUR area,
17     optionnally overridden by any of the following tags if set on that node:
18
19     'arch', 'pldistro', 'fcdistro',
20     'deployment', 'extensions', 'virt', 
21     """
22
23     roles = ['admin', 'user', 'node']
24
25     accepts = [
26         Auth(),
27         Mixed(Node.fields['node_id'],
28               Node.fields['hostname']),
29         ]
30
31     returns = {
32         'nodefamily' : Parameter (str, "the nodefamily this node should be based upon"),
33         'fcdistro': Parameter (str, "the fcdistro this node should be based upon"),
34         'extensions' : [ Parameter (str, "extensions to add to the base install") ],
35         'plain' : Parameter (bool, "use plain bootstrapfs image if set (for tests)" ) ,
36         }
37
38
39     ########## nodefamily
40     def nodefamily (self, auth, node_id, fcdistro, pldistro, arch):
41
42         # the deployment tag, if set, wins
43         # xxx Thierry: this probably is wrong; we need fcdistro to be set anyway
44         # for generating the proper yum config....
45         deployment = GetNodeDeployment (self.api,self.caller).call(auth,node_id)
46         if deployment: return deployment
47
48         # xxx would make sense to check the corresponding bootstrapfs is available
49         return "%s-%s-%s"%(pldistro,fcdistro,arch)
50
51     ##########
52     # parse PLC_FLAVOUR_VIRT_MAP 
53     known_virts=['vs','lxc']
54     default_virt='vs'
55     def virt_from_virt_map (self, node_fcdistro):
56         map={}
57         try:
58             assigns=[x.strip() for x in self.api.config.PLC_FLAVOUR_VIRT_MAP.split(';')]
59             for assign in assigns:
60                 (left,right)=[x.strip() for x in assign.split(':')]
61                 if right not in GetNodeFlavour.known_virts:
62                     print >> log, "GetNodeFlavour, unknown 'virt' %s - ignored" % right
63                     continue
64                 for fcdistro in [ x.strip() for x in left.split(',')]:
65                     map[fcdistro]=right
66         except:
67             print >> log, "GetNodeFlavour, issue with parsing PLC_FLAVOUR_VIRT_MAP=%s - returning '%s'"%\
68                 (self.api.config.PLC_FLAVOUR_VIRT_MAP,GetNodeFlavour.default_virt)
69             traceback.print_exc(file=log)
70             return GetNodeFlavour.default_virt
71 #        print 'virt_from_virt_map, using map',map
72         if node_fcdistro in map:  return map[node_fcdistro]
73         if 'default' in map: return map['default']
74         return GetNodeFlavour.default_virt
75             
76
77     def extensions (self, auth, node_id, fcdistro, arch):
78         try:
79             return [ "%s-%s-%s"%(e,fcdistro,arch) for e in GetNodeExtensions(self.api,self.caller).call(auth,node_id).split() ]
80         except:
81             return []
82
83     def plain (self, auth, node_id):
84         return not not GetNodePlainBootstrapfs(self.api,self.caller).call(auth,node_id)
85
86     def call(self, auth, node_id_or_name):
87         # Get node information
88         nodes = Nodes(self.api, [node_id_or_name])
89         if not nodes:
90             raise PLCInvalidArgument, "No such node %r"%node_id_or_name
91         node = nodes[0]
92         node_id = node['node_id']
93
94         arch = GetNodeArch (self.api,self.caller).call(auth,node_id)
95         # if not set, use the global default and tag the node, in case the global default changes later on
96         if not arch:
97             arch = self.api.config.PLC_FLAVOUR_NODE_ARCH
98             SetNodeArch (self.api,self.caller).call(auth,node_id,arch)
99
100         fcdistro = GetNodeFcdistro (self.api,self.caller).call(auth, node_id)
101         if not fcdistro:
102             fcdistro = self.api.config.PLC_FLAVOUR_NODE_FCDISTRO
103             SetNodeFcdistro (self.api,self.caller).call (auth, node_id, fcdistro)
104
105         pldistro = GetNodePldistro (self.api,self.caller).call(auth, node_id)
106         if not pldistro:
107             pldistro = self.api.config.PLC_FLAVOUR_NODE_PLDISTRO
108             SetNodePldistro(self.api,self.caller).call(auth,node_id,pldistro)
109
110         virt = GetNodeVirt (self.api,self.caller).call(auth, node_id)
111         if not virt:
112             virt = self.virt_from_virt_map (fcdistro)
113             # do not save in node - if a node was e.g. f14 and it gets set to f16
114             # we do not want to have to re-set virt
115             # SetNodeVirt (self.api, self.caller).call (auth, node_id, virt)
116
117         # xxx could use some sanity checking, and could provide fallbacks
118         return {
119             'arch'      : arch,
120             'fcdistro'  : fcdistro,
121             'pldistro'  : pldistro,
122             'virt'      : virt,
123             'nodefamily': self.nodefamily(auth,node_id, fcdistro, pldistro, arch),
124             'extensions': self.extensions(auth,node_id, fcdistro, arch),
125             'plain'     : self.plain(auth,node_id),
126             }