GetNodeFlavour exposes 'virt' based on node's 'virt' tag, or on PLC_FLAVOUR_VIRT_MAP
[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, 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 "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 "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()
70             return GetNodeFlavour.default_virt
71         if fcdistro in map:  return map[fcdistro]
72         if 'default' in map: return map['default']
73         return GetNodeFlavour.default_virt
74             
75
76     def extensions (self, auth, node_id, fcdistro, arch):
77         try:
78             return [ "%s-%s-%s"%(e,fcdistro,arch) for e in GetNodeExtensions(self.api,self.caller).call(auth,node_id).split() ]
79         except:
80             return []
81
82     def plain (self, auth, node_id):
83         return not not GetNodePlainBootstrapfs(self.api,self.caller).call(auth,node_id)
84
85     def call(self, auth, node_id_or_name):
86         # Get node information
87         nodes = Nodes(self.api, [node_id_or_name])
88         if not nodes:
89             raise PLCInvalidArgument, "No such node %r"%node_id_or_name
90         node = nodes[0]
91         node_id = node['node_id']
92
93         arch = GetNodeArch (self.api,self.caller).call(auth,node_id)
94         # if not set, use the global default and tag the node, in case the global default changes later on
95         if not arch:
96             arch = self.api.config.PLC_FLAVOUR_NODE_ARCH
97             SetNodeArch (self.api,self.caller).call(auth,node_id,arch)
98
99         fcdistro = GetNodeFcdistro (self.api,self.caller).call(auth, node_id)
100         if not fcdistro:
101             fcdistro = self.api.config.PLC_FLAVOUR_NODE_FCDISTRO
102             SetNodeFcdistro (self.api,self.caller).call (auth, node_id, fcdistro)
103
104         pldistro = GetNodePldistro (self.api,self.caller).call(auth, node_id)
105         if not pldistro:
106             pldistro = self.api.config.PLC_FLAVOUR_NODE_PLDISTRO
107             SetNodePldistro(self.api,self.caller).call(auth,node_id,pldistro)
108
109         virt = GetNodeVirt (self.api,self.caller).call(auth, node_id)
110         if not virt:
111             virt = self.virt_from_virt_map (fcdistro)
112             SetNodeVirt (self.api, self.caller).call (auth, node_id, virt)
113
114         # xxx could use some sanity checking, and could provide fallbacks
115         return {
116             'arch'      : arch,
117             'fcdistro'  : fcdistro,
118             'pldistro'  : pldistro,
119             'virt'      : virt,
120             'nodefamily': self.nodefamily(auth,node_id, fcdistro, pldistro, arch),
121             'extensions': self.extensions(auth,node_id, fcdistro, arch),
122             'plain'     : self.plain(auth,node_id),
123             }