~bernd-sch/onehundredscopes/sshsearch

« back to all changes in this revision

Viewing changes to sshsearch-lens

  • Committer: Bernd Schlapsi
  • Date: 2011-12-27 22:21:39 UTC
  • Revision ID: brot@gmx.info-20111227222139-oi27y5t6psec5qv7
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
#    Copyright (c) 2011 David Calle <davidc@framli.eu>
 
4
#    Copyright (c) 2011 Michael Hall <mhall119@gmail.com>
 
5
 
 
6
#    This program is free software: you can redistribute it and/or modify
 
7
#    it under the terms of the GNU General Public License as published by
 
8
#    the Free Software Foundation, either version 3 of the License, or
 
9
#    (at your option) any later version.
 
10
 
 
11
#    This program is distributed in the hope that it will be useful,
 
12
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
#    GNU General Public License for more details.
 
15
 
 
16
#    You should have received a copy of the GNU General Public License
 
17
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 
 
19
import os.path
 
20
import paramiko
 
21
import sys
 
22
 
 
23
from gi.repository import GLib, GObject, Gio
 
24
from gi.repository import Dee
 
25
# FIXME: Some weird bug in Dee or PyGI makes Dee fail unless we probe
 
26
#        it *before* we import the Unity module... ?!
 
27
_m = dir(Dee.SequenceModel)
 
28
from gi.repository import Unity
 
29
 
 
30
BUS_NAME = "net.launchpad.lens.sshsearch"
 
31
SSHCONFIG = os.path.join('~', '.ssh', 'config')
 
32
SSHCONFIG_EXPAND = os.path.expanduser(SSHCONFIG)
 
33
KNOWN_HOSTS = os.path.join('~', '.ssh', 'known_hosts')
 
34
KNOWN_HOSTS_EXPAND = os.path.expanduser(KNOWN_HOSTS)
 
35
TERMINAL_APP = 'gnome-terminal'
 
36
TERMINAL_APP_MIMETYPE = 'application-x-desktop'
 
37
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
 
38
 
 
39
class Daemon:
 
40
 
 
41
    def __init__ (self):
 
42
        # The path for the Lens *must* also match the one in our .lens file
 
43
        self._lens = Unity.Lens.new ("/net/launchpad/lens/sshsearch", "sshsearch")
 
44
        self._scope = Unity.Scope.new ("/net/launchpad/lens/sshsearch/main")
 
45
        self._scope.connect ("notify::active-search", self.on_search_changed)
 
46
        #self._scope.connect ("notify::active-global-search", self.on_search_changed)
 
47
        self._scope.connect ("filters-changed", self.on_search_changed);
 
48
        self._scope.connect ("notify::active", self.on_search_changed);
 
49
        self._scope.connect ("activate-uri", self.on_activate_uri);
 
50
        self._scope.export()
 
51
 
 
52
        self._lens.props.search_hint = "SSH Scope"
 
53
        self._lens.props.visible = True;
 
54
        self._lens.props.search_in_global = False;
 
55
        
 
56
        # Populate categories
 
57
        cats = []
 
58
        cats.append (Unity.Category.new (SSHCONFIG,
 
59
                                         Gio.ThemedIcon.new(os.path.join(SCRIPT_DIR, 'sshsearch-lens.png')),
 
60
                                         Unity.CategoryRenderer.VERTICAL_TILE))
 
61
        cats.append (Unity.Category.new (KNOWN_HOSTS,
 
62
                                         Gio.ThemedIcon.new(os.path.join(SCRIPT_DIR, 'sshsearch-lens.png')),
 
63
                                         Unity.CategoryRenderer.VERTICAL_TILE))
 
64
        self._lens.props.categories = cats
 
65
        
 
66
        # Populate filters
 
67
        filters = []
 
68
        self._lens.props.filters = filters
 
69
 
 
70
        self._lens.add_local_scope (self._scope);
 
71
        self._lens.export ()
 
72
        
 
73
        self._config_hosts = self.__read_config()
 
74
        self._known_hosts = self.__read_known_hosts()
 
75
        print self._config_hosts
 
76
        print self._known_hosts
 
77
        
 
78
    def __read_config(self):
 
79
        c = paramiko.SSHConfig()
 
80
        c.parse(open(SSHCONFIG_EXPAND))
 
81
        return [h['host'].lower() for h in c._config if h['host'] != '*']
 
82
        
 
83
    def __read_known_hosts(self):
 
84
        h = paramiko.HostKeys(KNOWN_HOSTS_EXPAND)
 
85
        return h.keys()
 
86
        
 
87
    def on_search_changed (self, entry, *args):
 
88
        search = self._scope.props.active_search or None
 
89
        if search:
 
90
            search_string = search.props.search_string.lower() or None
 
91
        else:
 
92
            search_string = None
 
93
        results = self._scope.props.results_model
 
94
        self.update_results_model (search_string, results)
 
95
 
 
96
    def update_results_model(self, search, model):
 
97
        if search is None or search == '':
 
98
            return
 
99
         
 
100
        model.clear()
 
101
        found = [host for host in self._config_hosts if host.find(search) >= 0]
 
102
        for host in found:
 
103
            model.append('ssh://config/%s' % host,
 
104
                         TERMINAL_APP,
 
105
                         0,
 
106
                         TERMINAL_APP_MIMETYPE,
 
107
                         host, host, '')
 
108
                         
 
109
        found = [host for host in self._known_hosts if host.find(search) >= 0]
 
110
        for host in found:
 
111
            model.append('ssh://known_hosts/%s' % host,
 
112
                         TERMINAL_APP,
 
113
                         1,
 
114
                         TERMINAL_APP_MIMETYPE,
 
115
                         host, host, '')
 
116
 
 
117
    def on_activate_uri (self, scope, uri):
 
118
        host = uri.split('/')[-1]
 
119
        GLib.spawn_command_line_async('%s -e "ssh %s"' % (TERMINAL_APP, host))
 
120
        return Unity.ActivationResponse(handled=Unity.HandledType.HIDE_DASH, goto_uri='')
 
121
 
 
122
 
 
123
if __name__ == "__main__":
 
124
    session_bus_connection = Gio.bus_get_sync (Gio.BusType.SESSION, None)
 
125
    session_bus = Gio.DBusProxy.new_sync (session_bus_connection, 0, None,
 
126
                                          'org.freedesktop.DBus',
 
127
                                          '/org/freedesktop/DBus',
 
128
                                          'org.freedesktop.DBus', None)
 
129
    result = session_bus.call_sync('RequestName',
 
130
                                   GLib.Variant ("(su)", (BUS_NAME, 0x4)),
 
131
                                   0, -1, None)
 
132
                                   
 
133
    # Unpack variant response with signature "(u)". 1 means we got it.
 
134
    result = result.unpack()[0]
 
135
    
 
136
    if result != 1 :
 
137
        print >> sys.stderr, "Failed to own name %s. Bailing out." % BUS_NAME
 
138
        raise SystemExit (1)
 
139
    
 
140
    daemon = Daemon()
 
141
    GObject.MainLoop().run()