{"action":"created","comment":{"url":"https://api.github.com/repos/puppetlabs/vanagon/pulls/comments/45373817","id":45373817,"diff_hunk":"@@ -0,0 +1,102 @@\n+require 'vanagon/engine/base'\n+require 'json'\n+require 'redis'\n+\n+REDIS_HOST = 'redis.delivery.puppetlabs.net'\n+REDIS_PORT = 6379\n+LOCK_USER = \"vanagon/#{ENV['USER']}\"\n+\n+\n+class Vanagon\n+  class Engine\n+    # Class to use when building on a hardware device (e.g. AIX, Switch, etc)\n+    #\n+    class Hardware < Base\n+\n+      # This method is used to obtain a vm to build upon\n+      # For the base class we just return the target that was passed in\n+      def select_target\n+        @build_host\n+      end\n+\n+      # Steps needed to tear down or clean up the system after the build is\n+      # complete. In this case, we'll attempt to unlock the hardware\n+      def teardown\n+        release_lock\n+      end\n+\n+      def initialize(platform)\n+        # see if we can aquire a lock\n+        Vanagon::Driver.logger.debug \"Hardware engine invoked.\"\n+        @platform = platform\n+        super\n+        @required_attributes << \"build_host\"\n+        @build_host = platform.build_host\n+        @target = @build_host\n+        aquire_lock\n+      end\n+\n+      # Lock the build_host as specificied in the platform definition. This\n+      # implement a rudimentary backoff sequence in order to wait on the host\n+      # to unlock. Note: this polls forever.\n+      def aquire_lock\n+        # Wait if locked\n+        if locked?\n+          warn \"Unable to aquire lock.\"\n+        end\n+        sleepcount = 1\n+        psleepcount = 1\n+        temp = 0\n+        while locked?\n+          print \"#{@build_host} is locked...\"\n+          puts \"waiting #{sleepcount} seconds.\"\n+          sleep sleepcount\n+          temp = sleepcount\n+          sleepcount += psleepcount\n+          psleepcount = temp\n+        end\n+        lock_contents = {}\n+        lock_contents[:user] = LOCK_USER\n+        lock_contents[:time] = Time.now.to_s\n+        lock_contents[:reason] = \"Vanagon build on #{@build_host}\"\n+        redis = connect_redis\n+        redis.set \"node_lock_#{@build_host.split('.')[0]}\", lock_contents.to_json\n+        puts \"Hardware locked: #{@build_host}\"\n+        Vanagon::Driver.logger.info \"Hardware locked: #{@build_host}\"\n+      end\n+\n+      # Release the lock on build_host\n+      def release_lock\n+        redis = connect_redis\n+        r = redis.get(\"node_lock_#{@build_host.split('.')[0]}\")","path":"lib/vanagon/engine/hardware.rb","position":null,"original_position":71,"commit_id":"fac4910b173c810ec89c76642807d9c13d0c623b","original_commit_id":"3db49407164291dfcade8ec34cd3beb8302c70a5","user":{"login":"haus","id":98408,"avatar_url":"https://avatars.githubusercontent.com/u/98408?v=3","gravatar_id":"","url":"https://api.github.com/users/haus","html_url":"https://github.com/haus","followers_url":"https://api.github.com/users/haus/followers","following_url":"https://api.github.com/users/haus/following{/other_user}","gists_url":"https://api.github.com/users/haus/gists{/gist_id}","starred_url":"https://api.github.com/users/haus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haus/subscriptions","organizations_url":"https://api.github.com/users/haus/orgs","repos_url":"https://api.github.com/users/haus/repos","events_url":"https://api.github.com/users/haus/events{/privacy}","received_events_url":"https://api.github.com/users/haus/received_events","type":"User","site_admin":false},"body":"It seems like using the FQDN here will be better than splitting, unless kerminator and the other tools are also splitting on `.` before locking (which they aren't). That way a user that locks pe-aix-53-builder.delivery.puppetlabs.net won't be surprised when their build gets clobbered.","created_at":"2015-11-19T17:42:05Z","updated_at":"2015-11-19T17:42:05Z","html_url":"https://github.com/puppetlabs/vanagon/pull/226#discussion_r45373817","pull_request_url":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226","_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/vanagon/pulls/comments/45373817"},"html":{"href":"https://github.com/puppetlabs/vanagon/pull/226#discussion_r45373817"},"pull_request":{"href":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226"}}},"pull_request":{"url":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226","id":51181781,"html_url":"https://github.com/puppetlabs/vanagon/pull/226","diff_url":"https://github.com/puppetlabs/vanagon/pull/226.diff","patch_url":"https://github.com/puppetlabs/vanagon/pull/226.patch","issue_url":"https://api.github.com/repos/puppetlabs/vanagon/issues/226","number":226,"state":"open","locked":false,"title":"Add Hardware engine to vanagon","user":{"login":"stahnma","id":6961,"avatar_url":"https://avatars.githubusercontent.com/u/6961?v=3","gravatar_id":"","url":"https://api.github.com/users/stahnma","html_url":"https://github.com/stahnma","followers_url":"https://api.github.com/users/stahnma/followers","following_url":"https://api.github.com/users/stahnma/following{/other_user}","gists_url":"https://api.github.com/users/stahnma/gists{/gist_id}","starred_url":"https://api.github.com/users/stahnma/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stahnma/subscriptions","organizations_url":"https://api.github.com/users/stahnma/orgs","repos_url":"https://api.github.com/users/stahnma/repos","events_url":"https://api.github.com/users/stahnma/events{/privacy}","received_events_url":"https://api.github.com/users/stahnma/received_events","type":"User","site_admin":false},"body":"(RE-5974) Vanagon should lock hardware when building\r\n\r\nIn the current build environment, vanagon can just trample any other\r\nbuild going on. This is bad. In the PE 2.y days, we built a crude\r\nlocking system for nodes. That system was improved a little bit to have\r\na kerminator (chatbot) interface.\r\n\r\nThis commit expands upon that by having vanagon lock a hardware node\r\nwhen the build starts and unlock it when it finishes. It also adds a new\r\nplatform dsl method around build_host. This allow for a hostname to be\r\nspecified in the platform definition instead of passing a build target\r\non the command line. This is how vanagon knows to use the hardware\r\nengine rather than just using base.\r\n\r\nDSL Example:\r\n\r\n    plat.build_host \"pe-aix-71-builder.delivery.puppetlabs.net\"\r\n\r\nThe engine will lock the node upon build invocation, if possible. If the\r\nnode is already locked, it will use a fibonacci backoff sequence to\r\nretry. Once the node is unlocked, it will acquire a lock and begin the\r\nbuild. One the build completes or fails, the lock is removed via the\r\nHardware engine's teardown method.\r\n\r\nThe engine also outputs and logs results of locks and unlock operations.\r\n\r\nExample build: (trimmed)\r\n\r\n    $ bundle exec build puppet-agent aix-7.1-ppc\r\n    Loading libxml2\r\n    ...\r\n    Hardware Locked: pe-aix-71-builder.delivery.puppetlabs.net\r\n    ...\r\n    mkdir -p output/aix/7.1/PC1/ppc\r\n    cp /var/tmp/tmp.vx9cWRlvoa/rpmbuild/*RPMS/**/*.rpm\r\n    ./output/aix/7.1/PC1/ppc\r\n    Removed hardware lock: pe-aix-71-builder.delivery.puppetlabs.net.\r\n\r\nvanagon_hosts.log\r\n\r\n    D, [2015-11-19T05:18:08.041680 #6902] DEBUG -- vanagon: Hardware engine invoked.\r\n    I, [2015-11-19T05:18:08.055747 #6902]  INFO -- vanagon: Hardware locked: pe-aix-71-builder.delivery.puppetlabs.net\r\n    I, [2015-11-19T05:18:16.727304 #6902]  INFO -- vanagon: Removed hardware lock: pe-aix-71-builder.delivery.puppetlabs.net.\r\n\r\n\r\n![](http://photon.101medialablimit.netdna-cdn.com/hypebeast.com/image/2015/06/the-ola-fingerprint-lock-is-the-latest-evolution-of-smart-locks-00.gif)\r\n","created_at":"2015-11-19T05:26:20Z","updated_at":"2015-11-19T17:42:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d71b8db73270ad03db2847b48224e694ead9f97f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226/commits","review_comments_url":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226/comments","review_comment_url":"https://api.github.com/repos/puppetlabs/vanagon/pulls/comments{/number}","comments_url":"https://api.github.com/repos/puppetlabs/vanagon/issues/226/comments","statuses_url":"https://api.github.com/repos/puppetlabs/vanagon/statuses/fac4910b173c810ec89c76642807d9c13d0c623b","head":{"label":"stahnma:hardware_locks","ref":"hardware_locks","sha":"fac4910b173c810ec89c76642807d9c13d0c623b","user":{"login":"stahnma","id":6961,"avatar_url":"https://avatars.githubusercontent.com/u/6961?v=3","gravatar_id":"","url":"https://api.github.com/users/stahnma","html_url":"https://github.com/stahnma","followers_url":"https://api.github.com/users/stahnma/followers","following_url":"https://api.github.com/users/stahnma/following{/other_user}","gists_url":"https://api.github.com/users/stahnma/gists{/gist_id}","starred_url":"https://api.github.com/users/stahnma/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stahnma/subscriptions","organizations_url":"https://api.github.com/users/stahnma/orgs","repos_url":"https://api.github.com/users/stahnma/repos","events_url":"https://api.github.com/users/stahnma/events{/privacy}","received_events_url":"https://api.github.com/users/stahnma/received_events","type":"User","site_admin":false},"repo":{"id":46469595,"name":"vanagon","full_name":"stahnma/vanagon","owner":{"login":"stahnma","id":6961,"avatar_url":"https://avatars.githubusercontent.com/u/6961?v=3","gravatar_id":"","url":"https://api.github.com/users/stahnma","html_url":"https://github.com/stahnma","followers_url":"https://api.github.com/users/stahnma/followers","following_url":"https://api.github.com/users/stahnma/following{/other_user}","gists_url":"https://api.github.com/users/stahnma/gists{/gist_id}","starred_url":"https://api.github.com/users/stahnma/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stahnma/subscriptions","organizations_url":"https://api.github.com/users/stahnma/orgs","repos_url":"https://api.github.com/users/stahnma/repos","events_url":"https://api.github.com/users/stahnma/events{/privacy}","received_events_url":"https://api.github.com/users/stahnma/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/stahnma/vanagon","description":"All of your packages will fit into this van with this one simple trick.","fork":true,"url":"https://api.github.com/repos/stahnma/vanagon","forks_url":"https://api.github.com/repos/stahnma/vanagon/forks","keys_url":"https://api.github.com/repos/stahnma/vanagon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/stahnma/vanagon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/stahnma/vanagon/teams","hooks_url":"https://api.github.com/repos/stahnma/vanagon/hooks","issue_events_url":"https://api.github.com/repos/stahnma/vanagon/issues/events{/number}","events_url":"https://api.github.com/repos/stahnma/vanagon/events","assignees_url":"https://api.github.com/repos/stahnma/vanagon/assignees{/user}","branches_url":"https://api.github.com/repos/stahnma/vanagon/branches{/branch}","tags_url":"https://api.github.com/repos/stahnma/vanagon/tags","blobs_url":"https://api.github.com/repos/stahnma/vanagon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/stahnma/vanagon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/stahnma/vanagon/git/refs{/sha}","trees_url":"https://api.github.com/repos/stahnma/vanagon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/stahnma/vanagon/statuses/{sha}","languages_url":"https://api.github.com/repos/stahnma/vanagon/languages","stargazers_url":"https://api.github.com/repos/stahnma/vanagon/stargazers","contributors_url":"https://api.github.com/repos/stahnma/vanagon/contributors","subscribers_url":"https://api.github.com/repos/stahnma/vanagon/subscribers","subscription_url":"https://api.github.com/repos/stahnma/vanagon/subscription","commits_url":"https://api.github.com/repos/stahnma/vanagon/commits{/sha}","git_commits_url":"https://api.github.com/repos/stahnma/vanagon/git/commits{/sha}","comments_url":"https://api.github.com/repos/stahnma/vanagon/comments{/number}","issue_comment_url":"https://api.github.com/repos/stahnma/vanagon/issues/comments{/number}","contents_url":"https://api.github.com/repos/stahnma/vanagon/contents/{+path}","compare_url":"https://api.github.com/repos/stahnma/vanagon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/stahnma/vanagon/merges","archive_url":"https://api.github.com/repos/stahnma/vanagon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/stahnma/vanagon/downloads","issues_url":"https://api.github.com/repos/stahnma/vanagon/issues{/number}","pulls_url":"https://api.github.com/repos/stahnma/vanagon/pulls{/number}","milestones_url":"https://api.github.com/repos/stahnma/vanagon/milestones{/number}","notifications_url":"https://api.github.com/repos/stahnma/vanagon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/stahnma/vanagon/labels{/name}","releases_url":"https://api.github.com/repos/stahnma/vanagon/releases{/id}","created_at":"2015-11-19T05:24:14Z","updated_at":"2015-11-19T05:24:14Z","pushed_at":"2015-11-19T17:37:51Z","git_url":"git://github.com/stahnma/vanagon.git","ssh_url":"git@github.com:stahnma/vanagon.git","clone_url":"https://github.com/stahnma/vanagon.git","svn_url":"https://github.com/stahnma/vanagon","homepage":null,"size":630,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"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":"puppetlabs:master","ref":"master","sha":"f87696e18d112861fd4a210d1be4ff0cd8e94824","user":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":26653553,"name":"vanagon","full_name":"puppetlabs/vanagon","owner":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/puppetlabs/vanagon","description":"All of your packages will fit into this van with this one simple trick.","fork":false,"url":"https://api.github.com/repos/puppetlabs/vanagon","forks_url":"https://api.github.com/repos/puppetlabs/vanagon/forks","keys_url":"https://api.github.com/repos/puppetlabs/vanagon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/puppetlabs/vanagon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/puppetlabs/vanagon/teams","hooks_url":"https://api.github.com/repos/puppetlabs/vanagon/hooks","issue_events_url":"https://api.github.com/repos/puppetlabs/vanagon/issues/events{/number}","events_url":"https://api.github.com/repos/puppetlabs/vanagon/events","assignees_url":"https://api.github.com/repos/puppetlabs/vanagon/assignees{/user}","branches_url":"https://api.github.com/repos/puppetlabs/vanagon/branches{/branch}","tags_url":"https://api.github.com/repos/puppetlabs/vanagon/tags","blobs_url":"https://api.github.com/repos/puppetlabs/vanagon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/puppetlabs/vanagon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/puppetlabs/vanagon/git/refs{/sha}","trees_url":"https://api.github.com/repos/puppetlabs/vanagon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/puppetlabs/vanagon/statuses/{sha}","languages_url":"https://api.github.com/repos/puppetlabs/vanagon/languages","stargazers_url":"https://api.github.com/repos/puppetlabs/vanagon/stargazers","contributors_url":"https://api.github.com/repos/puppetlabs/vanagon/contributors","subscribers_url":"https://api.github.com/repos/puppetlabs/vanagon/subscribers","subscription_url":"https://api.github.com/repos/puppetlabs/vanagon/subscription","commits_url":"https://api.github.com/repos/puppetlabs/vanagon/commits{/sha}","git_commits_url":"https://api.github.com/repos/puppetlabs/vanagon/git/commits{/sha}","comments_url":"https://api.github.com/repos/puppetlabs/vanagon/comments{/number}","issue_comment_url":"https://api.github.com/repos/puppetlabs/vanagon/issues/comments{/number}","contents_url":"https://api.github.com/repos/puppetlabs/vanagon/contents/{+path}","compare_url":"https://api.github.com/repos/puppetlabs/vanagon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/puppetlabs/vanagon/merges","archive_url":"https://api.github.com/repos/puppetlabs/vanagon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/puppetlabs/vanagon/downloads","issues_url":"https://api.github.com/repos/puppetlabs/vanagon/issues{/number}","pulls_url":"https://api.github.com/repos/puppetlabs/vanagon/pulls{/number}","milestones_url":"https://api.github.com/repos/puppetlabs/vanagon/milestones{/number}","notifications_url":"https://api.github.com/repos/puppetlabs/vanagon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/puppetlabs/vanagon/labels{/name}","releases_url":"https://api.github.com/repos/puppetlabs/vanagon/releases{/id}","created_at":"2014-11-14T19:17:18Z","updated_at":"2015-11-19T09:34:11Z","pushed_at":"2015-11-19T17:37:51Z","git_url":"git://github.com/puppetlabs/vanagon.git","ssh_url":"git@github.com:puppetlabs/vanagon.git","clone_url":"https://github.com/puppetlabs/vanagon.git","svn_url":"https://github.com/puppetlabs/vanagon","homepage":null,"size":725,"stargazers_count":9,"watchers_count":9,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":13,"mirror_url":null,"open_issues_count":2,"forks":13,"open_issues":2,"watchers":9,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226"},"html":{"href":"https://github.com/puppetlabs/vanagon/pull/226"},"issue":{"href":"https://api.github.com/repos/puppetlabs/vanagon/issues/226"},"comments":{"href":"https://api.github.com/repos/puppetlabs/vanagon/issues/226/comments"},"review_comments":{"href":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226/comments"},"review_comment":{"href":"https://api.github.com/repos/puppetlabs/vanagon/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/puppetlabs/vanagon/pulls/226/commits"},"statuses":{"href":"https://api.github.com/repos/puppetlabs/vanagon/statuses/fac4910b173c810ec89c76642807d9c13d0c623b"}}}}