mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
manager: Bring back multiple graph as an option.
Essentially a revert of the changes in 09189003ddf9
This commit is contained in:
parent
7aad3e86da
commit
fa8dccf0aa
@ -1,15 +1,41 @@
|
|||||||
<gconfschemafile>
|
<gconfschemafile>
|
||||||
<schemalist>
|
<schemalist>
|
||||||
<schema>
|
<schema>
|
||||||
<key>/schemas/apps/::PACKAGE::/vmlist-fields/stats-type</key>
|
<key>/schemas/apps/::PACKAGE::/vmlist-fields/disk_usage</key>
|
||||||
<applyto>/apps/::PACKAGE::/vmlist-fields/stats-type</applyto>
|
<applyto>/apps/::PACKAGE::/vmlist-fields/disk_usage</applyto>
|
||||||
<owner>::PACKAGE::</owner>
|
<owner>::PACKAGE::</owner>
|
||||||
<type>int</type>
|
<type>bool</type>
|
||||||
<default>0</default>
|
<default>0</default>
|
||||||
|
|
||||||
<locale name="C">
|
<locale name="C">
|
||||||
<short>Stats type in manager view</short>
|
<short>Show disk I/O in summary</short>
|
||||||
<long>Type of stats to graph (cpu, disk, net) in manager view</long>
|
<long>Show the disk I/O field in the domain list summary view</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/apps/::PACKAGE::/vmlist-fields/network_traffic</key>
|
||||||
|
<applyto>/apps/::PACKAGE::/vmlist-fields/network_traffic</applyto>
|
||||||
|
<owner>::PACKAGE::</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>0</default>
|
||||||
|
|
||||||
|
<locale name="C">
|
||||||
|
<short>Show network I/O in summary</short>
|
||||||
|
<long>Show the network I/O field in the domain list summary view</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/apps/::PACKAGE::/vmlist-fields/cpu_usage</key>
|
||||||
|
<applyto>/apps/::PACKAGE::/vmlist-fields/cpu_usage</applyto>
|
||||||
|
<owner>::PACKAGE::</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>1</default>
|
||||||
|
|
||||||
|
<locale name="C">
|
||||||
|
<short>Show cpu usage in summary</short>
|
||||||
|
<long>Show the cpu usage field in the domain list summary view</long>
|
||||||
</locale>
|
</locale>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
|
@ -256,12 +256,23 @@ class vmmConfig:
|
|||||||
# Suggest gconf syncs, so that the unset dirs are fully removed
|
# Suggest gconf syncs, so that the unset dirs are fully removed
|
||||||
self.conf.suggest_sync()
|
self.conf.suggest_sync()
|
||||||
|
|
||||||
def get_vmlist_stats_type(self):
|
def is_vmlist_cpu_usage_visible(self):
|
||||||
return self.conf.get_int(self.conf_dir + "/vmlist-fields/stats_type")
|
return self.conf.get_bool(self.conf_dir + "/vmlist-fields/cpu_usage")
|
||||||
|
|
||||||
def set_vmlist_stats_type(self, val):
|
def is_vmlist_disk_io_visible(self):
|
||||||
self.conf.set_int(self.conf_dir + "/vmlist-fields/stats_type", val)
|
return self.conf.get_bool(self.conf_dir + "/vmlist-fields/disk_usage")
|
||||||
|
|
||||||
|
def is_vmlist_network_traffic_visible(self):
|
||||||
|
return self.conf.get_bool(self.conf_dir + "/vmlist-fields/network_traffic")
|
||||||
|
|
||||||
|
def set_vmlist_cpu_usage_visible(self, state):
|
||||||
|
self.conf.set_bool(self.conf_dir + "/vmlist-fields/cpu_usage", state)
|
||||||
|
|
||||||
|
def set_vmlist_disk_io_visible(self, state):
|
||||||
|
self.conf.set_bool(self.conf_dir + "/vmlist-fields/disk_usage", state)
|
||||||
|
|
||||||
|
def set_vmlist_network_traffic_visible(self, state):
|
||||||
|
self.conf.set_bool(self.conf_dir + "/vmlist-fields/network_traffic", state)
|
||||||
|
|
||||||
def get_default_directory(self, conn, _type):
|
def get_default_directory(self, conn, _type):
|
||||||
if not _type:
|
if not _type:
|
||||||
@ -301,9 +312,14 @@ class vmmConfig:
|
|||||||
def set_view_system_tray(self, val):
|
def set_view_system_tray(self, val):
|
||||||
self.conf.set_bool(self.conf_dir + "/system-tray", val)
|
self.conf.set_bool(self.conf_dir + "/system-tray", val)
|
||||||
|
|
||||||
def on_vmlist_stats_type_changed(self, callback):
|
def on_vmlist_cpu_usage_visible_changed(self, callback):
|
||||||
self.conf.notify_add(self.conf_dir + "/vmlist-fields/stats_type",
|
self.conf.notify_add(self.conf_dir + "/vmlist-fields/cpu_usage", callback)
|
||||||
callback)
|
|
||||||
|
def on_vmlist_disk_io_visible_changed(self, callback):
|
||||||
|
self.conf.notify_add(self.conf_dir + "/vmlist-fields/disk_usage", callback)
|
||||||
|
|
||||||
|
def on_vmlist_network_traffic_visible_changed(self, callback):
|
||||||
|
self.conf.notify_add(self.conf_dir + "/vmlist-fields/network_traffic", callback)
|
||||||
|
|
||||||
def get_stats_update_interval(self):
|
def get_stats_update_interval(self):
|
||||||
interval = self.conf.get_int(self.conf_dir + "/stats/update-interval")
|
interval = self.conf.get_int(self.conf_dir + "/stats/update-interval")
|
||||||
|
@ -32,8 +32,6 @@ from virtManager.delete import vmmDeleteDialog
|
|||||||
from virtManager.graphwidgets import CellRendererSparkline
|
from virtManager.graphwidgets import CellRendererSparkline
|
||||||
from virtManager import util as util
|
from virtManager import util as util
|
||||||
|
|
||||||
VMLIST_SORT_NAME = 1
|
|
||||||
VMLIST_SORT_STATS = 2
|
|
||||||
|
|
||||||
# fields in the tree model data set
|
# fields in the tree model data set
|
||||||
ROW_HANDLE = 0
|
ROW_HANDLE = 0
|
||||||
@ -51,8 +49,9 @@ ROW_COLOR = 11
|
|||||||
|
|
||||||
# Columns in the tree view
|
# Columns in the tree view
|
||||||
COL_NAME = 0
|
COL_NAME = 0
|
||||||
COL_STATUS = 1
|
COL_CPU = 1
|
||||||
COL_STATS = 2
|
COL_DISK = 2
|
||||||
|
COL_NETWORK = 3
|
||||||
|
|
||||||
rcstring = """
|
rcstring = """
|
||||||
style "toolbar-style" {
|
style "toolbar-style" {
|
||||||
@ -158,12 +157,11 @@ class vmmManager(gobject.GObject):
|
|||||||
self.startup_error = None
|
self.startup_error = None
|
||||||
self.ignore_pause = False
|
self.ignore_pause = False
|
||||||
|
|
||||||
self.stats_column = None
|
|
||||||
self.stats_sparkline = None
|
|
||||||
|
|
||||||
self.prepare_vmlist()
|
self.prepare_vmlist()
|
||||||
|
|
||||||
self.config.on_vmlist_stats_type_changed(self.stats_toggled_config)
|
self.config.on_vmlist_cpu_usage_visible_changed(self.toggle_cpu_usage_visible_widget)
|
||||||
|
self.config.on_vmlist_disk_io_visible_changed(self.toggle_disk_io_visible_widget)
|
||||||
|
self.config.on_vmlist_network_traffic_visible_changed(self.toggle_network_traffic_visible_widget)
|
||||||
|
|
||||||
# Register callbacks with the global stats enable/disable values
|
# Register callbacks with the global stats enable/disable values
|
||||||
# that disable the associated vmlist widgets if reporting is disabled
|
# that disable the associated vmlist widgets if reporting is disabled
|
||||||
@ -172,6 +170,11 @@ class vmmManager(gobject.GObject):
|
|||||||
self.config.on_stats_enable_net_poll_changed(self.enable_polling,
|
self.config.on_stats_enable_net_poll_changed(self.enable_polling,
|
||||||
cfg.STATS_NETWORK)
|
cfg.STATS_NETWORK)
|
||||||
|
|
||||||
|
self.window.get_widget("menu_view_stats_cpu").set_active(self.config.is_vmlist_cpu_usage_visible())
|
||||||
|
self.window.get_widget("menu_view_stats_disk").set_active(self.config.is_vmlist_disk_io_visible())
|
||||||
|
self.window.get_widget("menu_view_stats_network").set_active(self.config.is_vmlist_network_traffic_visible())
|
||||||
|
|
||||||
|
|
||||||
self.vmmenu_icons = {}
|
self.vmmenu_icons = {}
|
||||||
self.vmmenu_icons["run"] = gtk.Image()
|
self.vmmenu_icons["run"] = gtk.Image()
|
||||||
self.vmmenu_icons["run"].set_from_stock(gtk.STOCK_MEDIA_PLAY,
|
self.vmmenu_icons["run"].set_from_stock(gtk.STOCK_MEDIA_PLAY,
|
||||||
@ -333,12 +336,12 @@ class vmmManager(gobject.GObject):
|
|||||||
self.connmenu.show()
|
self.connmenu.show()
|
||||||
|
|
||||||
self.window.signal_autoconnect({
|
self.window.signal_autoconnect({
|
||||||
"on_menu_view_stats_disk_toggled" : (self.stats_toggled,
|
"on_menu_view_cpu_usage_activate": (self.toggle_stats_visible,
|
||||||
cfg.STATS_DISK),
|
cfg.STATS_CPU),
|
||||||
"on_menu_view_stats_network_toggled" : (self.stats_toggled,
|
"on_menu_view_disk_io_activate" : (self.toggle_stats_visible,
|
||||||
cfg.STATS_NETWORK),
|
cfg.STATS_DISK),
|
||||||
"on_menu_view_stats_cpu_toggled" : (self.stats_toggled,
|
"on_menu_view_network_traffic_activate": (self.toggle_stats_visible,
|
||||||
cfg.STATS_CPU),
|
cfg.STATS_NETWORK),
|
||||||
|
|
||||||
"on_vm_manager_delete_event": self.close,
|
"on_vm_manager_delete_event": self.close,
|
||||||
"on_menu_file_add_connection_activate": self.new_connection,
|
"on_menu_file_add_connection_activate": self.new_connection,
|
||||||
@ -876,11 +879,18 @@ class vmmManager(gobject.GObject):
|
|||||||
nameCol.set_expand(True)
|
nameCol.set_expand(True)
|
||||||
nameCol.set_spacing(6)
|
nameCol.set_spacing(6)
|
||||||
cpuUsageCol = gtk.TreeViewColumn(_("CPU usage"))
|
cpuUsageCol = gtk.TreeViewColumn(_("CPU usage"))
|
||||||
cpuUsageCol.set_min_width(150)
|
diskIOCol = gtk.TreeViewColumn(_("Disk I/O"))
|
||||||
|
networkTrafficCol = gtk.TreeViewColumn(_("Network I/O"))
|
||||||
|
|
||||||
|
cpuUsageCol.set_min_width(140)
|
||||||
|
diskIOCol.set_min_width(140)
|
||||||
|
networkTrafficCol.set_min_width(140)
|
||||||
|
|
||||||
statusCol = nameCol
|
statusCol = nameCol
|
||||||
vmlist.append_column(nameCol)
|
vmlist.append_column(nameCol)
|
||||||
vmlist.append_column(cpuUsageCol)
|
vmlist.append_column(cpuUsageCol)
|
||||||
|
vmlist.append_column(diskIOCol)
|
||||||
|
vmlist.append_column(networkTrafficCol)
|
||||||
|
|
||||||
# For the columns which follow, we deliberately bind columns
|
# For the columns which follow, we deliberately bind columns
|
||||||
# to fields in the list store & on each update copy the info
|
# to fields in the list store & on each update copy the info
|
||||||
@ -900,7 +910,7 @@ class vmmManager(gobject.GObject):
|
|||||||
nameCol.pack_start(name_txt, True)
|
nameCol.pack_start(name_txt, True)
|
||||||
nameCol.add_attribute(name_txt, 'markup', ROW_MARKUP)
|
nameCol.add_attribute(name_txt, 'markup', ROW_MARKUP)
|
||||||
nameCol.add_attribute(name_txt, 'foreground-gdk', ROW_COLOR)
|
nameCol.add_attribute(name_txt, 'foreground-gdk', ROW_COLOR)
|
||||||
nameCol.set_sort_column_id(VMLIST_SORT_NAME)
|
nameCol.set_sort_column_id(COL_NAME)
|
||||||
|
|
||||||
cpuUsage_txt = gtk.CellRendererText()
|
cpuUsage_txt = gtk.CellRendererText()
|
||||||
cpuUsage_img = CellRendererSparkline()
|
cpuUsage_img = CellRendererSparkline()
|
||||||
@ -911,14 +921,37 @@ class vmmManager(gobject.GObject):
|
|||||||
cpuUsageCol.pack_start(cpuUsage_txt, False)
|
cpuUsageCol.pack_start(cpuUsage_txt, False)
|
||||||
cpuUsageCol.add_attribute(cpuUsage_img, 'visible', ROW_IS_VM)
|
cpuUsageCol.add_attribute(cpuUsage_img, 'visible', ROW_IS_VM)
|
||||||
cpuUsageCol.add_attribute(cpuUsage_txt, 'visible', ROW_IS_CONN)
|
cpuUsageCol.add_attribute(cpuUsage_txt, 'visible', ROW_IS_CONN)
|
||||||
cpuUsageCol.set_sort_column_id(VMLIST_SORT_STATS)
|
cpuUsageCol.set_cell_data_func(cpuUsage_img, self.cpu_usage_img, None)
|
||||||
self.stats_sparkline = cpuUsage_img
|
cpuUsageCol.set_visible(self.config.is_vmlist_cpu_usage_visible())
|
||||||
self.stats_column = cpuUsageCol
|
cpuUsageCol.set_sort_column_id(COL_CPU)
|
||||||
self.stats_toggled(None, self.get_stats_type())
|
|
||||||
|
|
||||||
model.set_sort_func(VMLIST_SORT_NAME, self.vmlist_name_sorter)
|
diskIO_img = CellRendererSparkline()
|
||||||
|
diskIO_img.set_property("xpad", 6)
|
||||||
|
diskIO_img.set_property("ypad", 12)
|
||||||
|
diskIO_img.set_property("reversed", True)
|
||||||
|
diskIOCol.pack_start(diskIO_img, True)
|
||||||
|
diskIOCol.add_attribute(diskIO_img, 'visible', ROW_IS_VM)
|
||||||
|
diskIOCol.set_cell_data_func(diskIO_img, self.disk_io_img, None)
|
||||||
|
diskIOCol.set_visible(self.config.is_vmlist_disk_io_visible())
|
||||||
|
diskIOCol.set_sort_column_id(COL_DISK)
|
||||||
|
|
||||||
model.set_sort_column_id(VMLIST_SORT_NAME, gtk.SORT_ASCENDING)
|
networkTraffic_img = CellRendererSparkline()
|
||||||
|
networkTraffic_img.set_property("xpad", 6)
|
||||||
|
networkTraffic_img.set_property("ypad", 12)
|
||||||
|
networkTraffic_img.set_property("reversed", True)
|
||||||
|
networkTrafficCol.pack_start(networkTraffic_img, True)
|
||||||
|
networkTrafficCol.add_attribute(networkTraffic_img, 'visible', ROW_IS_VM)
|
||||||
|
networkTrafficCol.set_cell_data_func(networkTraffic_img,
|
||||||
|
self.network_traffic_img, None)
|
||||||
|
networkTrafficCol.set_visible(self.config.is_vmlist_network_traffic_visible())
|
||||||
|
networkTrafficCol.set_sort_column_id(COL_NETWORK)
|
||||||
|
|
||||||
|
model.set_sort_func(COL_NAME, self.vmlist_name_sorter)
|
||||||
|
model.set_sort_func(COL_CPU, self.vmlist_cpu_usage_sorter)
|
||||||
|
model.set_sort_func(COL_DISK, self.vmlist_disk_io_sorter)
|
||||||
|
model.set_sort_func(COL_NETWORK, self.vmlist_network_usage_sorter)
|
||||||
|
|
||||||
|
model.set_sort_column_id(COL_NAME, gtk.SORT_ASCENDING)
|
||||||
|
|
||||||
def vmlist_name_sorter(self, model, iter1, iter2):
|
def vmlist_name_sorter(self, model, iter1, iter2):
|
||||||
return cmp(model.get_value(iter1, ROW_NAME),
|
return cmp(model.get_value(iter1, ROW_NAME),
|
||||||
@ -950,53 +983,31 @@ class vmmManager(gobject.GObject):
|
|||||||
widget.set_sensitive(False)
|
widget.set_sensitive(False)
|
||||||
tool_text = _("Disabled in preferences dialog.")
|
tool_text = _("Disabled in preferences dialog.")
|
||||||
|
|
||||||
if self.get_stats_type() == userdata:
|
|
||||||
# Switch graphs over to guaranteed safe value
|
|
||||||
self.stats_toggled(None, cfg.STATS_CPU)
|
|
||||||
|
|
||||||
util.tooltip_wrapper(widget, tool_text)
|
util.tooltip_wrapper(widget, tool_text)
|
||||||
|
|
||||||
def stats_toggled_config(self, ignore1, ignore2, conf_entry, ignore4):
|
def toggle_network_traffic_visible_widget(self, *ignore):
|
||||||
self.stats_toggled(None, conf_entry.get_value().get_int())
|
vmlist = self.window.get_widget("vm-list")
|
||||||
|
col = vmlist.get_column(COL_NETWORK)
|
||||||
|
col.set_visible(self.config.is_vmlist_network_traffic_visible())
|
||||||
|
|
||||||
def get_stats_type(self):
|
def toggle_disk_io_visible_widget(self, *ignore):
|
||||||
return self.config.get_vmlist_stats_type()
|
vmlist = self.window.get_widget("vm-list")
|
||||||
|
col = vmlist.get_column(COL_DISK)
|
||||||
|
col.set_visible(self.config.is_vmlist_disk_io_visible())
|
||||||
|
|
||||||
def stats_toggled(self, src, stats_id):
|
def toggle_cpu_usage_visible_widget(self, *ignore):
|
||||||
if src and not src.get_active():
|
vmlist = self.window.get_widget("vm-list")
|
||||||
return
|
col = vmlist.get_column(COL_CPU)
|
||||||
|
col.set_visible(self.config.is_vmlist_cpu_usage_visible())
|
||||||
|
|
||||||
if stats_id == cfg.STATS_NETWORK:
|
def toggle_stats_visible(self, src, stats_id):
|
||||||
column_name = _("Network I/O")
|
visible = src.get_active()
|
||||||
stats_func = self.network_traffic_img
|
set_stats = {
|
||||||
sort_func = self.vmlist_network_usage_sorter
|
cfg.STATS_CPU: self.config.set_vmlist_cpu_usage_visible,
|
||||||
widg = "menu_view_stats_network"
|
cfg.STATS_DISK: self.config.set_vmlist_disk_io_visible,
|
||||||
elif stats_id == cfg.STATS_DISK:
|
cfg.STATS_NETWORK: self.config.set_vmlist_network_traffic_visible,
|
||||||
column_name = _("Disk I/O")
|
}
|
||||||
stats_func = self.disk_io_img
|
set_stats[stats_id](visible)
|
||||||
sort_func = self.vmlist_disk_io_sorter
|
|
||||||
widg = "menu_view_stats_disk"
|
|
||||||
elif stats_id == cfg.STATS_CPU:
|
|
||||||
column_name = _("CPU Usage")
|
|
||||||
stats_func = self.cpu_usage_img
|
|
||||||
sort_func = self.vmlist_cpu_usage_sorter
|
|
||||||
widg = "menu_view_stats_cpu"
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
if not src:
|
|
||||||
self.window.get_widget(widg).set_active(True)
|
|
||||||
|
|
||||||
if self.stats_column:
|
|
||||||
vmlist = self.window.get_widget("vm-list")
|
|
||||||
model = vmlist.get_model()
|
|
||||||
self.stats_column.set_title(column_name)
|
|
||||||
self.stats_column.set_cell_data_func(self.stats_sparkline,
|
|
||||||
stats_func, None)
|
|
||||||
model.set_sort_func(VMLIST_SORT_STATS, sort_func)
|
|
||||||
|
|
||||||
if stats_id != self.get_stats_type():
|
|
||||||
self.config.set_vmlist_stats_type(stats_id)
|
|
||||||
|
|
||||||
def cpu_usage_img(self, column, cell, model, _iter, data):
|
def cpu_usage_img(self, column, cell, model, _iter, data):
|
||||||
if model.get_value(_iter, ROW_HANDLE) is None:
|
if model.get_value(_iter, ROW_HANDLE) is None:
|
||||||
|
@ -158,33 +158,31 @@
|
|||||||
<child>
|
<child>
|
||||||
<widget class="GtkMenu" id="menu1">
|
<widget class="GtkMenu" id="menu1">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkRadioMenuItem" id="menu_view_stats_cpu">
|
<widget class="GtkCheckMenuItem" id="menu_view_stats_cpu">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="label" translatable="yes">CPU</property>
|
<property name="label" translatable="yes">CPU Usage</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="draw_as_radio">True</property>
|
<property name="active">True</property>
|
||||||
<signal name="toggled" handler="on_menu_view_stats_cpu_toggled"/>
|
<signal name="activate" handler="on_menu_view_cpu_usage_activate"/>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkCheckMenuItem" id="menu_view_stats_disk">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes">Disk I/O</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="active">True</property>
|
||||||
|
<signal name="activate" handler="on_menu_view_disk_io_activate"/>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkRadioMenuItem" id="menu_view_stats_disk">
|
<widget class="GtkCheckMenuItem" id="menu_view_stats_network">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="label" translatable="yes">Disk</property>
|
<property name="label" translatable="yes">Network I/O</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="draw_as_radio">True</property>
|
<property name="active">True</property>
|
||||||
<property name="group">menu_view_stats_cpu</property>
|
<signal name="activate" handler="on_menu_view_network_traffic_activate"/>
|
||||||
<signal name="toggled" handler="on_menu_view_stats_disk_toggled"/>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkRadioMenuItem" id="menu_view_stats_network">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="label" translatable="yes">Network</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="draw_as_radio">True</property>
|
|
||||||
<property name="group">menu_view_stats_cpu</property>
|
|
||||||
<signal name="toggled" handler="on_menu_view_stats_network_toggled"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
Loading…
Reference in New Issue
Block a user