Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

machines: detect if libvirt is running #8493

Merged
merged 2 commits into from
Mar 24, 2018

Conversation

atiratree
Copy link
Contributor

show error with link to libvirt service if it is not running

add infrastructure for adding errors to the ui

@@ -812,6 +850,7 @@ function startEventMonitor(dispatch, connectionName) {
.fail(ex => {
// this usually happens if libvirtd gets stopped or isn't running; retry connecting every 10s
console.log("virsh event failed:", ex);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

virsh process can fail or be killed here, but is this console.log still needed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with dropping it; I wanted to keep it in after landing the virsh event stuff, but I figure it's stable enough now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I will remove it then

@martinpitt
Copy link
Member

This seems to break all VM tests?

@atiratree
Copy link
Contributor Author

This seems to break all VM tests?

It is because of the layout change (there is no empty vms screen first)
This is fixed in #7820 13b1876

actionMessage: PropTypes.string.isRequired,
};

const NotificationArea = ({ errors, dismissable, onDismiss, id }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we reuse Alert from inlineNotification.jsx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be resolved after the final design decision

});
}

let notificationArea = errors.length > 0 ? (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this into the NotificationArea component, so it can properly handle even empty list?


if (!isLibvirtActive) {
errors.push({
message: "Libvirt is not active.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider I18N: use _("...")

const errors = [...ui.errors];
const isLibvirtActive = libvirtState.status === 'active';

if (!isLibvirtActive) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make the NotificationArea component responsible for producing this message, just pass state-info to props.

@@ -56,6 +58,18 @@ if (!String.prototype.startsWith) {
};
}

if (typeof String.prototype.includes === 'undefined') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this required? Can't we find a way to do it via babel? Or avoid it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use https://babeljs.io/docs/usage/polyfill/

These are required here 3546515#diff-de184ca652af74b4142eac404126b77fR767 and in #7820

  • String: startsWith, includes
  • Array: includes

};
}

if (typeof Array.prototype.startsWith === 'undefined') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

likewise

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one was added by mistake

CHECK_LIBVIRT_STATUS() {
logDebug(`${this.name}.CHECK_LIBVIRT_STATUS`);
return dispatch => {
return cockpit.spawn(['systemctl', '--property=ActiveState', 'show', 'libvirtd'])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is systemctl available on all supported systems?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be (on their supported versions)
http://cockpit-project.org/running.html

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

systemctl itself is, but less sure about --property. But systemctl is-active --quiet myunit has been supported for a long time, and is even easier to use as you just need to look at the exit code. Alternatively, use the D-Bus API (GetUnit() and then its ActiveState property).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the history of systemd man pages and it should be ok for our versions. I will leave it like it is for now. + we are using the string state in the ui so it is not a big difference

// set up event monitor for that connection; force PTY as otherwise the buffering
// will not show every line immediately
cockpit.spawn(['virsh'].concat(VMS_CONFIG.Virsh.connections[connectionName].params).concat(['-r', 'event', '--all', '--loop']), {'err': 'message', 'pty': true})
.stream(data => {
if (data.startsWith("error: Disconnected from") || data.startsWith("error: internal error: client socket is closed")) {
// libvirt failed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we log here? Just to be sure we do not swallow status info which might be useful when debugging

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added debug log to all the places where event monitor fail is expected

@atiratree atiratree force-pushed the libvirt-status-msgs branch 4 times, most recently from 0f5e0c3 to 07c25ff Compare January 30, 2018 13:52
@atiratree
Copy link
Contributor Author

New version of design

There is one notification area which consists of:

  • libvirt warning which is not dismissable and will disappear when fixed
  • dismissable errors
  • dismissable info messages

Reasons

There can be multiple errors and messages so I put them in one closable notification

  • the ui will not be cluttered by many messages
  • you don't have to click on the cross of each message to clear them all

Design

combined

@garrett @andreasn
can you give me feedback on this pls?

@garrett
Copy link
Member

garrett commented Jan 30, 2018

Warning: libvirt

"libvirt is not active": Cockpit has a pattern in place, based on PatternFly's empty state pattern to handle things like this:

docker not active

A customized version for libvirt would look something like this:

libvirt not active

This does look a little odd, as Sentence case is used on the header and Title Case is used on the button — but, from what I can tell, libvirt is one of those projects named completely lowercase.

However, in Cockpit, we generally try to use phrases of higher-level concepts instead of specific technology (where appropriate). In this case, the resulting empty state screen might look like the following:

virtualization subsystem is not active

I'm not a fan of jargony phrases like "subsystems", however. @andreasn (or anyone else): Have any better ideas on what to call this?

Dismissable errors & notices

Could you provide some concrete examples of errors and notices that would be used in the inline notifications, please? (Good design requires example content and intent.) Thanks!

@atiratree
Copy link
Contributor Author

I guess empty state makes more sense.

Just one note:

  • I am not sure this will be the right choice for the ovirt usecase though. Because you can choose to connet to ovirt instead.

Could you provide some concrete examples of errors and notices that would be used in the inline notifications, please? (Good design requires example content and intent.) Thanks!

For now error about vm creation failure. It can take some time and there can be multiple failures at the same time.

there is no usage for notices yet (I just put it into the example), but it could be useful in the future

@garrett
Copy link
Member

garrett commented Jan 30, 2018

It could use an empty state pattern with a secondary button (btn-standard) for connecting to oVirt. When you click on the button, it would ask for the details in a modal popup

virt-service / connect to oVirt

@mareklibra
Copy link
Contributor

IMO, we should name libvirt within the empty-state title and not rephrase it to virtualization susbsystem or so. The first one is more clear, the second one is like definition of new terminology.

It's both nice and consistent to have the Start button there causing sort of systemctl start libvirtd.
Anyway, it would be useful to provide a link to the /services view for the case the user needs to inspect logs or even enable the service (means start at boot time).

I am not sure this will be the right choice for the ovirt usecase though. Because you can choose to connet to ovirt instead.

No matter what the application allows now, the cockpit-machines-ovirt is being described as an extension on top of cockpit-machines functionality. Having that on mind, the empty state shall be rendered even here if the libvirt is down.

@atiratree
Copy link
Contributor Author

current state

libvirt status

before libvirt status is known:
loading

when libvirt is down:

libvirt-not-active

error messages

  • are left the same as before from design perspective
  • code was refactored to reuse functionality in inlineNotification

Copy link
Member

@garrett garrett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concept should be expressed in the language. However, I think it's a good compromise to merge our mockups to also mention libvirt in the docs link. (I like your idea to add the link there for further details.)

I've added inline comments in the code.

icon = (<div className="spinner spinner-lg"/>);
break;
default:
message = _("libvirt is not active on the system");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should say "Virtualization service is not active", which is more descriptive of what's happening. Not everyone will know what "libvirt" is. (It even sounds confusingly like a library.)

icon = (<span className="fa fa-exclamation-circle"/>);
detail = (
<p>
{_("See libvirt service for ")}<a onClick={mouseClick(goToLink)}>{_("more configuration.")}</a>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to say libvirt here and, in fact, would help to reinforce that libvirt is a virtualization service (and vice versa) based on context.

Perhaps the code should look something like the following:

            detail = (
                <p> {
                    cockpit.format(_("Please refer to $0 for more information."),
                        `<a href="${goToLink}" target="_blank">libvirt documentation</a>`)
                } </p>
            );

(It might not be quite right -- I didn't test it. It's based on the file pkg/ovirt/components/ConsoleClientResources.jsx which has a the link as an actual link (instead of a JavaScript-only action) and the method in which it is written enables the strings to be translatable more easily.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the reason to do it, but I do not think it is a good idea.
That example is much easier because it is just a link (outside of cockpit).

  • passing function like that breaks things:
    Refused to execute inline event handler because it violates the following Content Security Policy directive: "default-src 'self' http://localhost:9090". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
  • it is not a react like
  • translation is problematic; the link can be at various position in other languages

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know; this way it is also not translation friendly

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't know React*. Please listen to someone else on the team with React experience. Treat any React code I write anytime soon to basically be pseudo-code. 😉

);
action = (
<div className="blank-slate-pf-main-action">
<button className="btn btn-primary btn-lg" onClick={mouseClick(start)}>{_("Start libvirt")}</button>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This button name should also be descriptive, similar to the header; that is, it should state: "Start Virtualization Service".

The docs link directly above explains that the "virtualization service" is libvirt.

@atiratree
Copy link
Contributor Author

screenshot from 2018-02-06 15-40-25

although now, the word "service" is occurring 3 time

@atiratree
Copy link
Contributor Author

atiratree commented Feb 6, 2018

Errors: expected usage

screenshot from 2018-02-06 16-28-34

@atiratree
Copy link
Contributor Author

atiratree commented Feb 6, 2018

Errors: expected usage

for create vm dialog that results in this flow:

  1. wait for few sec and allow user to fix the mistake 1)
  2. close the dialog
  3. error occurs with some delay
  4. show the error in Notification area machines: detect if libvirt is running #8493 (comment)
1)

screenshot from 2018-02-06 16-32-49

@garrett
Copy link
Member

garrett commented Feb 7, 2018

although now, the word "service" is occurring 3 time

Yeah, you're right.

The secondary line should be something more like "Please refer to libvirt documentation for more information."

(The link should be a link that opens in a new window with a target, such as: <a target="_blank" href="libvirt-docs-link-goes-here">link text</a>.)

@atiratree
Copy link
Contributor Author

The secondary line should be something more like "Please refer to libvirt documentation for more information."

I really think there should be link to the service in cockpit. The main reason for that is to enable the service. Clicking the button only makes the service start once.

We could also add the documentation part, but I am not sure if it isn't too much?

@mareklibra
Copy link
Contributor

mareklibra commented Feb 7, 2018

The main reason for that is to enable the service.

I agree, there's already functionality in Cockpit allowing fixing that in most of the cases.
From UX perspective, there might be Troubleshoot secondary action leading the user to the service view.

@garrett
Copy link
Member

garrett commented Feb 7, 2018

link to the service in cockpit

What do you mean? (I thought it was supposed to be a documentation link.)

The main reason for that is to enable the service. Clicking the button only makes the service start once.

Why not both enable and start the service at the same time?

leading the user to the service view

It wouldn't be helpful to just drop someone in the service view to find something (most people probably wouldn't remember they're looking for "libvirt") and then do something with it. (We know they'd need to enable the service, but would they? Most likely not.)

@atiratree
Copy link
Contributor Author

Why not both enable and start the service at the same time?

I do not think that is good default behaviour, because it might not be what the user wants.

It wouldn't be helpful to just drop someone in the service view to find something (most people probably wouldn't remember they're looking for "libvirt") and then do something with it. (We know they'd need to enable the service, but would they? Most likely not.)

  • no, it goes exactly to the service detail /system/services#/libvirtd.service
  • I think linux user should be familiar with the concept of services and what is expected of them to do if they click more configuration -> lands on the libvirt service page

there can be also link to the documentation but I do not think it is necessary

@atiratree
Copy link
Contributor Author

Can we let it in the current state?

I will start writing tests for this.

@garrett
Copy link
Member

garrett commented Feb 20, 2018

There seem to be multiple things covered in this one PR. Can we split apart this pull request into 3 different items?

  1. This PR: Keep the general error message that has an empty pattern
  2. New, separate PR: Create new dialog error
  3. A design issue where it is discussed how best to handle enable versus start for services (as this impacts other parts of Cockpit as well, such as the Containers page)

I'll open the issue (item # 3).

@suomiy, can you move the dialog part of this PR to a separate one (# 2)?

By splitting it apart, I think it can help to focus on getting this PR in (and then the next too). Thanks!

@atiratree
Copy link
Contributor Author

ubuntu needs to be fixed
name of the service is libvirt-bin instead of libvirtd there

@atiratree atiratree force-pushed the libvirt-status-msgs branch 4 times, most recently from e16e2bf to fdb4366 Compare March 19, 2018 23:49
@atiratree
Copy link
Contributor Author

@mareklibra
Can you please rereview? I had to get name of a libvirt service in initialization phase because of ubuntus

@@ -170,29 +174,47 @@ LIBVIRT_PROVIDER = {
};
},

INITIALIZE () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not reuse the init method above?
Please note, the init() can return both boolean or Promise.

I think we can fire reading of libvirt service name in init(), store result into redux and reuse it in GET_ALL_VMS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please align with similar initialization flow in pkg/ovirt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided it is better not to mix init() in libvirt and ovirt

*/
export function getAllVms(connectionName) {
return virt('GET_ALL_VMS', { connectionName });
export function getAllVms(connectionName, libvirtServiceName) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like adding the param here unless really necessarily.
It has nothing to do with the actual read of VMs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided it is fine for now

render() {
const service = this.props.libvirtService;
const goToLink = () => cockpit.jump("/system/services#/" + service.name);
const start = () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be moved outside the render() function to sort of onStartClicked()

@@ -50,5 +50,5 @@ export function appMain() {
render();

// initiate data retrieval
store.dispatch(getAllVms());
store.dispatch(initialize());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important: Please do update pkg/ovirt accordingly as well.

def startLibvirt(self):
m = self.machine
# Ensure everything has started correctly
m.execute("systemctl start libvirtd")
m.execute("systemctl start {0}".format(self.getLibvirtName()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests were passing prior this PR. What has changed that this is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it works, but disabling libvirt will make this stop working in ubuntus where libvirt-bin.service can have a priority. libvirtd.service is an alias when libvirt-bin.service is enabled

@atiratree atiratree force-pushed the libvirt-status-msgs branch 2 times, most recently from 3c35182 to 4fe8dca Compare March 20, 2018 20:10
@atiratree
Copy link
Contributor Author

fixed review

Copy link
Contributor

@mareklibra mareklibra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! This looks very nice indeed. I found some things to clean up, but the general structure looks fine.

logDebug(`${this.name}.CHECK_LIBVIRT_STATUS`);
return dispatch => {
return cockpit.spawn(['systemctl', '--property=ActiveState', '--property=UnitFileState', 'show', serviceName])
.done(data => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the systemd D-Bus API for querying and controlling the libvirt service. Have a look at pkg/lib/service.js which provides a nice API for that. It's e. g. being used in pkg/tuned/dialog.js.

if (line.toLowerCase().includes("failed to connect")) {
// known error: virsh process fails anyway
logDebug(error, line);
}else{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nitpick: missing spaces around else)

unitState: 'unknown',
},
osInfoList: [],
};
state = state ? state : [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is a no-op now and should go away. After the previous hunk state is now always non-empty.

#!/bin/sh

# libvirt-bin is primary in ubuntu 1604
NAME="`systemctl list-unit-files | grep -o libvirt-bin.service || echo libvirtd.service`"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can save the grep and the extra systemctl call below with

NAME=`systemctl --no-legend list-unit-files  libvirtd.service libvirt-bin.service |  head -n1 | cut -f1 -d' '`

This will prefer libvirtd.service over libvirt-bin.service even if the latter is an alias on upgrades.

name = self.machine.execute(
"systemctl list-unit-files | grep -o libvirt-bin.service || echo libvirtd.service").replace('\n', '')
return self.machine.execute(
"systemctl --property=Id show {0} | cut -c 4-".format(name)).replace('\n', '')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not repeat the same logic. Just special-case if self.machine.image == "ubuntu-1604":

m.execute("systemctl disable {0}".format(libvirtServiceName))
print(self.getLibvirtName())
m.execute("systemctl stop {0}".format(libvirtServiceName))
b.wait(lambda: not checkLibvirtEnabled())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitively no wait needed here -- systemctl stop and disable are synchronous.

b.click("#start-libvirt")

b.wait_in_text("body", "Virtual Machines")
b.wait(lambda: checkLibvirtEnabled())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, once the UI updates (which you already wait for in the previous line), this should succeed right away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ui shows up when the service starts. We should not expect the Ui to enable the service atomicly with the start

b.wait_present("#enable-libvirt:checked")
b.set_checked("#enable-libvirt", False)
b.click("#start-libvirt")
b.wait(lambda: not checkLibvirtEnabled())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you move this down one line (i. e. wait for the UI to update first), it should again not require waiting.

b.wait(lambda: url_location in b.eval_js("window.location.href"))

# HACK: restarting libvirtd causes this completely unrelated SELinux issue
self.allow_journal_messages('.*denied.*search.*"systemd-machine".*dev="proc".*')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally report them to bugzilla, create a known issue, and add a naughty override for these, so that these issues get fixed and these hacks clean up themselves over time.

self.allow_journal_messages('.*denied.*search.*"systemd-machine".*dev="proc".*')
# enabling/disabling libvirt causes unwanted logs
self.allow_journal_messages('.*libvirt.*')
self.allow_journal_messages('.*virt.*socket.*')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this looks too broad and can easily hide errors. What are the complete messages here, and how do they break the test? We only check for unexpected log messages on cockpit.service and type=14?? audit messages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure it was complaining about creating/removing symlinks, but now it is fine on my setup.

It only throws this on ubuntu-1604

audit: type=1400 audit(1521636424.736:15): apparmor="DENIED" operation="open" profile="libvirt-a73c87e3-37a7-43c0-8671-b477f5783d95" name="/etc/gss/mech.d/" pid=2069 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=64055 ouid=0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debian-testing

audit: type=1400 audit(1521637589.708:41): apparmor="DENIED" operation="signal" profile="/usr/sbin/libvirtd" pid=1146 comm="libvirtd" requested_mask="send" denied_mask="send" signal=hup peer="unconfined"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@suomiy : The gss failure is issue #6901, we already have a naughty override for this. We don't yet have one for the "signal" thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed #6901. Anyway I think --sit should not fail without --thorough option on known issue. This got me confused.

@atiratree
Copy link
Contributor Author

fixed review

@atiratree atiratree force-pushed the libvirt-status-msgs branch 2 times, most recently from 2378fd7 to 1a0f514 Compare March 21, 2018 14:13
Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates! Next round of review.

if [ -n "$NAME" ]; then
# get id name because libvirt-bin is primary in ubuntu 1604
systemctl --property=Id show "$NAME" | cut -c 4-
fi
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this isn't necessary. On Ubuntu-16.04, the above command already gives you libvirt-bin.service. (But see comment above, I think this file could be eliminated completely).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can also give libvirtd.service on Ubuntu 16.04. libvirt-bin.service creates alias to libvirtd.service when enabled. To make things more interesting we even cannot prefer libvirt-bin.service because on ubuntu 17.10 libvirtd.service is primary and creates symlink to libvirt-bin.service.

We really need the id of the service, because that is the only service visible when disabled and stopped.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"We really need the id of the service" → What does that mean? How is it in any way different than the $NAME you already determined? (It's demonstrably not on fedora-27 and ubuntu-1604; I didn't try other cases)

Copy link
Contributor Author

@atiratree atiratree Mar 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sorry. It works on ubuntu 16.04 (didn't try this exact command and assumed wrong sort order of those two names).

But it still breaks on ubuntu 17.10:

systemctl enable libvirtd.service
systemctl --no-legend list-unit-files libvirtd.service libvirt-bin.service |  head -n1 | cut -f1 -d' '
# libvirt-bin.service
systemctl disable libvirtd.service
systemctl --no-legend list-unit-files libvirtd.service libvirt-bin.service |  head -n1 | cut -f1 -d' '
# libvirtd.service

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

appending to the last comment:

systemctl status libvirt-bin
# Unit libvirt-bin.service could not be found.

logDebug(`${this.name}.INIT_DATA_RETRIEVAL():`);
return dispatch => {
dispatch(getOsInfoList());
return cockpit.script(getLibvirtServiceNameScript, null, { err: "message", environ: ['LC_ALL=en_US.UTF-8'] })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this script is now an one-liner, and you already do some regexp post-processing below, you could just simply call cockpit.spawn() here on systemctl --no-legend list-unit-files libvirtd.service libvirt-bin.service and ditch the script. This makes the code easier to read as everything that happens here is at the same place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still need the script.

return cockpit.script(getLibvirtServiceNameScript, null, { err: "message", environ: ['LC_ALL=en_US.UTF-8'] })
.then(serviceName => {
const match = serviceName.match(/(.+)\n$/);
const name = getRegexGroup(match, 1, 'libvirtd.service'); // fallback to libvirtd to be able to show link in libvirtSlate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should fall back in this way. If libvirtd isn't installed (i. e. the above command does not have any result), then this should be treated properly and not ignored. If libvirt isn't installed, then getting its state and VMs is doomed to fail anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I will move this handling to libvirtSlate and leave serviceName empty in the store

dispatch(getOsInfoList());
return cockpit.script(getLibvirtServiceNameScript, null, { err: "message", environ: ['LC_ALL=en_US.UTF-8'] })
.then(serviceName => {
const match = serviceName.match(/(.+)\n$/);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to get the first word only, this saves the head and cut processing in shell, and drop the unnecessary helper function:

.then(output => {
    const match = output.match(/(\w+)/);
    const serviceName = match ? match[0] : null;
    if (serviceName) {
        ... get libvirt state
    } else {
         console.error (...);
         // handle faillure
   }
);

# HACK: restarting libvirtd causes this completely unrelated SELinux issue
self.allow_journal_messages('.*denied.*search.*"systemd-machine".*dev="proc".*')

self.allow_journal_messages('.*audit.*apparmor="DENIED".*operation="signal".*libvirt.*denied_mask="send".*')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two still need to be replaced with known issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should I create these issues and put these messages into naughty overrides in this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we could reopen this issue #8467 ? It is exactly the same except the signal is hup instead of kill

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quite sure the policy is not so specific as to limit particular signals, it's just not allowed to send signals in general. I. e. it's most likely the same bug. But are you sure that it still actually applies? This was fixed recently (certainly way after you started working on this PR), and in the recent test run there is no such apparmor denial. So I think this can just be dropped and should be fine as-is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still see it in the logs, but it is fine with me if it is not causing any problems anymore.

@atiratree
Copy link
Contributor Author

fixed except the journal messages (the first one is present in testBasic as well)

- Show spinner before the status is known
- Show slate with action if libvirt is down

Closes cockpit-project#8493
Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a force-push with some small changes:

  • Drop the AppArmor expected message (should work just fine now)
  • Squash code change and test together
  • Add a Closes # for button mergeability

Thank you, great work!

@martinpitt martinpitt merged commit 94cc54e into cockpit-project:master Mar 24, 2018
martinpitt pushed a commit that referenced this pull request Mar 24, 2018
- Show spinner before the status is known
- Show slate with action if libvirt is down

Closes #8493
@martinpitt
Copy link
Member

Current screenshot for release notes:

libvirt-status

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

machines: detect libvirt stopped
5 participants