{"action":"created","comment":{"url":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/comments/93524407","pull_request_review_id":14054575,"id":93524407,"diff_hunk":"@@ -0,0 +1,114 @@\n+#\n+# Copyright 2016, SUSE\n+#\n+# Licensed under the Apache License, Version 2.0 (the \"License\");\n+# you may not use this file except in compliance with the License.\n+# You may obtain a copy of the License at\n+#\n+#     http://www.apache.org/licenses/LICENSE-2.0\n+#\n+# Unless required by applicable law or agreed to in writing, software\n+# distributed under the License is distributed on an \"AS IS\" BASIS,\n+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+# See the License for the specific language governing permissions and\n+# limitations under the License.\n+#\n+\n+require \"rexml/document\"\n+\n+module CrowbarPacemakerCIBAttribute\n+  def self.validate_simple(string, type)\n+    # only accept alphanumeric characters as well as - and _\n+    if string !~ /^[-\\w]*$/\n+      raise \"Invalid #{type} when interacting with pacemaker attributes: #{string}\"\n+    end\n+  end\n+\n+  def self.validate_node(node)\n+    validate_simple(node, \"node name\")\n+  end\n+\n+  def self.validate_attribute(attribute)\n+    validate_simple(attribute, \"attribute name\")\n+  end\n+\n+  def self.validate_value(value)\n+    validate_simple(attribute, \"value\")\n+  end\n+\n+  def self.get(node, attribute, default)\n+    # This is what we want:\n+    # $ crm_attribute --name=crowbar_sync-pacemaker_setup --node=d52-54-77-77-77-2 --query --default=0\n+    # Could not map name=d52-54-77-77-77-2 to a UUID\n+    # $ crm_attribute --name=crowbar_sync-pacemaker_setup --node=d52-54-77-77-77-02 --query --default=0\n+    # scope=nodes  name=crowbar_sync-pacemaker_setup value=0\n+    validate_node(node)\n+    validate_attribute(attribute)\n+    validate_value(default)\n+    output = `crm_attribute --name=#{attribute} --node=#{node} --query --default=#{default} 2>&1`\n+    if output !~ /^Could not map name=/\n+      raise \"Cannot fetch attribute for node unknown to pacemaker (#{output})\"\n+    elsif output !~ /^scope=nodes\\s+name=#{attribute}\\s+value=(.*)$/\n+      raise \"Unexpected output when fetching pacemaker attribute: #{output}\"\n+    end\n+    $1\n+  end\n+\n+  def self.set(node, attribute, value)\n+    # We want to do something like:\n+    # $ crm_attribute --name=crowbar_sync-pacemaker_setup --node=d52-54-77-77-77-01 --update=1\n+    validate_node(node)\n+    validate_attribute(attribute)\n+    validate_value(default)\n+    `crm_attribute --name=#{attribute} --node=#{node} --update=#{value} &> /dev/null`\n+  end\n+\n+  def self.unset(node, attribute)\n+    # We want to do something like:\n+    # $ crm_attribute --name=crowbar_sync-pacemaker_setup --node=d52-54-77-77-77-01 --delete\n+    validate_node(node)\n+    validate_attribute(attribute)\n+    `crm_attribute --name=#{attribute} --node=#{node} --delete &> /dev/null`\n+  end\n+\n+  def self.list(node)\n+    # We want to do something like:\n+    # $ crm_mon --show-node-attributes --as-xml\n+    # <?xml version=\"1.0\"?>\n+    # <crm_mon version=\"1.1.13\">\n+    # [...]\n+    #     <node_attributes>\n+    #         <node name=\"d52-54-77-77-77-01\">\n+    #             <attribute name=\"OpenStack-role\" value=\"controller\" />\n+    #             <attribute name=\"crowbar_sync-pacemaker_setup\" value=\"1\" />\n+    #             <attribute name=\"maintenance\" value=\"off\" />\n+    #         </node>\n+    #         <node name=\"d52-54-77-77-77-02\">\n+    #             <attribute name=\"OpenStack-role\" value=\"controller\" />\n+    #             <attribute name=\"maintenance\" value=\"off\" />\n+    #         </node>\n+    #         <node name=\"d52-54-77-77-77-03\">\n+    #             <attribute name=\"OpenStack-role\" value=\"controller\" />\n+    #             <attribute name=\"maintenance\" value=\"off\" />\n+    #         </node>\n+    #     </node_attributes>\n+    # [...]\n+    validate_node(node)\n+\n+    begin\n+      xml = REXML::Document.new(`crm_mon --show-node-attributes --as-xml 2> /dev/null`)\n+    rescue REXML::ParseException => e\n+      raise \"Cannot parse output of crm_mon when listing attributes!\"\n+    end\n+\n+    raise \"No xml output from crm_mon when listing attributes!\" if xml.root.nil?\n+\n+    all_attributes = {}\n+\n+    xml.root.elements.each(\"node_attributes/node[@name=\\\"#{node}\\\"]/attribute\") do |e|","path":"chef/cookbooks/crowbar-pacemaker/libraries/cibattribute.rb","position":108,"original_position":108,"commit_id":"3c8411ab49a756bc3c7d489ff79bd933d00707e3","original_commit_id":"3c8411ab49a756bc3c7d489ff79bd933d00707e3","user":{"login":"houndci-bot","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"Lint/ShadowingOuterLocalVariable: Shadowing outer local variable - e.","created_at":"2016-12-21T21:38:19Z","updated_at":"2016-12-21T21:38:19Z","html_url":"https://github.com/crowbar/crowbar-ha/pull/170#discussion_r93524407","pull_request_url":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170","_links":{"self":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/comments/93524407"},"html":{"href":"https://github.com/crowbar/crowbar-ha/pull/170#discussion_r93524407"},"pull_request":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170"}}},"pull_request":{"url":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170","id":99009236,"html_url":"https://github.com/crowbar/crowbar-ha/pull/170","diff_url":"https://github.com/crowbar/crowbar-ha/pull/170.diff","patch_url":"https://github.com/crowbar/crowbar-ha/pull/170.patch","issue_url":"https://api.github.com/repos/crowbar/crowbar-ha/issues/170","number":170,"state":"open","locked":false,"title":"Reimplement sync marks without node searches","user":{"login":"vuntz","id":1758783,"avatar_url":"https://avatars.githubusercontent.com/u/1758783?v=3","gravatar_id":"","url":"https://api.github.com/users/vuntz","html_url":"https://github.com/vuntz","followers_url":"https://api.github.com/users/vuntz/followers","following_url":"https://api.github.com/users/vuntz/following{/other_user}","gists_url":"https://api.github.com/users/vuntz/gists{/gist_id}","starred_url":"https://api.github.com/users/vuntz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vuntz/subscriptions","organizations_url":"https://api.github.com/users/vuntz/orgs","repos_url":"https://api.github.com/users/vuntz/repos","events_url":"https://api.github.com/users/vuntz/events{/privacy}","received_events_url":"https://api.github.com/users/vuntz/received_events","type":"User","site_admin":false},"body":"This has several benefits, as highlighted in the commit messages.\r\n\r\nSubmitting now for early reviews, but this is not tested nor ready.","created_at":"2016-12-21T21:38:04Z","updated_at":"2016-12-21T21:38:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1386472bbc5da9b66ec9e19641d68ddb99fd4c50","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170/commits","review_comments_url":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170/comments","review_comment_url":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/comments{/number}","comments_url":"https://api.github.com/repos/crowbar/crowbar-ha/issues/170/comments","statuses_url":"https://api.github.com/repos/crowbar/crowbar-ha/statuses/3c8411ab49a756bc3c7d489ff79bd933d00707e3","head":{"label":"vuntz:new-sync-marks","ref":"new-sync-marks","sha":"3c8411ab49a756bc3c7d489ff79bd933d00707e3","user":{"login":"vuntz","id":1758783,"avatar_url":"https://avatars.githubusercontent.com/u/1758783?v=3","gravatar_id":"","url":"https://api.github.com/users/vuntz","html_url":"https://github.com/vuntz","followers_url":"https://api.github.com/users/vuntz/followers","following_url":"https://api.github.com/users/vuntz/following{/other_user}","gists_url":"https://api.github.com/users/vuntz/gists{/gist_id}","starred_url":"https://api.github.com/users/vuntz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vuntz/subscriptions","organizations_url":"https://api.github.com/users/vuntz/orgs","repos_url":"https://api.github.com/users/vuntz/repos","events_url":"https://api.github.com/users/vuntz/events{/privacy}","received_events_url":"https://api.github.com/users/vuntz/received_events","type":"User","site_admin":false},"repo":{"id":41142170,"name":"crowbar-ha","full_name":"vuntz/crowbar-ha","owner":{"login":"vuntz","id":1758783,"avatar_url":"https://avatars.githubusercontent.com/u/1758783?v=3","gravatar_id":"","url":"https://api.github.com/users/vuntz","html_url":"https://github.com/vuntz","followers_url":"https://api.github.com/users/vuntz/followers","following_url":"https://api.github.com/users/vuntz/following{/other_user}","gists_url":"https://api.github.com/users/vuntz/gists{/gist_id}","starred_url":"https://api.github.com/users/vuntz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vuntz/subscriptions","organizations_url":"https://api.github.com/users/vuntz/orgs","repos_url":"https://api.github.com/users/vuntz/repos","events_url":"https://api.github.com/users/vuntz/events{/privacy}","received_events_url":"https://api.github.com/users/vuntz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/vuntz/crowbar-ha","description":"HA deployment for Crowbar","fork":true,"url":"https://api.github.com/repos/vuntz/crowbar-ha","forks_url":"https://api.github.com/repos/vuntz/crowbar-ha/forks","keys_url":"https://api.github.com/repos/vuntz/crowbar-ha/keys{/key_id}","collaborators_url":"https://api.github.com/repos/vuntz/crowbar-ha/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/vuntz/crowbar-ha/teams","hooks_url":"https://api.github.com/repos/vuntz/crowbar-ha/hooks","issue_events_url":"https://api.github.com/repos/vuntz/crowbar-ha/issues/events{/number}","events_url":"https://api.github.com/repos/vuntz/crowbar-ha/events","assignees_url":"https://api.github.com/repos/vuntz/crowbar-ha/assignees{/user}","branches_url":"https://api.github.com/repos/vuntz/crowbar-ha/branches{/branch}","tags_url":"https://api.github.com/repos/vuntz/crowbar-ha/tags","blobs_url":"https://api.github.com/repos/vuntz/crowbar-ha/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/vuntz/crowbar-ha/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/vuntz/crowbar-ha/git/refs{/sha}","trees_url":"https://api.github.com/repos/vuntz/crowbar-ha/git/trees{/sha}","statuses_url":"https://api.github.com/repos/vuntz/crowbar-ha/statuses/{sha}","languages_url":"https://api.github.com/repos/vuntz/crowbar-ha/languages","stargazers_url":"https://api.github.com/repos/vuntz/crowbar-ha/stargazers","contributors_url":"https://api.github.com/repos/vuntz/crowbar-ha/contributors","subscribers_url":"https://api.github.com/repos/vuntz/crowbar-ha/subscribers","subscription_url":"https://api.github.com/repos/vuntz/crowbar-ha/subscription","commits_url":"https://api.github.com/repos/vuntz/crowbar-ha/commits{/sha}","git_commits_url":"https://api.github.com/repos/vuntz/crowbar-ha/git/commits{/sha}","comments_url":"https://api.github.com/repos/vuntz/crowbar-ha/comments{/number}","issue_comment_url":"https://api.github.com/repos/vuntz/crowbar-ha/issues/comments{/number}","contents_url":"https://api.github.com/repos/vuntz/crowbar-ha/contents/{+path}","compare_url":"https://api.github.com/repos/vuntz/crowbar-ha/compare/{base}...{head}","merges_url":"https://api.github.com/repos/vuntz/crowbar-ha/merges","archive_url":"https://api.github.com/repos/vuntz/crowbar-ha/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/vuntz/crowbar-ha/downloads","issues_url":"https://api.github.com/repos/vuntz/crowbar-ha/issues{/number}","pulls_url":"https://api.github.com/repos/vuntz/crowbar-ha/pulls{/number}","milestones_url":"https://api.github.com/repos/vuntz/crowbar-ha/milestones{/number}","notifications_url":"https://api.github.com/repos/vuntz/crowbar-ha/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/vuntz/crowbar-ha/labels{/name}","releases_url":"https://api.github.com/repos/vuntz/crowbar-ha/releases{/id}","deployments_url":"https://api.github.com/repos/vuntz/crowbar-ha/deployments","created_at":"2015-08-21T07:34:12Z","updated_at":"2015-08-21T07:34:13Z","pushed_at":"2016-12-21T21:37:13Z","git_url":"git://github.com/vuntz/crowbar-ha.git","ssh_url":"git@github.com:vuntz/crowbar-ha.git","clone_url":"https://github.com/vuntz/crowbar-ha.git","svn_url":"https://github.com/vuntz/crowbar-ha","homepage":"","size":1351,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"crowbar:master","ref":"master","sha":"c08655eb6841faa54ff2bb67f63bfd46612aab85","user":{"login":"crowbar","id":2910205,"avatar_url":"https://avatars.githubusercontent.com/u/2910205?v=3","gravatar_id":"","url":"https://api.github.com/users/crowbar","html_url":"https://github.com/crowbar","followers_url":"https://api.github.com/users/crowbar/followers","following_url":"https://api.github.com/users/crowbar/following{/other_user}","gists_url":"https://api.github.com/users/crowbar/gists{/gist_id}","starred_url":"https://api.github.com/users/crowbar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crowbar/subscriptions","organizations_url":"https://api.github.com/users/crowbar/orgs","repos_url":"https://api.github.com/users/crowbar/repos","events_url":"https://api.github.com/users/crowbar/events{/privacy}","received_events_url":"https://api.github.com/users/crowbar/received_events","type":"Organization","site_admin":false},"repo":{"id":39006836,"name":"crowbar-ha","full_name":"crowbar/crowbar-ha","owner":{"login":"crowbar","id":2910205,"avatar_url":"https://avatars.githubusercontent.com/u/2910205?v=3","gravatar_id":"","url":"https://api.github.com/users/crowbar","html_url":"https://github.com/crowbar","followers_url":"https://api.github.com/users/crowbar/followers","following_url":"https://api.github.com/users/crowbar/following{/other_user}","gists_url":"https://api.github.com/users/crowbar/gists{/gist_id}","starred_url":"https://api.github.com/users/crowbar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crowbar/subscriptions","organizations_url":"https://api.github.com/users/crowbar/orgs","repos_url":"https://api.github.com/users/crowbar/repos","events_url":"https://api.github.com/users/crowbar/events{/privacy}","received_events_url":"https://api.github.com/users/crowbar/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/crowbar/crowbar-ha","description":"HA deployment for Crowbar","fork":false,"url":"https://api.github.com/repos/crowbar/crowbar-ha","forks_url":"https://api.github.com/repos/crowbar/crowbar-ha/forks","keys_url":"https://api.github.com/repos/crowbar/crowbar-ha/keys{/key_id}","collaborators_url":"https://api.github.com/repos/crowbar/crowbar-ha/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/crowbar/crowbar-ha/teams","hooks_url":"https://api.github.com/repos/crowbar/crowbar-ha/hooks","issue_events_url":"https://api.github.com/repos/crowbar/crowbar-ha/issues/events{/number}","events_url":"https://api.github.com/repos/crowbar/crowbar-ha/events","assignees_url":"https://api.github.com/repos/crowbar/crowbar-ha/assignees{/user}","branches_url":"https://api.github.com/repos/crowbar/crowbar-ha/branches{/branch}","tags_url":"https://api.github.com/repos/crowbar/crowbar-ha/tags","blobs_url":"https://api.github.com/repos/crowbar/crowbar-ha/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/crowbar/crowbar-ha/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/crowbar/crowbar-ha/git/refs{/sha}","trees_url":"https://api.github.com/repos/crowbar/crowbar-ha/git/trees{/sha}","statuses_url":"https://api.github.com/repos/crowbar/crowbar-ha/statuses/{sha}","languages_url":"https://api.github.com/repos/crowbar/crowbar-ha/languages","stargazers_url":"https://api.github.com/repos/crowbar/crowbar-ha/stargazers","contributors_url":"https://api.github.com/repos/crowbar/crowbar-ha/contributors","subscribers_url":"https://api.github.com/repos/crowbar/crowbar-ha/subscribers","subscription_url":"https://api.github.com/repos/crowbar/crowbar-ha/subscription","commits_url":"https://api.github.com/repos/crowbar/crowbar-ha/commits{/sha}","git_commits_url":"https://api.github.com/repos/crowbar/crowbar-ha/git/commits{/sha}","comments_url":"https://api.github.com/repos/crowbar/crowbar-ha/comments{/number}","issue_comment_url":"https://api.github.com/repos/crowbar/crowbar-ha/issues/comments{/number}","contents_url":"https://api.github.com/repos/crowbar/crowbar-ha/contents/{+path}","compare_url":"https://api.github.com/repos/crowbar/crowbar-ha/compare/{base}...{head}","merges_url":"https://api.github.com/repos/crowbar/crowbar-ha/merges","archive_url":"https://api.github.com/repos/crowbar/crowbar-ha/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/crowbar/crowbar-ha/downloads","issues_url":"https://api.github.com/repos/crowbar/crowbar-ha/issues{/number}","pulls_url":"https://api.github.com/repos/crowbar/crowbar-ha/pulls{/number}","milestones_url":"https://api.github.com/repos/crowbar/crowbar-ha/milestones{/number}","notifications_url":"https://api.github.com/repos/crowbar/crowbar-ha/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/crowbar/crowbar-ha/labels{/name}","releases_url":"https://api.github.com/repos/crowbar/crowbar-ha/releases{/id}","deployments_url":"https://api.github.com/repos/crowbar/crowbar-ha/deployments","created_at":"2015-07-13T10:53:43Z","updated_at":"2016-12-19T05:57:08Z","pushed_at":"2016-12-21T21:38:05Z","git_url":"git://github.com/crowbar/crowbar-ha.git","ssh_url":"git@github.com:crowbar/crowbar-ha.git","clone_url":"https://github.com/crowbar/crowbar-ha.git","svn_url":"https://github.com/crowbar/crowbar-ha","homepage":"","size":1294,"stargazers_count":2,"watchers_count":2,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":23,"mirror_url":null,"open_issues_count":21,"forks":23,"open_issues":21,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170"},"html":{"href":"https://github.com/crowbar/crowbar-ha/pull/170"},"issue":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/issues/170"},"comments":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/issues/170/comments"},"review_comments":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170/comments"},"review_comment":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/pulls/170/commits"},"statuses":{"href":"https://api.github.com/repos/crowbar/crowbar-ha/statuses/3c8411ab49a756bc3c7d489ff79bd933d00707e3"}}}}
{"actor":{"display_login":"houndci-bot"}}