facter: move to a directory of its own
[racktables-contribs] / facter / facter.php
CommitLineData
38ba29a5
AD
1<?php
2/*
3 * Facter (Puppet) plugin for racktables 0.19.1 (and probably newer)
1806a4df
DO
4*
5* This file is both a web GUI and REST webservice for auto create and update machines based on facter (puppet) files.
6*
7* REST examples:
8* curl -k -F myfile=@facter.txt -u username:password https://facter/racktables/process.php?page=depot&tab=facter&op=Update
9* curl -F myfile=@facter.txt -u username:password http://facter/racktables/process.php?page=depot&tab=facter&op=Update
10*
11* Usage instructions:
12* * Just symlink it to your inc folder
13* * add it to the local.php file inn your inc folder: echo "<?php include_once 'facter.php'; ?>" >> inc/local.php
14* * If you want you can add the CPU attribute and it will show you your cpu's aswell
15*
16* Author: Torstein Hansen <huleboer@users.sourceforge.net>, sponsored by eniro.no
17*
18* This script is based on yaml_import for racktables by Tommy Botten Jensen
19*
20* 2011-08-25 modified by Neil Scholten <neil.scholten@gamigo.com>
21* - adjusted path for racktables > 0.19.1
22* - modified .yaml parsing to match to 'facter -py' format
23* - modified interface-type detection to use virtual port on VMs
24* - modified OS detection to match more better default sets (Testcase: CentOS).
25*
26*/
38ba29a5
AD
27
28
29// Depot Tab for objects.
30$tab['depot']['facter'] = 'Facter';
31$tabhandler['depot']['facter'] = 'ViewHTML';
32$ophandler['depot']['facter']['Update'] = 'Update';
33
34
35// The ophandler to insert objects (if any)
36function Update()
37{
1806a4df
DO
38 // Read uploaded file
39 $lines = file($_FILES['userfile']['tmp_name']);
40
41 // add file contents to facter array
42 foreach ($lines as $line_num => $line)
43 {
44 $tmpfacter=explode(":",$line,2);
45 $facter[trim($tmpfacter[0])]=str_replace('"', '',trim($tmpfacter[1]));
46 }
47
48 // Fix fqdn since all fields have \n inn them
49 $facter['fqdn']=str_replace("\n","", $facter['fqdn']);
50
51 // Check if it's an existing machine
5d5dbda0
DO
52 // 2011-08-31 <neil.scholten@gamigo.com>
53 // * expanded query to try to match via facter Serialnumber to be able to
54 // match unnamed HW assets. Serial is more precise and less likely to be changed.
55 if (
56 array_key_exists('serialnumber', $facter) &&
57 strlen($facter['serialnumber']) > 0 &&
58 $facter['serialnumber'] != 'Not Specified' ) {
59 $query = "select id from RackObject where name = \"$facter[fqdn]\" OR asset_no = \"$facter[serialnumber]\" LIMIT 1";
60 } else {
61 $query = "select id from RackObject where name = \"$facter[fqdn]\" LIMIT 1";
62 }
1806a4df
DO
63 unset($result);
64 $result = usePreparedSelectBlade ($query);
65 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
66 if($resultarray) {
67 $id=$resultarray[0]['id'];
68 }
69
70 // If it's a new machine
71 if (! isset($id))
72 {
73 // Check to see if it's a physical machine and get the correct id for Server
5d5dbda0 74 if ($facter['is_virtual']=="false")
1806a4df
DO
75 {
76 // Find server id
77 $query = "select dict_key from Dictionary where dict_value='Server' LIMIT 1";
78 unset($result);
79 $result = usePreparedSelectBlade ($query);
80 $resultarray = $result->fetchAll ();
81 if($resultarray)
82 {
83 $virtual=$resultarray[0]['dict_key'];
84 }
85 }
86 // Check to see if it's a virtual machine and get the correct id for VM
87 else
88 {
89 // Find virtual id
90 $query = "select dict_key from Dictionary where dict_value='VM' LIMIT 1";
91 unset($result);
92 $result = usePreparedSelectBlade ($query);
93 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
94 if($resultarray)
95 {
96 $virtual=$resultarray[0]['dict_key'];
97 }
98 }
99 // Add the new machine
100 $newmachine=commitAddObject($facter['fqdn'],$facter['fqdn'],$virtual,$value = "");
101 }
102 // If it's an existing machine
103 else
104 {
105 // Just set some fields I use later down for updating
106 $newmachine=$id;
107 $machineupdate=1;
108 }
109
110
111
112 // Add lot's of attributes to the machine. Next version use an array (from config file) and do a loop for most of these fields.....
113
5d5dbda0
DO
114 // 2011-08-31 <neil.scholten@gamigo.com>
115 // * Update (unique) name of object.
116 if (
117 array_key_exists('serialnumber', $facter) &&
118 strlen($facter['serialnumber']) > 0 &&
119 $facter['serialnumber'] != 'Not Specified' ) {
120
121 unset($result);
122 $query = "select * from RackObject where asset_no = \"$facter[serialnumber]\" LIMIT 1";
123 $result = usePreparedSelectBlade ($query);
124 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
125 if($resultarray) {
126 $id = $resultarray[0]['id'];
127 $label = $resultarray[0]['label'];
128 // Update FQDN
129 commitUpdateObject($id, $facter['fqdn'], $label, 'no', $facter['serialnumber'], 'Facter Import::Update Common Name');
130 }
131 }
132
1806a4df
DO
133 // Find FQDN id
134 $query = "select id from Attribute where name='FQDN' LIMIT 1";
135 unset($result);
136 $result = usePreparedSelectBlade ($query);
137 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
138 if($resultarray) {
139 $id=$resultarray[0]['id'];
140 // Update FQDN
141 commitUpdateAttrValue ($object_id = $newmachine, $attr_id = $id, $value = $facter['fqdn']);
142 }
143
144
145 // Find HW type id
5d5dbda0
DO
146 // 2011-08-31 <neil.scholten@gamigo.com>
147 // * adjust format to match default Dictionary Sets
148 $iHWTemp = preg_match('([a-zA-Z]{1,})', $facter['manufacturer'], $matches);
149 $sManufacturer = $matches[0];
150 $sHW = preg_replace('(\ )', '\1%GPASS%', $facter['productname']);
151 $sHWType = $sManufacturer.' '.$sHW;
152 $query = "select id from Attribute where name='HW type' LIMIT 1";
1806a4df
DO
153 unset($result);
154 $result = usePreparedSelectBlade ($query);
155 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
156 if($resultarray) {
157 $id=$resultarray[0]['id'];
158 // Update HW type
5d5dbda0 159 $hw_dict_key = getdict($sHWType, $chapter=11 );
1806a4df
DO
160 commitUpdateAttrValue ($object_id = $newmachine, $attr_id = $id, $value = $hw_dict_key);
161 }
162
163
164 // Find SW type id (OS)
165 $query = "select id from Attribute where name='SW type' LIMIT 1";
166 unset($result);
167 $result = usePreparedSelectBlade ($query);
168 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
169 if($resultarray) {
170 $id=$resultarray[0]['id'];
171 // Update SW type (OS)
172 $osrelease = $facter['lsbdistid'] . '%GSKIP%' . $facter['lsbdistid'] . ' V' . $facter['lsbmajdistrelease'];
173 $os_dict_key = getdict($hw=$osrelease, $chapter=13);
174 commitUpdateAttrValue ($object_id = $newmachine, $attr_id = $id, $value = $os_dict_key);
175 }
176
177
178 // Find OEM S/N 1
179 $query = "select id from Attribute where name='OEM S/N 1' LIMIT 1";
180 unset($result);
181 $result = usePreparedSelectBlade ($query);
182 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
183 if($resultarray) {
184 $id=$resultarray[0]['id'];
185 // Update serial number
186 commitUpdateAttrValue ($object_id = $newmachine, $attr_id = $id, $value = $facter['serialnumber']);
187 }
188
189
190 // Find Architecture id
191 $query = "select id from Attribute where name='Architecture' LIMIT 1";
192 unset($result);
193 $result = usePreparedSelectBlade ($query);
194 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
195 if($resultarray) {
196 $id=$resultarray[0]['id'];
197 // Update Architecture id
198 commitUpdateAttrValue ($object_id = $newmachine, $attr_id = $id, $value = $facter['architecture']);
199 }
200
201
202
203 // Find Memory id
204 $query = "select id from Attribute where name='DRAM, GIB' LIMIT 1";
205 unset($result);
206 $result = usePreparedSelectBlade ($query);
207 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
208 if($resultarray) {
209 $id=$resultarray[0]['id'];
210 // Update Memory id
211 commitUpdateAttrValue ($object_id = $newmachine, $attr_id = $id, $value = $facter['memorysize']);
212 }
213
214
215 // Find CPU id (custom field you'll need to add yourself)
216 $cpu = $facter['processorcount'] . " x " . $facter['processor0'];
217 $query = "select id from Attribute where name='CPU' LIMIT 1";
218 unset($result);
219 $result = usePreparedSelectBlade ($query);
220 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
221 if($resultarray) {
222 $id=$resultarray[0]['id'];
223 // Update CPU id
224 $cpu = $facter['processorcount'] . " x " . $facter['processor0'];
225 commitUpdateAttrValue ($object_id = $newmachine, $id, $value = $cpu);
226 }
227
228 // Add network interfaces
229
230 // Create an array with interfaces
231 $nics = explode(',',$facter['interfaces']);
232
233 // Go thew all interfaces and add IP and MAC
234 $count = count($nics);
235 for ($i = 0; $i < $count; $i++) {
236 // Remove newline from the field
237 $nics[$i]=str_replace("\n","", $nics[$i]);
238
239 // We generally don't monitor sit interfaces.
240 // We don't do this for lo interfaces, too
5d5dbda0
DO
241 // 2011-08-31 <neil.scholten@gamigo.com>
242 // * Only Document real interfaces, dont do bridges, bonds, vlan-interfaces
243 // when they have no IP defined.
244 if ( preg_match('(_|^(br|bond|lo|sit|vnet|virbr))',$nics[$i]) != 0 && !isset($facter['ipaddress_' . $nics[$i]]) ) {
245 // do nothing
246 } else {
247 // Get IP
248 if (isset($facter['ipaddress_' . $nics[$i]]))
249 $ip = $facter['ipaddress_' . $nics[$i]];
250
251 // Get MAC
252 if (isset($facter['macaddress_' . $nics[$i]]))
253 $mac = $facter['macaddress_' . $nics[$i]];
254
255 //check if VM or not
256 if ($facter['is_virtual']=="false")
257 {
258 // Find 1000Base-T id
259 $query = "select dict_key from Dictionary where dict_value='1000Base-T' LIMIT 1";
1806a4df 260 }
5d5dbda0
DO
261 else
262 {
263 // Find virtual port id
264 $query = "select dict_key from Dictionary where dict_value='virtual port' LIMIT 1";
265 }
266 unset($result);
267 $result = usePreparedSelectBlade ($query);
268 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
269 if($resultarray) {
270 $nictypeid=$resultarray[0]['dict_key'];
271 }
272
273 // Remove newline from ip
274 $ip=str_replace("\n","", $ip);
275
276 // Check to se if the interface has an ip assigned
277 $query = "SELECT object_id FROM IPv4Allocation where object_id=$newmachine and name=\"$nics[$i]\"";
278 unset($result);
279 $result = usePreparedSelectBlade ($query);
280 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
281
282 if($resultarray) {
283 unset($id);
284 $ipcheck=$resultarray;
285 }
286
287
288 // Check if it's been configured a port already
289 $query = "SELECT id,iif_id FROM Port where object_id=$newmachine and name=\"$nics[$i]\"";
290 unset($result);
291 $result = usePreparedSelectBlade ($query);
292 $resultarray = $result->fetchAll (PDO::FETCH_ASSOC);
293
294 if($resultarray) {
295 $portid = $resultarray[0]['id'];
296 unset($id);
297 $portcheck=$resultarray;
298 }
299
300 // Add/update port
301 // 2011-08-31 <neil.scholten@gamigo.com>
302 // * Don't touch already existing complex ports
303 if ( $resultarray[0]['type'] != 9 ) {
304 if ( count($portcheck) == 1 ) {
305 commitUpdatePort($newmachine,$portid, $nics[$i], $nictypeid, "Ethernet port", "$mac", NULL);
306 }
307 else
308 {
309 commitAddPort($object_id = $newmachine, $nics[$i], $nictypeid,'Ethernet port',"$mac");
310 }
311 } else {
312 //We've got a complex port, don't touch it, it raises an error with 'Database error: foreign key violation'
313 }
314
315 // Add/update ip
316 if (count($ipcheck) == 1 ) {
317 if( $ip ) {
318 updateAddress($ip , $newmachine, $nics[$i],'regular');
319 }
1806a4df 320 }
5d5dbda0
DO
321 else
322 {
323 if( $ip ) {
324 bindIpToObject($ip , $newmachine, $nics[$i],'regular');
325 }
326 }
327
328 unset($portcheck);
329 unset($ipcheck);
330 unset($ip);
331 unset($mac);
1806a4df 332 }
1806a4df
DO
333 }
334 return buildWideRedirectURL ();
38ba29a5
AD
335}
336
337// Display the import page.
338function ViewHTML()
339{
1806a4df
DO
340 startPortlet();
341
342 echo "<table with=90% align=center border=0 cellpadding=5 cellspacing=0 align=center class=cooltable><tr valign=top>";
343 echo "<form method=post enctype=\"multipart/form-data\" action='index.php?module=redirect&page=depot&tab=facter&op=Update'>";
344 echo "<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"30000\" />";
345 echo "Upload a facter file: <input name=\"userfile\" type=\"file\" /><br />";
346 echo "<input type=\"submit\" value=\"Upload File\" />";
347
348 echo "</td></tr></table></td></tr>";
349 echo "</form>";
350 echo "</table>";
351 finishPortlet();
38ba29a5
AD
352}
353
354function getdict ($hw,$chapter) {
1806a4df
DO
355 try {
356 global $dbxlink;
357 $query = "select dict_key from Dictionary where chapter_id='$chapter' AND dict_value ='$hw' LIMIT 1";
358 $result = usePreparedSelectBlade ($query);
359 $array = $result->fetchAll (PDO::FETCH_ASSOC);
360
361 if($array) {
362 return $array[0]['dict_key'];
363 }
364 else {
365 // Chapter ID for hardware is 11.
366 $dbxlink->exec("INSERT INTO Dictionary (chapter_id,dict_value) VALUES ('$chapter','$hw')");
367
368 $squery = "select dict_key from Dictionary where dict_value ='$hw' AND chapter_ID ='$chapter' LIMIT 1";
369 $sresult = usePreparedSelectBlade ($squery);
370 $sarray = $sresult->fetchAll (PDO::FETCH_ASSOC);
371
372 if($sarray) {
373 return $sarray[0]['dict_key'];
374 }
375
376 else {
377 // If it still has not returned, we are up shit creek.
378 return 0;
379 }
380 }
381 $dbxlink = null;
382 }
383 catch(PDOException $e)
384 {
385 echo $e->getMessage();
386 }
38ba29a5
AD
387}
388?>