diff --git a/ui/details.ui b/ui/details.ui
index 8b3f939e..5fd3f3e4 100644
--- a/ui/details.ui
+++ b/ui/details.ui
@@ -2122,6 +2122,21 @@
1
+
+
+
+ 0
+ 2
+ 2
+
+
diff --git a/virtManager/details.py b/virtManager/details.py
index 10398b56..4e4e8439 100644
--- a/virtManager/details.py
+++ b/virtManager/details.py
@@ -537,6 +537,7 @@ class vmmDetails(vmmGObjectUI):
"on_cpu_maxvcpus_changed": self.config_maxvcpus_changed,
"on_cpu_model_changed": lambda *x: self.config_cpu_model_changed(x),
"on_cpu_copy_host_clicked": self.on_cpu_copy_host_clicked,
+ "on_cpu_secure_toggled": self.on_cpu_secure_toggled,
"on_cpu_cores_changed": self.config_cpu_topology_changed,
"on_cpu_sockets_changed": self.config_cpu_topology_changed,
"on_cpu_threads_changed": self.config_cpu_topology_changed,
@@ -1732,6 +1733,11 @@ class vmmDetails(vmmGObjectUI):
def on_cpu_copy_host_clicked(self, src):
uiutil.set_grid_row_visible(
self.widget("cpu-model"), not src.get_active())
+ uiutil.set_grid_row_visible(
+ self.widget("cpu-secure"), not src.get_active())
+ self.enable_apply(EDIT_CPU)
+
+ def on_cpu_secure_toggled(self, ignore):
self.enable_apply(EDIT_CPU)
def config_cpu_model_changed(self, ignore):
@@ -2032,6 +2038,7 @@ class vmmDetails(vmmGObjectUI):
if self.edited(EDIT_CPU):
kwargs["model"] = self.get_config_cpu_model()
+ kwargs["secure"] = self.widget("cpu-secure").get_active()
if self.edited(EDIT_TOPOLOGY):
do_top = self.widget("cpu-topology-enable").get_active()
@@ -2605,6 +2612,11 @@ class vmmDetails(vmmGObjectUI):
n1, n2 = self.vm.network_traffic_vectors()
self.network_traffic_graph.set_property("data_array", n1 + n2)
+ def _cpu_secure_is_available(self):
+ domcaps = self.vm.get_domain_capabilities()
+ features = domcaps.get_cpu_security_features()
+ return self.vm.get_xmlobj().os.is_x86() and len(features) > 0
+
def refresh_config_cpu(self):
# Set topology first, because it impacts maxvcpus values
cpu = self.vm.get_cpu_config()
@@ -2658,6 +2670,15 @@ class vmmDetails(vmmGObjectUI):
self.widget("cpu-copy-host").set_active(bool(is_host))
self.on_cpu_copy_host_clicked(self.widget("cpu-copy-host"))
+ if not self._cpu_secure_is_available():
+ self.widget("cpu-secure").set_sensitive(False)
+ self.widget("cpu-secure").set_tooltip_text(
+ "No security features to copy, the host is missing "
+ "security patches or the host CPU is not vulnerable.")
+
+ cpu.check_security_features(self.vm.get_xmlobj())
+ self.widget("cpu-secure").set_active(cpu.secure)
+
def refresh_config_memory(self):
host_mem_widget = self.widget("state-host-memory")
host_mem = self.vm.conn.host_memory_size() // 1024
diff --git a/virtManager/domain.py b/virtManager/domain.py
index 2134bfbc..f4f03c7a 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -442,7 +442,7 @@ class vmmDomain(vmmLibvirtObject):
self._redefine_xmlobj(xmlobj)
def define_cpu(self, vcpus=_SENTINEL, maxvcpus=_SENTINEL,
- model=_SENTINEL, sockets=_SENTINEL,
+ model=_SENTINEL, secure=_SENTINEL, sockets=_SENTINEL,
cores=_SENTINEL, threads=_SENTINEL):
guest = self._make_xmlobj_to_define()
@@ -456,7 +456,8 @@ class vmmDomain(vmmLibvirtObject):
guest.cpu.cores = cores
guest.cpu.threads = threads
- if model != _SENTINEL:
+ if secure != _SENTINEL or model != _SENTINEL:
+ guest.cpu.secure = secure
if model in guest.cpu.SPECIAL_MODES:
guest.cpu.set_special_mode(guest, model)
else:
diff --git a/virtinst/domain/cpu.py b/virtinst/domain/cpu.py
index bf553449..45fdbd3a 100644
--- a/virtinst/domain/cpu.py
+++ b/virtinst/domain/cpu.py
@@ -122,6 +122,36 @@ class DomainCpu(XMLBuilder):
if not exists:
self.add_feature(feature)
+ def check_security_features(self, guest):
+ """
+ Since 'secure' property is not exported into the domain XML
+ we might need to refresh its state.
+ """
+ domcaps = guest.lookup_domcaps()
+ features = domcaps.get_cpu_security_features()
+
+ if len(features) == 0:
+ self.secure = False
+ return
+
+ for feature in features:
+ exists = False
+ for f in self.features:
+ if f.name == feature and f.policy == "require":
+ exists = True
+ break
+ if not exists:
+ self.secure = False
+ return
+
+ def _remove_security_features(self, guest):
+ domcaps = guest.lookup_domcaps()
+ for feature in domcaps.get_cpu_security_features():
+ for f in self.features:
+ if f.name == feature and f.policy == "require":
+ self.remove_child(f)
+ break
+
def set_model(self, guest, val):
logging.debug("setting cpu model %s", val)
if val: