VOL-1397: Adtran-OLT - Initial containerization commit
- Need to move VERSION to base directory
Change-Id: I9d62d0607a011ce642e379fd92b35ec48b300070
diff --git a/adapters/adtran_common/net/rcmd.py b/adapters/adtran_common/net/rcmd.py
new file mode 100644
index 0000000..3062b4c
--- /dev/null
+++ b/adapters/adtran_common/net/rcmd.py
@@ -0,0 +1,112 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import structlog
+from twisted.internet.defer import Deferred, succeed
+from twisted.internet.protocol import Factory, Protocol
+from twisted.conch.client.knownhosts import ConsoleUI, KnownHostsFile
+from twisted.conch.endpoints import SSHCommandClientEndpoint
+from twisted.internet import reactor
+
+log = structlog.get_logger()
+_open = open
+
+
+class RCmd(object):
+ """
+ Execute a one-time remote command via SSH
+ """
+ def __init__(self, host, username, password,
+ command,
+ port=None,
+ keys=None,
+ known_hosts=None,
+ agent=None):
+ self.reactor = reactor
+ self.host = host
+ self.port = port
+ self.username = username
+ self.password = password
+ self.keys = keys
+ # self.knownHosts = known_hosts
+ self.knownHosts = known_hosts
+ self.agent = agent
+ self.command = command
+ self.ui = RCmd.FixedResponseUI(True)
+
+ class NoiseProtocol(Protocol):
+ def __init__(self):
+ self.finished = Deferred()
+ self.strings = ["bif", "pow", "zot"]
+
+ def connectionMade(self):
+ log.debug('connection-made')
+ self._send_noise()
+
+ def _send_noise(self):
+ if self.strings:
+ self.transport.write(self.strings.pop(0) + "\n")
+ else:
+ self.transport.loseConnection()
+
+ def dataReceived(self, data):
+ log.debug('rx', data=data)
+ if self.finished is not None and not self.finished.called:
+ self.finished.callback(data)
+ self._send_noise()
+
+ def connectionLost(self, reason):
+ log.debug('connection-lost')
+ if not self.finished.called:
+ self.finished.callback(reason)
+
+ class PermissiveKnownHosts(KnownHostsFile):
+ def verifyHostKey(self, ui, hostname, ip, key):
+ log.debug('verifyHostKey')
+ return True
+
+ class FixedResponseUI(ConsoleUI):
+ def __init__(self, result):
+ super(RCmd.FixedResponseUI, self).__init__(lambda: _open("/dev/null",
+ "r+b",
+ buffering=0))
+ self.result = result
+
+ def prompt(self, _):
+ log.debug('prompt')
+ return succeed(True)
+
+ def warn(self, text):
+ log.debug('warn')
+ pass
+
+ def _endpoint_for_command(self, command):
+ return SSHCommandClientEndpoint.newConnection(
+ self.reactor, command, self.username, self.host,
+ port=self.port,
+ password=self.password,
+ keys=self.keys,
+ agentEndpoint=self.agent,
+ knownHosts=self.knownHosts,
+ ui=self.ui
+ )
+
+ def execute(self):
+ endpoint = self._endpoint_for_command(self.command)
+ factory = Factory()
+ factory.protocol = RCmd.NoiseProtocol
+
+ d = endpoint.connect(factory)
+ d.addCallback(lambda proto: proto.finished)
+ return d