Index: branches/maintenance-0.19.x/gateways/deviceconfig/linux.connector
===================================================================
--- branches/maintenance-0.19.x/gateways/deviceconfig/linux.connector	(revision 0)
+++ branches/maintenance-0.19.x/gateways/deviceconfig/linux.connector	(revision 0)
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+#  racktables/gateways/deviceconfig/linux.connector
+#
+#  Pre-Requirements:
+#    1) SSH key-based authorization on remote hosts.
+#       See SSHUSER and KEYFILE below.
+#    2) Password-less sudo on remote side:
+#         /sbin/ip -o a
+#         /sbin/ethtool eth*
+#         /usr/sbin/arp -an
+#    3) Correct hostname resolution via DNS or /etc/hosts.
+#
+#  Written by evseev@fastvps.ru at Mar-2011
+#
+
+[ $# = 3 ] || exit 1
+
+ENDPOINT=$1
+COMMAND=$2
+WORKFILE=$3
+
+SSHUSER=racktbl
+KEYFILE=/etc/racktables/id_rsa
+
+test -r "$KEYFILE" || exit 3
+
+case $COMMAND in
+get8021q)
+	cmd='sudo /sbin/ip -o a'
+	outfile="$WORKFILE"
+	;;
+getportstatus)
+	cmd='cd /sys/class/net && for d in eth*; do sudo /sbin/ethtool $d; done'
+	outfile="$WORKFILE"
+	;;
+getmaclist)
+	cmd='sudo /usr/sbin/arp -an'
+	outfile="$WORKFILE"
+	;;
+deploy)
+	cmd=$(cat "$WORKFILE")
+	outfile=/dev/null
+	;;
+*)
+	exit 6
+	;;
+esac
+rc=0
+ssh -o 'BatchMode yes'  \
+    -o 'CheckHostIP no' \
+    -o 'StrictHostKeyChecking no' \
+    -yqni "$KEYFILE" \
+    $SSHUSER@$ENDPOINT "$cmd" > "$outfile" 2>&1 || rc=4
+#cp -p $outfile $outfile.out; echo "cmd=$cmd, rc=$rc" > $outfile.cmd
+exit $rc

Property changes on: branches/maintenance-0.19.x/gateways/deviceconfig/linux.connector
___________________________________________________________________
Added: svn:executable
   + *

Index: branches/maintenance-0.19.x/wwwroot/inc/gateways.php
===================================================================
--- branches/maintenance-0.19.x/wwwroot/inc/gateways.php	(revision 4983)
+++ branches/maintenance-0.19.x/wwwroot/inc/gateways.php	(working copy)
@@ -30,6 +30,7 @@
 );
 $gwrxlator['get8021q'] = array
 (
+	'linux' => 'linuxReadVLANConfig',
 	'dlink' => 'dlinkReadVLANConfig',
 	'ios12' => 'ios12ReadVLANConfig',
 	'fdry5' => 'fdry5ReadVLANConfig',
@@ -41,6 +42,7 @@
 );
 $gwrxlator['getportstatus'] = array
 (
+	'linux' => 'linuxReadInterfaceStatus',
 	'dlink' => 'dlinkReadInterfaceStatus',
 	'ios12' => 'ciscoReadInterfaceStatus',
 	'vrp53' => 'vrpReadInterfaceStatus',
@@ -49,6 +51,7 @@
 );
 $gwrxlator['getmaclist'] = array
 (
+	'linux' => 'linuxReadMacList',
 	'dlink' => 'dlinkReadMacList',
 	'ios12' => 'ios12ReadMacList',
 	'vrp53' => 'vrp53ReadMacList',
@@ -317,6 +320,21 @@
 	gwRecvFile (str_replace (' ', '+', $endpoints[0]), $handlername, $output);
 }
 
+function isLinuxSWID($swid)
+{
+	//error_log("isLinuxSWID: check $swid");
+	if (
+		($swid >=  225 and $swid <=  235) ||
+		($swid >=  242 and $swid <=  243) ||
+		($swid >=  418 and $swid <=  436) ||
+		($swid >= 1331 and $swid <= 1334) ||
+		($swid >= 1395 and $swid <= 1396) ||
+		($swid >= 1417 and $swid <= 1422)
+	)
+		return TRUE;
+	return FALSE;
+}
+
 function detectDeviceBreed ($object_id)
 {
 	$breed_by_swcode = array
@@ -341,6 +359,8 @@
 		// See Attribute table: ID = 4, Type = 'dict', Name = 'SW Type'
 		if ($record['id'] == 4 and array_key_exists ($record['key'], $breed_by_swcode))
 			return $breed_by_swcode[$record['key']];
+		if ($record['id'] == 4 and isLinuxSWID($record['key']))
+			return 'linux';
 		// See Attribute table: ID = 2, Type = 'dict', Name = 'HW Type'
 		if ($record['id'] == 2 and $record['key'] >= 589 and $record['key'] <= 637)
 			return 'dlink';
Index: branches/maintenance-0.19.x/wwwroot/inc/deviceconfig.php
===================================================================
--- branches/maintenance-0.19.x/wwwroot/inc/deviceconfig.php	(revision 4983)
+++ branches/maintenance-0.19.x/wwwroot/inc/deviceconfig.php	(working copy)
@@ -183,6 +183,46 @@
 	return $ret;
 }
 
+function linuxReadVLANConfig($input)
+{
+	$ret = array
+	(
+		'vlanlist' => array(VLAN_DFL_ID),  // linear array of VIDs
+		'portdata' => array(), // portname => (mode=>trunk/access, native=>vid, allowed=>(vids))
+	);
+	foreach (explode ("\n", $input) as $line)
+	{
+		// 13: vlan11@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP \    link/ether 00:1e:34:ae:75:21 brd ff:ff:ff:ff:ff:ff
+		$matches = array();
+		if (!preg_match ('/^[[:digit:]]+:\s+([^\s]+):\s.*\slink\/ether\s/', $line, $matches))
+			continue;
+		$iface = $matches[1];
+		if (preg_match ('/^(eth[[:digit:]]+)\.0*([[:digit:]]+):?$/', $iface, $matches))
+			linuxStoreVLANInfo ($ret, 'vlan'.$matches[2], $matches[1], $matches[2]);
+		elseif (preg_match('/^vlan0*([[:digit:]]+)\@(.*)$/', $iface, $matches))
+			linuxStoreVLANInfo ($ret, 'vlan'.$matches[1], $matches[2], $matches[1]);
+		elseif (!array_key_exists($iface, $ret['portdata']))
+			$ret['portdata'][$iface] = array ('mode'=>'access', 'native'=>0, 'allowed'=>array() );
+	}
+	return $ret;
+}
+
+function linuxStoreVLANInfo(&$ret, $iface, $baseport, $vid)
+{
+	$ret['vlanlist'][] = $vid;
+	if (!array_key_exists ($baseport, $ret['portdata']))
+	{
+		$ret['portdata'][$baseport] = array ('mode'=>'trunk', 'native'=>0, 'allowed'=>array($vid) );
+	}
+	else
+	{
+		$ret['portdata'][$baseport]['mode'] = 'trunk';
+		$ret['portdata'][$baseport]['allowed'][] = $vid;
+	}
+	if (!array_key_exists($iface, $ret['portdata']))
+		$ret['portdata'][$iface] = array ('mode'=>'access', 'native'=>$vid, 'allowed'=>array($vid) );
+}
+
 /*
 D-Link VLAN info sample:
 ========================
@@ -1530,6 +1570,87 @@
 }
 
 /*
+ Linux "ethtool" output sample
+ =============================
+
+Settings for eth0:
+        Supported ports: [ TP ]
+        Supported link modes:   10baseT/Half 10baseT/Full
+                                100baseT/Half 100baseT/Full
+                                1000baseT/Full
+        Supports auto-negotiation: Yes
+        Advertised link modes:  10baseT/Half 10baseT/Full
+                                100baseT/Half 100baseT/Full
+                                1000baseT/Full
+        Advertised pause frame use: No
+        Advertised auto-negotiation: Yes
+        Speed: 1000Mb/s
+        Duplex: Full
+        Port: Twisted Pair
+        PHYAD: 2
+        Transceiver: internal
+        Auto-negotiation: on
+        MDI-X: off
+        Supports Wake-on: pumbg
+        Wake-on: g
+        Current message level: 0x00000001 (1)
+        Link detected: yes
+
+Settings for eth1:
+        Supported ports: [ TP ]
+        Supported link modes:   10baseT/Half 10baseT/Full
+                                100baseT/Half 100baseT/Full
+                                1000baseT/Full
+        Supports auto-negotiation: Yes
+        Advertised link modes:  10baseT/Half 10baseT/Full
+                                100baseT/Half 100baseT/Full
+                                1000baseT/Full
+        Advertised pause frame use: No
+        Advertised auto-negotiation: Yes
+        Speed: Unknown!
+        Duplex: Unknown! (255)
+        Port: Twisted Pair
+        PHYAD: 1
+        Transceiver: internal
+        Auto-negotiation: on
+        MDI-X: Unknown
+        Supports Wake-on: pumbg
+        Wake-on: g
+        Current message level: 0x00000001 (1)
+        Link detected: no
+*/
+function linuxReadInterfaceStatus($text)
+{
+	$result = array();
+	$iface = '';
+	$status = 'down';
+	$speed = '0';
+	$duplex = '';
+	foreach (explode ("\n", $text) as $line)
+	{
+		$m = array();
+		if (preg_match ('/^[^\s].* (.*):$/', $line, $m))
+		{
+			if ($iface !== '')
+				$result[$iface] = array ('status'=>$status, 'speed'=>$speed, 'duplex'=>$duplex);
+			$iface = $m[1];
+			$status = 'down';
+			$speed = 0;
+			$duplex = '';
+		}
+		elseif (preg_match ('/^\s*Speed: (.*)$/', $line, $m))
+			$speed = $m[1];
+		elseif (preg_match ('/^\s*Duplex: (.*)$/', $line, $m))
+			$duplex = $m[1];
+		elseif (preg_match ('/^\s*Link detected: (.*)$/', $line, $m))
+			$status = ( ($m[1] === 'yes') ? 'up' : 'down' );
+	}
+	if ($iface !== '')
+		$result[$iface] = array ('status' => $status, 'speed' => $speed, 'duplex' => $duplex);
+	return $result;
+}
+
+/*
  D-Link "show ports" output sample
  =================================
 
@@ -1651,6 +1772,29 @@
 	return ($a['vid'] < $b['vid']) ? -1 : 1;
 }
 
+function linuxReadMacList($text)
+{
+	$result = array();
+	$passed;
+	foreach (explode ("\n", $text) as $line)
+	{
+		$m = array();
+		if (!preg_match ('/\(([^\s]+)\) at ([^\s]+) \[ether\] on (.*)$/', $line, $m))
+			continue;
+
+		// prevent multiple additions
+		if (array_key_exists ($m[2].$m[3], $passed))
+			continue;
+		$passed[$m[2].$m[3]] = 1;
+
+		$result[$m[3]][] = array ('mac' => $m[2], 'vid'=>1);
+		//error_log("linuxReadMacList: $m[1], $m[2], $m[3].");
+	}
+	foreach ($result as $portname => &$maclist)
+		usort ($maclist, 'maclist_sort');
+	return $result;
+}
+
 /*
 D-Link "show fdb" output sample
 ===============================
