I have transitioning from a primary Windows desktop environment to a Linux desktop, and found that I wanted to get my saved connections from superputty, which my co-workers are using to a Linux tool. I found a tool called PAC Manager which does what I needed.
The main thing I wanted was a tree hierarchy what the routers are split by location. SupperPutty uses an XML based config file and PAC Manager uses YAML files. The main problem was finding a way to discover and map out the tree structure, because SupperPutty list the hierarchy like a file listing with a separator of “/”.
I was able to use a Python to extract the XML elements, and create a list of directory tree objects and element objects. In PAC’s YaML you need to list each folder and element separately, you also need to show the parent child relationships in both the folder and they element. I have attached the current version of my Python code below. I may later develop this further into a library that abstracts and can import and export both formats fully, but the current code meets my current need.
#!/usr/bin/python
import uuid
import xml.etree.ElementTree as ET
def branchListImport(devices):
temp = []
branches = {}
for y in devices:
x = y['SessionId'].split('/')[:-1]
if "/".join(y['SessionId'].split('/')[:-1]) not in branches:
if x[0] not in branches:
branches.update({str(x[0]) : {'name' : str(x[0]), 'description' : str(x[0]), 'uuidNumber' : uuid.uuid4(), 'parent' : "__PAC__EXPORTED__"}})
if len(x) > 1:
for y in range(1,len(x)):
if "/".join(x[:(y+1)]) not in branches:
branches.update({"/".join(x[:(y+1)]) : {'name': "/".join(x[:(y+1)]), 'description' : str(x[y]), 'uuidNumber' : uuid.uuid4(), 'parent' : str(branches["/".join(x[:y])]['uuidNumber'])}})
for x in sorted(branches.items()):
temp.append(branchPoint(**x[1]))
for x in temp:
for y in temp:
if str(x.uuid) == str(y.parent):
x.addChild(y.uuid)
return temp
def deviceListImport(devices, branchList):
temp = []
for x in devices:
temp.append(device(description=x['SessionName'], parentName="/".join(x['SessionId'].split('/')[:-1]), ip=x['Host'], port=x['Port'], method=x['Proto'], username=x['Username'] ))
for x in temp:
for y in branchList:
if x.parentName == y.name:
x.parentUuid = str(y.uuid)
y.addChild(str(x.uuid))
break
return temp
class device(object):
def __init__(self, description="", parentName="Unknown", parentUuid=False, uuidNumber=False, ip="", port="", method="", username="", password=False):
self.description = description
self.parentName = parentName
self.parentUuid = parentUuid
if uuidNumber == False:
self.uuid = uuid.uuid4()
else:
if isinstance(uuidNumber, uuid.UUID):
self.uuid = uuidNumber
elif isinstance(uuidNumber, str):
self.uuid = uuid.UUID(uuidNumber)
self.ip = ip
self.port = port
if method.upper() == "SSH":
self.method = "SSH"
elif method.upper() == "TELNET":
self.method = "Telnet"
else:
self.method = method.upper()
self.username = username
self.password = password
def __hash__(self):
return hash(self.description, self.parentName, self.parentUuid, self.uuid, self.ip, self.port, self.method, self.username, self.password)
def __str__(self):
return str(self.uuid)
def __repr__(self):
return 'pac_template.device(description="{}", parentName={}, parentUuid="{}", uuidNumber="{}", ip="{}", port="{}", method="{}", username="{}", password="{}"'.format(self.description, self.parentName, self.parentUuid, self.uuid, self.ip, self.port, self.method, self.username, self.password)
@property
def ymlString(self):
if self.password == False:
password = "<<ASK_PASS>>"
else:
password = self.password
return elementTemplate.format(uuid=self.uuid, ip=self.ip, desc=self.description, parent=self.parentUuid, port=self.port, method=self.method, username=self.username, password=password)
class branchPoint(object):
def __init__(self, description="", name="", parent="__PAC__EXPORTED__", children=False,uuidNumber=False):
self.description = description
self.name = name
self.parent = parent
self.children = children
if uuidNumber == False:
self.uuid = uuid.uuid4()
else:
if isinstance(uuidNumber, uuid.UUID):
self.uuid = uuidNumber
elif isinstance(uuidNumber, str):
self.uuid = uuid.UUID(uuidNumber)
def __hash__(self):
return hash(self.uuid, self.name, self.description, self.parent, self.children)
def __str__(self):
return str(self.uuid)
def __repr__(self):
return 'pac_template.branchPoint(description="{}", name={}, parent="{}", children={}, uuidNumber="{}"'.format(self.description, self.name, self.parent, self.children, self.uuid)
def addChild(self, child):
if self.children == False:
self.children = []
self.children.append(str(child))
@property
def ymlString(self):
temp = "{}:\n _is_group: 1\n _protected: 0\n children:\n".format(str(self.uuid))
if self.children != False:
for x in self.children:
temp += " {}: 1\n".format(x)
temp += " cluster: []\n description: Connection group '{0}'\n name: {0}\n parent: {1}\n screenshots: ~\n variables: []".format(self.description, self.parent)
return temp
elementTemplate = """{uuid}:
KPX title regexp: '.*{desc}.*'
_is_group: 0
_protected: 0
auth fallback: 1
auth type: userpass
autoreconnect: ''
autossh: ''
children: {{}}
cluster: []
description: "Connection with '{desc}'"
embed: 0
expect: []
favourite: 0
infer from KPX where: 3
infer user pass from KPX: ''
ip: {ip}
local after: []
local before: []
local connected: []
mac: ''
macros: []
method: {method}
name: '{desc}'
options: ' -X'
parent: {parent}
pass: '{password}'
passphrase: ''
passphrase user: ''
port: {port}
prepend command: ''
proxy ip: ''
proxy pass: ''
proxy port: 8080
proxy user: ''
public key: /home/braaen
quote command: ''
remove control chars: ''
save session logs: ''
screenshots: ~
search pass on KPX: 0
send slow: 0
send string active: ''
send string every: 60
send string intro: 1
send string txt: ''
session log pattern: <UUID>_<NAME>_<DATE_Y><DATE_M><DATE_D>_<TIME_H><TIME_M><TIME_S>.txt
session logs amount: 10
session logs folder: ~/.config/pac/session_logs
startup launch: ''
startup script: ''
startup script name: sample1.pl
terminal options:
audible bell: ''
back color: '#000000000000'
bold color: '#cc62cc62cc62'
bold color like text: 1
command prompt: '[#%\$>]|\:\/\s*$'
cursor shape: block
disable ALT key bindings: ''
disable CTRL key bindings: ''
disable SHIFT key bindings: ''
open in tab: 1
password prompt: "([p|P]ass|[p|P]ass[w|W]or[d|t]|ontrase.a|Enter passphrase for key '.+'):\\s*$"
tab back color: '#000000000000'
terminal backspace: auto
terminal character encoding: UTF-8
terminal emulation: xterm
terminal font: Monospace 9
terminal scrollback lines: 5000
terminal select words: \.:_\/-A-Za-z0-9
terminal transparency: 0
terminal window hsize: 800
terminal window vsize: 600
text color: '#cc62cc62cc62'
timeout command: 40
timeout connect: 40
use personal settings: ''
use tab back color: ''
username prompt: '([l|L]ogin|[u|u]suario|[u|U]ser-?[n|N]ame|[u|U]ser):\s*$'
visible bell: ''
title: '{desc}'
use prepend command: ''
use proxy: 0
use sudo: ''
user: {username}
variables: []"""
def main():
temp = []
tree = ET.parse('Sessions.xml')
root = tree.getroot()
devices = []
for child in root:
if child.tag == 'SessionData':
devices.append(child.attrib)
branchList = branchListImport(devices)
deviceList = deviceListImport(devices, branchList)
temp.append("---\n__PAC__EXPORTED__:\n children:")
temp += [" {}: 1".format(str(x.uuid)) for x in branchList if '__PAC__EXPORTED__' == x.parent]
temp += [x.ymlString for x in branchList]
temp += [x.ymlString for x in deviceList]
print "\n".join(temp)
if __name__ == "__main__":
main()