blob: 5b5d97a68657743d4d3760a4a1bced60717362aa [file] [log] [blame]
Ales Komarek166cc672016-07-27 14:17:22 +02001# -*- coding: utf-8 -*-
2'''
3Module for handling reclass files.
4
5'''
6
7from __future__ import absolute_import
8
9import logging
10import os
11import sys
Ales Komareka961df42016-11-21 21:50:24 +010012import six
Ales Komarek166cc672016-07-27 14:17:22 +020013import yaml
Ales Komareka961df42016-11-21 21:50:24 +010014import json
Ales Komarek166cc672016-07-27 14:17:22 +020015
16LOG = logging.getLogger(__name__)
17
18RECLASS_NODES_DIR = "/srv/salt/reclass/nodes"
19RECLASS_CLASSES_DIR = "/srv/salt/reclass/classes"
20
Ales Komareka961df42016-11-21 21:50:24 +010021
Ales Komarek166cc672016-07-27 14:17:22 +020022def __virtual__():
23 '''
24 Only load this module if reclass
25 is installed on this minion.
26 '''
27 return 'reclass'
28
29
30__opts__ = {}
31
32
33def node_create(name, path=None, cluster="default", environment="prd", classes=None, parameters=None, **kwargs):
34 '''
35 Create a reclass node
36
37 :param name: new node FQDN
38 :param path: custom path in nodes for new node
39 :param classes: classes given to the new node
40 :param parameters: parameters given to the new node
41 :param environment: node's environment
42 :param cluster: node's cluster
43
44 CLI Examples:
45
46 .. code-block:: bash
47
48 salt '*' reclass.node_create server.domain.com classes=[system.neco1, system.neco2]
49 salt '*' reclass.node_create namespace/test enabled=False
50
51 '''
52 ret = {}
53
54 node = node_get(name=name)
55
56 if node and not "Error" in node:
57 LOG.debug("node {0} exists".format(name))
58 ret[name] = node
59 return ret
60
61 host_name = name.split('.')[0]
62 domain_name = '.'.join(name.split('.')[1:])
63
64 if classes == None:
65 meta_classes = []
66 else:
Ales Komareka961df42016-11-21 21:50:24 +010067 if isinstance(classes, six.string_types):
68 meta_classes = json.loads(classes)
69 else:
70 meta_classes = classes
Ales Komarek166cc672016-07-27 14:17:22 +020071
72 if parameters == None:
73 meta_parameters = {}
74 else:
Ales Komareka961df42016-11-21 21:50:24 +010075 if isinstance(parameters, six.string_types):
76 meta_parameters = json.loads(parameters)
77 else:
78 meta_parameters = parameters
Ales Komarek166cc672016-07-27 14:17:22 +020079
80 node_meta = {
81 'classes': meta_classes,
82 'parameters': {
83 '_param': meta_parameters,
84 'linux': {
85 'system': {
86 'name': host_name,
87 'domain': domain_name,
88 'cluster': cluster,
89 'environment': environment,
90 }
91 }
92 }
93 }
94 LOG.debug(node_meta)
95
96 if path == None:
97 file_path = os.path.join(RECLASS_NODES_DIR, name + '.yml')
98 else:
99 file_path = os.path.join(RECLASS_NODES_DIR, path, name + '.yml')
100
101 with open(file_path, 'w') as node_file:
Ales Komareka961df42016-11-21 21:50:24 +0100102 node_file.write(yaml.safe_dump(node_meta, default_flow_style=False))
Ales Komarek71f94b02016-07-27 14:48:57 +0200103
Ales Komarek166cc672016-07-27 14:17:22 +0200104 return node_get(name)
105
106def node_delete(name, **kwargs):
107 '''
108 Delete a reclass node
109
110 :params node: Node name
111
112 CLI Examples:
113
114 .. code-block:: bash
115
116 salt '*' reclass.node_delete demo01.domain.com
117 salt '*' reclass.node_delete name=demo01.domain.com
118 '''
119
120 node = node_get(name=name)
121
122 if 'Error' in node:
123 return {'Error': 'Unable to retreive node'}
124
125 if node[name]['path'] == '':
126 file_path = os.path.join(RECLASS_NODES_DIR, name + '.yml')
127 else:
128 file_path = os.path.join(RECLASS_NODES_DIR, node[name]['path'], name + '.yml')
129
130 os.remove(file_path)
131
132 ret = 'Node {0} deleted'.format(name)
133
134 return ret
135
136
137def node_get(name, path=None, **kwargs):
138 '''
139 Return a specific node
140
141 CLI Examples:
142
143 .. code-block:: bash
144
145 salt '*' reclass.node_get host01.domain.com
146 salt '*' reclass.node_get name=host02.domain.com
147 '''
148 ret = {}
149 nodes = node_list(**kwargs)
150
151 if not name in nodes:
152 return {'Error': 'Error in retrieving node'}
153 ret[name] = nodes[name]
154 return ret
155
156
157def node_list(**connection_args):
158 '''
159 Return a list of available nodes
160
161 CLI Example:
162
163 .. code-block:: bash
164
165 salt '*' reclass.node_list
166 '''
167 ret = {}
168
169 for root, sub_folders, files in os.walk(RECLASS_NODES_DIR):
170 for file in files:
171 file_path = os.path.join(root, file)
172 file_content = open(file_path, 'r')
173 file_data = yaml.load(file_content.read())
174 file_content.close()
175 if 'classes' in file_data:
176 classes = file_data.get('classes')
177 else:
178 classes = []
179 if 'parameters' in file_data:
180 if '_param' in file_data.get('parameters'):
181 parameters = file_data.get('parameters').get('_param')
182 else:
183 parameters = []
184 else:
185 parameters = []
186 name = file.replace('.yml', '')
187 host_name = name.split('.')[0]
188 domain_name = '.'.join(name.split('.')[1:])
189 path = root.replace(RECLASS_NODES_DIR+'/', '')
190 ret[name] = {
191 'name': host_name,
192 'domain': domain_name,
193 'cluster': 'default',
194 'environment': 'prd',
195 'path': path,
196 'classes': classes,
197 'parameters': parameters
198 }
199
200 return ret
201
202def node_update(name, classes=None, parameters=None, **connection_args):
203 '''
204 Update a node metadata information, classes and parameters.
205
206 CLI Examples:
207
208 .. code-block:: bash
209
210 salt '*' reclass.node_update name=nodename classes="[clas1, class2]"
211 '''
212 node = node_get(name=name)
213 if not node.has_key('Error'):
Ales Komarek71f94b02016-07-27 14:48:57 +0200214 node = node[name.split("/")[1]]
215 else:
216 return {'Error': 'Error in retrieving node'}