]> git.stg.codes - ssmd.git/blobdiff - src/switch.cpp
Control dumping snmp scripts.
[ssmd.git] / src / switch.cpp
index 43c83da2ad8d14c45770b95504c6020198c82f7e..71917ed798df5e6e0a519bfe576de63ad9a5000e 100644 (file)
@@ -1,3 +1,5 @@
+#include <cstdio>
+#include <fstream>
 #include <boost/lexical_cast.hpp>
 
 #include "snmp_pp/snmp_pp.h"
@@ -10,8 +12,8 @@
 #include "snmptable.h"
 #include "oids.h"
 
-using GTS::Switch;
-using GTS::SNMPTable;
+using SSMD::Switch;
+using SSMD::SNMPTable;
 
 Switch::Switch(const Settings & settings,
                Snmp & snmp,
@@ -26,7 +28,8 @@ Switch::Switch(const Settings & settings,
       _writeCommunity(writeCommunity),
       _uplinkPort(uplinkPort),
       _nextUpACL(1),
-      _nextDownACL(1)
+      _nextDownACL(1),
+      _aclsCreated(false)
 {
 }
 
@@ -39,12 +42,38 @@ Switch::Switch(const Switch & rvalue)
       _uplinkPort(rvalue._uplinkPort),
       _nextUpACL(rvalue._nextUpACL),
       _nextDownACL(rvalue._nextDownACL),
-      _acls(rvalue._acls)
+      _acls(rvalue._acls),
+      _aclsCreated(rvalue._aclsCreated)
 {
 }
 
 Switch::~Switch()
 {
+    if (_aclsCreated) {
+        IpAddress addr(_ip.c_str());
+        if (!addr.valid()) {
+            logger << "Switch::~Switch() - ivalid switch ip: '" << _ip << "'" << std::endl;
+            return;
+        }
+
+        CTarget target(addr, _readCommunity.c_str(), _writeCommunity.c_str());
+        if (!target.valid()) {
+            logger << "Switch::~Switch() - failed to create target for the switch '" << _ip << "'" << std::endl;
+            return;
+        }
+
+        target.set_version(version2c);
+
+        if (!checkProfiles(target)) {
+            logger << "Switch::~Switch() - no upload and download profiles defined for the switch '" << _ip << "'" << std::endl;
+            return;
+        }
+
+        if (!dropACLs(target, std::cerr)) {
+            logger << "Switch::~Switch() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
+            return;
+        }
+    }
 }
 
 Switch & Switch::operator=(const Switch & rvalue)
@@ -56,6 +85,7 @@ Switch & Switch::operator=(const Switch & rvalue)
     _nextUpACL = rvalue._nextUpACL;
     _nextDownACL = rvalue._nextDownACL;
     _acls = rvalue._acls;
+    _aclsCreated = rvalue._aclsCreated;
 
     return *this;
 }
@@ -99,13 +129,33 @@ void Switch::sync()
         return;
     }
 
-    if (!dropACLs(target)) {
-        logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
-        return;
-    }
+    {
+        std::ostream * stream = NULL;
+        std::string fileName(_settings.scriptBase() + "/" + _ip + ".sh");
+        std::string newFileName(fileName + ".new");
 
-    if (!createACLs(target)) {
-        logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl;
+        if (_settings.dumpScripts()) {
+            stream = new std::ofstream(newFileName.c_str());
+            *stream << "#!/bin/sh\n";
+        } else {
+            stream = new std::stringstream;
+        }
+
+        if (!dropACLs(target, *stream)) {
+            logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
+            delete stream;
+            return;
+        }
+
+        if (!createACLs(target, *stream)) {
+            logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl;
+            delete stream;
+            return;
+        }
+
+        delete stream;
+        if (_settings.dumpScripts())
+            rename(newFileName.c_str(), fileName.c_str());
     }
 
     if (_settings.isDebug()) {
@@ -135,7 +185,7 @@ bool Switch::checkProfiles(const CTarget & target)
     return false;
 }
 
-bool Switch::dropACLs(const CTarget & target)
+bool Switch::dropACLs(const CTarget & target, std::ostream & stream)
 {
     std::string upOidValue(swACLEtherRuleAccessID);
     upOidValue += ".";
@@ -154,13 +204,13 @@ bool Switch::dropACLs(const CTarget & target)
         return false;
     }
     if (!aclsUpTable.empty()) {
-        if (!dropACLsByTable(target, _settings.upProfileId(), aclsUpTable)) {
+        if (!dropACLsByTable(target, _settings.upProfileId(), aclsUpTable, stream)) {
             logger << "Switch::dropACLs() - failed to drop acls from upload table for the switch '" << _ip << "'" << std::endl;
             return false;
         }
     }
     if (!aclsDownTable.empty()) {
-        if (!dropACLsByTable(target, _settings.downProfileId(), aclsDownTable)) {
+        if (!dropACLsByTable(target, _settings.downProfileId(), aclsDownTable, stream)) {
             logger << "Switch::dropACLs() - failed to drop acls from download table for the switch '" << _ip << "'" << std::endl;
             return false;
         }
@@ -168,43 +218,64 @@ bool Switch::dropACLs(const CTarget & target)
     return true;
 }
 
-bool Switch::dropACLsByTable(const CTarget & target, unsigned profileId, const SNMPTable & table)
+bool Switch::dropACLsByTable(const CTarget & target, unsigned profileId, const SNMPTable & table, std::ostream & stream)
 {
     std::string dropACLOidPrefix(swACLEtherRuleRowStatus);
     dropACLOidPrefix += ".";
     dropACLOidPrefix += boost::lexical_cast<std::string>(profileId);
     SNMPList aclsList(table.getList());
-    Pdu pdu;
-    SNMPList::const_iterator it;
-    for (it = aclsList.begin(); it != aclsList.end(); ++it) {
-        int id;
-        if (it->get_value(id) != SNMP_CLASS_SUCCESS) {
-            return false;
+    SNMPList::const_iterator it(aclsList.begin());
+    size_t chunks = aclsList.size() / _settings.maxACLPerPDU() + 1;
+    for (size_t i = 0; i < chunks && it != aclsList.end(); ++i) {
+        Pdu pdu;
+        if (_settings.dumpScripts())
+            stream << "snmpset -v2c -c" << _writeCommunity << " " << _ip;
+        for (size_t j = 0; j < _settings.maxACLPerPDU() && it != aclsList.end(); ++j, ++it) {
+            int id;
+            if (int c = it->get_value(id) != SNMP_CLASS_SUCCESS) {
+                logger << "Switch::dropACLsByTable() - failed to get ACL id for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
+                return false;
+            }
+            std::string dropACLOid(dropACLOidPrefix);
+            dropACLOid += ".";
+            dropACLOid += boost::lexical_cast<std::string>(id);
+            Vb vb(Oid(dropACLOid.c_str()));
+            vb.set_value(int(6));
+            pdu += vb;
+            if (_settings.dumpScripts())
+                stream << " " << dropACLOid << " i 6";
+        }
+        if (_settings.dumpScripts())
+            stream << "\n";
+        if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
+            if (c != SNMP_ERROR_TOO_BIG) {
+                logger << "Switch::dropACLsByTable() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
+                return false;
+            }
         }
-        std::string dropACLOid(dropACLOidPrefix);
-        dropACLOid += ".";
-        dropACLOid += boost::lexical_cast<std::string>(id);
-        Vb vb(Oid(dropACLOid.c_str()));
-        vb.set_value(int(6));
-        pdu += vb;
-    }
-    if (_snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
-        logger << "Switch::dropACLsByTable() - failed to invoke Snmp::set for the switch '" << _ip << "'" << std::endl;
-        return false;
     }
     return true;
 }
 
-bool Switch::createACLs(const CTarget & target)
+bool Switch::createACLs(const CTarget & target, std::ostream & stream)
 {
     std::vector<ACL>::const_iterator it;
+    size_t pos = 0;
     for (it = _acls.begin(); it != _acls.end(); ++it) {
         Pdu pdu;
         it->appendPdu(pdu);
-        if (_snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
-            logger << "Switch::createACLs() - failed to invoke Snmp::set for the switch '" << _ip << "'" << std::endl;
-            return false;
+        if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
+            if (c != SNMP_ERROR_TOO_BIG) {
+                logger << "Switch::createACLs() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'. Error occured at creation of " << (pos + 1) << " from " << _acls.size() << " ACL's" << std::endl;
+                logger << "Switch::createACLs() - ACL dump: " << *it << std::endl;
+                return false;
+            }
         }
+        pdu.clear();
+        _aclsCreated = true;
+        ++pos;
+        if (_settings.dumpScripts())
+            stream << "snmpset -v2c -c" << _writeCommunity << " " << _ip << " " << *it << "\n";
     }
     return true;
 }