1# Copyright (C) 2007, 2013-2014 Red Hat, Inc.
2# Copyright (C) 2007 Daniel P. Berrange <berrange@redhat.com>
3#
4# This work is licensed under the GNU GPLv2 or later.
5# See the COPYING file in the top-level directory.
6
7from virtinst import log
8
9from .lib import uiutil
10from .baseclass import vmmGObjectUI
11from .engine import vmmEngine
12from .lib.graphwidgets import Sparkline
13from .hostnets import vmmHostNets
14from .hoststorage import vmmHostStorage
15
16
17class vmmHost(vmmGObjectUI):
18    @classmethod
19    def show_instance(cls, parentobj, conn):
20        try:
21            # Maintain one dialog per connection
22            uri = conn.get_uri()
23            if cls._instances is None:
24                cls._instances = {}
25            if uri not in cls._instances:
26                cls._instances[uri] = vmmHost(conn)
27            cls._instances[uri].show()
28        except Exception as e:  # pragma: no cover
29            if not parentobj:
30                raise
31            parentobj.err.show_err(
32                    _("Error launching host dialog: %s") % str(e))
33
34    def __init__(self, conn):
35        vmmGObjectUI.__init__(self, "host.ui", "vmm-host")
36        self.conn = conn
37
38        # Set default window size
39        w, h = self.conn.get_details_window_size()
40        if w <= 0:
41            w = 800
42        if h <= 0:
43            h = 600
44        self.topwin.set_default_size(w, h)
45        self._window_size = None
46
47        self._cpu_usage_graph = None
48        self._memory_usage_graph = None
49        self._init_conn_state()
50
51        self._storagelist = None
52        self._init_storage_state()
53
54        self._hostnets = None
55        self._init_net_state()
56
57        self.builder.connect_signals({
58            "on_menu_file_view_manager_activate": self._view_manager_cb,
59            "on_menu_file_quit_activate": self._exit_app_cb,
60            "on_menu_file_close_activate": self.close,
61            "on_vmm_host_delete_event": self.close,
62            "on_vmm_host_configure_event": self._window_resized_cb,
63            "on_host_page_switch": self._page_changed_cb,
64
65            "on_overview_name_changed": self._overview_name_changed_cb,
66            "on_config_autoconnect_toggled": self._autoconnect_toggled_cb,
67        })
68
69        self.conn.connect("state-changed", self._conn_state_changed_cb)
70        self.conn.connect("resources-sampled", self._conn_resources_sampled_cb)
71
72        self._refresh_resources()
73        self._refresh_conn_state()
74        self.widget("config-autoconnect").set_active(
75            self.conn.get_autoconnect())
76
77        self._cleanup_on_conn_removed()
78
79
80    #######################
81    # Standard UI methods #
82    #######################
83
84    def show(self):
85        log.debug("Showing host details: %s", self.conn)
86        vis = self.is_visible()
87        self.topwin.present()
88        if vis:
89            return  # pragma: no cover
90
91        vmmEngine.get_instance().increment_window_counter()
92
93    def close(self, src=None, event=None):
94        dummy = src
95        dummy = event
96        log.debug("Closing host window for %s", self.conn)
97        if not self.is_visible():
98            return
99
100        self.topwin.hide()
101        vmmEngine.get_instance().decrement_window_counter()
102
103        return 1
104
105    def _cleanup(self):
106        if self._window_size:
107            self.conn.set_details_window_size(*self._window_size)
108
109        self.conn = None
110
111        self._storagelist.cleanup()
112        self._storagelist = None
113
114        self._hostnets.cleanup()
115        self._hostnets = None
116
117        self._cpu_usage_graph.destroy()
118        self._cpu_usage_graph = None
119
120        self._memory_usage_graph.destroy()
121        self._memory_usage_graph = None
122
123
124    ###########
125    # UI init #
126    ###########
127
128    def _init_net_state(self):
129        self._hostnets = vmmHostNets(self.conn, self.builder, self.topwin)
130        self.widget("net-align").add(self._hostnets.top_box)
131
132    def _init_storage_state(self):
133        self._storagelist = vmmHostStorage(self.conn, self.builder, self.topwin)
134        self.widget("storage-align").add(self._storagelist.top_box)
135
136    def _init_conn_state(self):
137        uri = self.conn.get_uri()
138        auto = self.conn.get_autoconnect()
139
140        self.widget("overview-uri").set_text(uri)
141        self.widget("config-autoconnect").set_active(auto)
142
143        self._cpu_usage_graph = Sparkline()
144        self._cpu_usage_graph.show()
145        self.widget("performance-cpu-align").add(self._cpu_usage_graph)
146
147        self._memory_usage_graph = Sparkline()
148        self._memory_usage_graph.show()
149        self.widget("performance-memory-align").add(self._memory_usage_graph)
150
151
152    ######################
153    # UI conn populating #
154    ######################
155
156    def _refresh_resources(self):
157        vm_memory = uiutil.pretty_mem(self.conn.stats_memory())
158        host_memory = uiutil.pretty_mem(self.conn.host_memory_size())
159
160        cpu_vector = self.conn.host_cpu_time_vector()
161        memory_vector = self.conn.stats_memory_vector()
162        cpu_vector.reverse()
163        memory_vector.reverse()
164
165        self.widget("performance-cpu").set_text("%d %%" %
166                                        self.conn.host_cpu_time_percentage())
167        self.widget("performance-memory").set_text(
168                            _("%(currentmem)s of %(maxmem)s") %
169                            {'currentmem': vm_memory, 'maxmem': host_memory})
170
171        self._cpu_usage_graph.set_property("data_array", cpu_vector)
172        self._memory_usage_graph.set_property("data_array", memory_vector)
173
174    def _refresh_conn_state(self):
175        conn_active = self.conn.is_active()
176
177        self.topwin.set_title(
178            _("%(connection)s - Connection Details") %
179            {"connection": self.conn.get_pretty_desc()})
180        if not self.widget("overview-name").has_focus():
181            self.widget("overview-name").set_text(self.conn.get_pretty_desc())
182
183        if conn_active:
184            return
185        self._hostnets.close()
186        self._storagelist.close()
187
188
189    ################
190    # UI listeners #
191    ################
192
193    def _view_manager_cb(self, src):
194        from .manager import vmmManager
195        vmmManager.get_instance(self).show()
196
197    def _exit_app_cb(self, src):
198        vmmEngine.get_instance().exit_app()
199
200    def _window_resized_cb(self, src, event):
201        if not self.is_visible():
202            return
203        self._window_size = self.topwin.get_size()
204
205    def _overview_name_changed_cb(self, src):
206        src = self.widget("overview-name")
207        self.conn.set_config_pretty_name(src.get_text())
208
209    def _autoconnect_toggled_cb(self, src):
210        self.conn.set_autoconnect(src.get_active())
211
212    def _page_changed_cb(self, src, child, pagenum):
213        if pagenum == 1:
214            self._hostnets.refresh_page()
215        elif pagenum == 2:
216            self._storagelist.refresh_page()
217
218    def _conn_state_changed_cb(self, conn):
219        self._refresh_conn_state()
220
221    def _conn_resources_sampled_cb(self, conn):
222        self._refresh_resources()
223