{"action":"created","comment":{"url":"https://api.github.com/repos/cockpit-project/cockpit/pulls/comments/143696250","pull_request_review_id":68243228,"id":143696250,"diff_hunk":"@@ -0,0 +1,344 @@\n+#! /usr/bin/python\n+\n+# nfs-mounts   --  Monitor and manage NFS mounts\n+#\n+# This is similar to how UDisks2 monitors and manages block device\n+# mounts, but for NFS.  This might be moved into UDisks2, or not.\n+\n+import select\n+import re\n+import sys\n+import json\n+\n+import os\n+import ctypes\n+import struct\n+import subprocess\n+import traceback\n+\n+# We monitor all NFS remotes listed in /etc/fstab and in /etc/mtab.\n+# If a entry from mtab is also found in fstab, we report only the\n+# fstab entry and mark it is \"mounted\".\n+\n+IN_CLOSE_WRITE = 0x00000008\n+IN_IGNORED     = 0x00008000\n+\n+class Inotify:\n+    def __init__(self):\n+        self._libc = ctypes.CDLL(None, use_errno=True)\n+        self._get_errno_func = ctypes.get_errno\n+\n+        self._libc.inotify_init.argtypes = []\n+        self._libc.inotify_init.restype = ctypes.c_int\n+        self._libc.inotify_add_watch.argtypes = [ctypes.c_int, ctypes.c_char_p,\n+                                                 ctypes.c_uint32]\n+        self._libc.inotify_add_watch.restype = ctypes.c_int\n+        self._libc.inotify_rm_watch.argtypes = [ctypes.c_int, ctypes.c_int]\n+        self._libc.inotify_rm_watch.restype = ctypes.c_int\n+\n+        self.fd = self._libc.inotify_init()\n+\n+    def add_watch(self, path, mask):\n+        path = ctypes.create_string_buffer(path.encode(sys.getfilesystemencoding()))\n+        wd = self._libc.inotify_add_watch(self.fd, path, mask)\n+        if wd < 0:\n+            sys.stderr.write(\"can't add watch for %s: %s\\n\" % (path, os.strerror(self._get_errno_func())))\n+        return wd\n+\n+    def rem_watch(self, wd):\n+        if self._libc.inotify_rm_watch(self.fd, wd) < 0:\n+            sys.stderr.write(\"can't remove watch: %s\\n\" % (os.strerror(self._get_errno_func())))\n+\n+    def process(self, callback):\n+        buf = os.read(self.fd, 4096)\n+        pos = 0\n+        while pos < len(buf):\n+            (wd, mask, cookie, name_len) = struct.unpack('iIII', buf[pos:pos+16])\n+            pos += 16\n+            (name,) = struct.unpack('%ds' % name_len, buf[pos:pos + name_len])\n+            pos += name_len\n+            callback(wd, mask, name.decode().rstrip('\\0'))","path":"pkg/storaged/nfs-mounts.py","position":60,"original_position":60,"commit_id":"3debb56effdc2e40d707ee495264f437605fa6b4","original_commit_id":"3debb56effdc2e40d707ee495264f437605fa6b4","user":{"login":"mvollmer","id":3228183,"avatar_url":"https://avatars1.githubusercontent.com/u/3228183?v=4","gravatar_id":"","url":"https://api.github.com/users/mvollmer","html_url":"https://github.com/mvollmer","followers_url":"https://api.github.com/users/mvollmer/followers","following_url":"https://api.github.com/users/mvollmer/following{/other_user}","gists_url":"https://api.github.com/users/mvollmer/gists{/gist_id}","starred_url":"https://api.github.com/users/mvollmer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mvollmer/subscriptions","organizations_url":"https://api.github.com/users/mvollmer/orgs","repos_url":"https://api.github.com/users/mvollmer/repos","events_url":"https://api.github.com/users/mvollmer/events{/privacy}","received_events_url":"https://api.github.com/users/mvollmer/received_events","type":"User","site_admin":false},"body":"> Not for RHEL 7.4 - there, the bridge is shipped in base and cannot (easily) change, but in extras we ship cockpit-{storaged,packagekit} which get rebased frequently.\r\n\r\nI see.  This is another argument against including remote mounts in our fsys sampling.","created_at":"2017-10-10T11:10:39Z","updated_at":"2017-10-10T11:10:39Z","html_url":"https://github.com/cockpit-project/cockpit/pull/7580#discussion_r143696250","pull_request_url":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/cockpit-project/cockpit/pulls/comments/143696250"},"html":{"href":"https://github.com/cockpit-project/cockpit/pull/7580#discussion_r143696250"},"pull_request":{"href":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580"}},"in_reply_to_id":143164652},"pull_request":{"url":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580","id":138144509,"html_url":"https://github.com/cockpit-project/cockpit/pull/7580","diff_url":"https://github.com/cockpit-project/cockpit/pull/7580.diff","patch_url":"https://github.com/cockpit-project/cockpit/pull/7580.patch","issue_url":"https://api.github.com/repos/cockpit-project/cockpit/issues/7580","number":7580,"state":"open","locked":false,"title":"NFS client","user":{"login":"mvollmer","id":3228183,"avatar_url":"https://avatars1.githubusercontent.com/u/3228183?v=4","gravatar_id":"","url":"https://api.github.com/users/mvollmer","html_url":"https://github.com/mvollmer","followers_url":"https://api.github.com/users/mvollmer/followers","following_url":"https://api.github.com/users/mvollmer/following{/other_user}","gists_url":"https://api.github.com/users/mvollmer/gists{/gist_id}","starred_url":"https://api.github.com/users/mvollmer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mvollmer/subscriptions","organizations_url":"https://api.github.com/users/mvollmer/orgs","repos_url":"https://api.github.com/users/mvollmer/repos","events_url":"https://api.github.com/users/mvollmer/events{/privacy}","received_events_url":"https://api.github.com/users/mvollmer/received_events","type":"User","site_admin":false},"body":"- [x] Also show mounts not in fstab\r\n- [x] Create and remove mount point directories\r\n- [x] Avoid flicker of arming machinery when list is rendered\r\n- [x] Use showmount to help with/validate remote bits\r\n- [x] Avoid quadratic complexity when preparing mount report\r\n- [x] Show nice text when there are no nfs mounts\r\n- [x] Tests\r\n- [x] Use \"mount -o remount\" if only options change\r\n- [x] Layout when armed\r\n- [x] Don't let the user change server/remote/dir when mount is busy.\r\n- [x] Refuse to remove busy mounts.\r\n- [x] Reimplement lsof/fuser withing nfs-mounts.py\r\n- [x] Let user kill all systemd units that keep a mount busy\r\n- [x] Use python3 in preference to python2\r\n- [x] Add nfs-server and python3-dbus to Debian/Ubuntu images\r\n- [x] Make video for release notes\r\n- [ ] #7812 \r\n- [ ] #7827 \r\n- [ ] #7852 \r\n\r\nVideo: https://www.youtube.com/watch?v=PGCBda3Le9Y","created_at":"2017-08-29T10:41:52Z","updated_at":"2017-10-10T11:10:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5bb150e31099a3ed11aebfe2d0f1357556cf31a7","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580/commits","review_comments_url":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580/comments","review_comment_url":"https://api.github.com/repos/cockpit-project/cockpit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cockpit-project/cockpit/issues/7580/comments","statuses_url":"https://api.github.com/repos/cockpit-project/cockpit/statuses/3debb56effdc2e40d707ee495264f437605fa6b4","head":{"label":"mvollmer:storage-nfs-client","ref":"storage-nfs-client","sha":"3debb56effdc2e40d707ee495264f437605fa6b4","user":{"login":"mvollmer","id":3228183,"avatar_url":"https://avatars1.githubusercontent.com/u/3228183?v=4","gravatar_id":"","url":"https://api.github.com/users/mvollmer","html_url":"https://github.com/mvollmer","followers_url":"https://api.github.com/users/mvollmer/followers","following_url":"https://api.github.com/users/mvollmer/following{/other_user}","gists_url":"https://api.github.com/users/mvollmer/gists{/gist_id}","starred_url":"https://api.github.com/users/mvollmer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mvollmer/subscriptions","organizations_url":"https://api.github.com/users/mvollmer/orgs","repos_url":"https://api.github.com/users/mvollmer/repos","events_url":"https://api.github.com/users/mvollmer/events{/privacy}","received_events_url":"https://api.github.com/users/mvollmer/received_events","type":"User","site_admin":false},"repo":{"id":20679941,"name":"cockpit","full_name":"mvollmer/cockpit","owner":{"login":"mvollmer","id":3228183,"avatar_url":"https://avatars1.githubusercontent.com/u/3228183?v=4","gravatar_id":"","url":"https://api.github.com/users/mvollmer","html_url":"https://github.com/mvollmer","followers_url":"https://api.github.com/users/mvollmer/followers","following_url":"https://api.github.com/users/mvollmer/following{/other_user}","gists_url":"https://api.github.com/users/mvollmer/gists{/gist_id}","starred_url":"https://api.github.com/users/mvollmer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mvollmer/subscriptions","organizations_url":"https://api.github.com/users/mvollmer/orgs","repos_url":"https://api.github.com/users/mvollmer/repos","events_url":"https://api.github.com/users/mvollmer/events{/privacy}","received_events_url":"https://api.github.com/users/mvollmer/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mvollmer/cockpit","description":"Cockpit, a user interface for GNU/Linux servers","fork":true,"url":"https://api.github.com/repos/mvollmer/cockpit","forks_url":"https://api.github.com/repos/mvollmer/cockpit/forks","keys_url":"https://api.github.com/repos/mvollmer/cockpit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mvollmer/cockpit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mvollmer/cockpit/teams","hooks_url":"https://api.github.com/repos/mvollmer/cockpit/hooks","issue_events_url":"https://api.github.com/repos/mvollmer/cockpit/issues/events{/number}","events_url":"https://api.github.com/repos/mvollmer/cockpit/events","assignees_url":"https://api.github.com/repos/mvollmer/cockpit/assignees{/user}","branches_url":"https://api.github.com/repos/mvollmer/cockpit/branches{/branch}","tags_url":"https://api.github.com/repos/mvollmer/cockpit/tags","blobs_url":"https://api.github.com/repos/mvollmer/cockpit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mvollmer/cockpit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mvollmer/cockpit/git/refs{/sha}","trees_url":"https://api.github.com/repos/mvollmer/cockpit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mvollmer/cockpit/statuses/{sha}","languages_url":"https://api.github.com/repos/mvollmer/cockpit/languages","stargazers_url":"https://api.github.com/repos/mvollmer/cockpit/stargazers","contributors_url":"https://api.github.com/repos/mvollmer/cockpit/contributors","subscribers_url":"https://api.github.com/repos/mvollmer/cockpit/subscribers","subscription_url":"https://api.github.com/repos/mvollmer/cockpit/subscription","commits_url":"https://api.github.com/repos/mvollmer/cockpit/commits{/sha}","git_commits_url":"https://api.github.com/repos/mvollmer/cockpit/git/commits{/sha}","comments_url":"https://api.github.com/repos/mvollmer/cockpit/comments{/number}","issue_comment_url":"https://api.github.com/repos/mvollmer/cockpit/issues/comments{/number}","contents_url":"https://api.github.com/repos/mvollmer/cockpit/contents/{+path}","compare_url":"https://api.github.com/repos/mvollmer/cockpit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mvollmer/cockpit/merges","archive_url":"https://api.github.com/repos/mvollmer/cockpit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mvollmer/cockpit/downloads","issues_url":"https://api.github.com/repos/mvollmer/cockpit/issues{/number}","pulls_url":"https://api.github.com/repos/mvollmer/cockpit/pulls{/number}","milestones_url":"https://api.github.com/repos/mvollmer/cockpit/milestones{/number}","notifications_url":"https://api.github.com/repos/mvollmer/cockpit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mvollmer/cockpit/labels{/name}","releases_url":"https://api.github.com/repos/mvollmer/cockpit/releases{/id}","deployments_url":"https://api.github.com/repos/mvollmer/cockpit/deployments","created_at":"2014-06-10T09:35:54Z","updated_at":"2016-07-01T17:36:24Z","pushed_at":"2017-10-10T09:42:46Z","git_url":"git://github.com/mvollmer/cockpit.git","ssh_url":"git@github.com:mvollmer/cockpit.git","clone_url":"https://github.com/mvollmer/cockpit.git","svn_url":"https://github.com/mvollmer/cockpit","homepage":"http://www.cockpit-project.org/","size":38920,"stargazers_count":2,"watchers_count":2,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":2,"default_branch":"master"}},"base":{"label":"cockpit-project:master","ref":"master","sha":"b06f2e0b7550f9df39b4a9bed2f80ed8f53e8611","user":{"login":"cockpit-project","id":5765104,"avatar_url":"https://avatars2.githubusercontent.com/u/5765104?v=4","gravatar_id":"","url":"https://api.github.com/users/cockpit-project","html_url":"https://github.com/cockpit-project","followers_url":"https://api.github.com/users/cockpit-project/followers","following_url":"https://api.github.com/users/cockpit-project/following{/other_user}","gists_url":"https://api.github.com/users/cockpit-project/gists{/gist_id}","starred_url":"https://api.github.com/users/cockpit-project/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cockpit-project/subscriptions","organizations_url":"https://api.github.com/users/cockpit-project/orgs","repos_url":"https://api.github.com/users/cockpit-project/repos","events_url":"https://api.github.com/users/cockpit-project/events{/privacy}","received_events_url":"https://api.github.com/users/cockpit-project/received_events","type":"Organization","site_admin":false},"repo":{"id":14049216,"name":"cockpit","full_name":"cockpit-project/cockpit","owner":{"login":"cockpit-project","id":5765104,"avatar_url":"https://avatars2.githubusercontent.com/u/5765104?v=4","gravatar_id":"","url":"https://api.github.com/users/cockpit-project","html_url":"https://github.com/cockpit-project","followers_url":"https://api.github.com/users/cockpit-project/followers","following_url":"https://api.github.com/users/cockpit-project/following{/other_user}","gists_url":"https://api.github.com/users/cockpit-project/gists{/gist_id}","starred_url":"https://api.github.com/users/cockpit-project/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cockpit-project/subscriptions","organizations_url":"https://api.github.com/users/cockpit-project/orgs","repos_url":"https://api.github.com/users/cockpit-project/repos","events_url":"https://api.github.com/users/cockpit-project/events{/privacy}","received_events_url":"https://api.github.com/users/cockpit-project/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cockpit-project/cockpit","description":"There's code a goin' on","fork":false,"url":"https://api.github.com/repos/cockpit-project/cockpit","forks_url":"https://api.github.com/repos/cockpit-project/cockpit/forks","keys_url":"https://api.github.com/repos/cockpit-project/cockpit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cockpit-project/cockpit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cockpit-project/cockpit/teams","hooks_url":"https://api.github.com/repos/cockpit-project/cockpit/hooks","issue_events_url":"https://api.github.com/repos/cockpit-project/cockpit/issues/events{/number}","events_url":"https://api.github.com/repos/cockpit-project/cockpit/events","assignees_url":"https://api.github.com/repos/cockpit-project/cockpit/assignees{/user}","branches_url":"https://api.github.com/repos/cockpit-project/cockpit/branches{/branch}","tags_url":"https://api.github.com/repos/cockpit-project/cockpit/tags","blobs_url":"https://api.github.com/repos/cockpit-project/cockpit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cockpit-project/cockpit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cockpit-project/cockpit/git/refs{/sha}","trees_url":"https://api.github.com/repos/cockpit-project/cockpit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cockpit-project/cockpit/statuses/{sha}","languages_url":"https://api.github.com/repos/cockpit-project/cockpit/languages","stargazers_url":"https://api.github.com/repos/cockpit-project/cockpit/stargazers","contributors_url":"https://api.github.com/repos/cockpit-project/cockpit/contributors","subscribers_url":"https://api.github.com/repos/cockpit-project/cockpit/subscribers","subscription_url":"https://api.github.com/repos/cockpit-project/cockpit/subscription","commits_url":"https://api.github.com/repos/cockpit-project/cockpit/commits{/sha}","git_commits_url":"https://api.github.com/repos/cockpit-project/cockpit/git/commits{/sha}","comments_url":"https://api.github.com/repos/cockpit-project/cockpit/comments{/number}","issue_comment_url":"https://api.github.com/repos/cockpit-project/cockpit/issues/comments{/number}","contents_url":"https://api.github.com/repos/cockpit-project/cockpit/contents/{+path}","compare_url":"https://api.github.com/repos/cockpit-project/cockpit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cockpit-project/cockpit/merges","archive_url":"https://api.github.com/repos/cockpit-project/cockpit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cockpit-project/cockpit/downloads","issues_url":"https://api.github.com/repos/cockpit-project/cockpit/issues{/number}","pulls_url":"https://api.github.com/repos/cockpit-project/cockpit/pulls{/number}","milestones_url":"https://api.github.com/repos/cockpit-project/cockpit/milestones{/number}","notifications_url":"https://api.github.com/repos/cockpit-project/cockpit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cockpit-project/cockpit/labels{/name}","releases_url":"https://api.github.com/repos/cockpit-project/cockpit/releases{/id}","deployments_url":"https://api.github.com/repos/cockpit-project/cockpit/deployments","created_at":"2013-11-01T17:36:46Z","updated_at":"2017-10-10T07:21:14Z","pushed_at":"2017-10-10T10:37:58Z","git_url":"git://github.com/cockpit-project/cockpit.git","ssh_url":"git@github.com:cockpit-project/cockpit.git","clone_url":"https://github.com/cockpit-project/cockpit.git","svn_url":"https://github.com/cockpit-project/cockpit","homepage":"http://www.cockpit-project.org/","size":37245,"stargazers_count":2345,"watchers_count":2345,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":345,"mirror_url":null,"open_issues_count":463,"forks":345,"open_issues":463,"watchers":2345,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580"},"html":{"href":"https://github.com/cockpit-project/cockpit/pull/7580"},"issue":{"href":"https://api.github.com/repos/cockpit-project/cockpit/issues/7580"},"comments":{"href":"https://api.github.com/repos/cockpit-project/cockpit/issues/7580/comments"},"review_comments":{"href":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580/comments"},"review_comment":{"href":"https://api.github.com/repos/cockpit-project/cockpit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cockpit-project/cockpit/pulls/7580/commits"},"statuses":{"href":"https://api.github.com/repos/cockpit-project/cockpit/statuses/3debb56effdc2e40d707ee495264f437605fa6b4"}},"author_association":"OWNER"}}
{"actor":{"display_login":"mvollmer"}}