{"action":"created","comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/comments/31752818","id":31752818,"diff_hunk":"@@ -0,0 +1,211 @@\n+# Copyright 2015 Google Inc. All rights reserved.\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+\"\"\"Class to represent a DigitalOcean Virtual Machine object (Droplet).\n+\"\"\"\n+\n+import json\n+import time\n+\n+from perfkitbenchmarker import disk\n+from perfkitbenchmarker import errors\n+from perfkitbenchmarker import flags\n+from perfkitbenchmarker import package_managers\n+from perfkitbenchmarker import virtual_machine\n+from perfkitbenchmarker import vm_util\n+from perfkitbenchmarker.digitalocean import digitalocean_disk\n+from perfkitbenchmarker.digitalocean import util\n+\n+FLAGS = flags.FLAGS\n+\n+CLOUD_CONFIG_TEMPLATE = '''#cloud-config\n+users:\n+  - name: {0}\n+    ssh-authorized-keys:\n+      - {1}\n+    sudo: ['ALL=(ALL) NOPASSWD:ALL']\n+    groups: sudo\n+    shell: /bin/bash\n+'''\n+\n+class DigitaloceanVirtualMachine(virtual_machine.BaseVirtualMachine):\n+  \"\"\"Object representing a DigitalOcean Virtual Machine (Droplet).\"\"\"\n+\n+  def __init__(self, vm_spec):\n+    \"\"\"Initialize a DigitalOcean virtual machine.\n+\n+    Args:\n+      vm_spec: virtual_machine.BaseVirtualMachineSpec object of the vm.\n+    \"\"\"\n+    super(DigitaloceanVirtualMachine, self).__init__(vm_spec)\n+    self.droplet_id = None\n+    self.max_local_disks = 1\n+    self.local_disk_counter = 0\n+\n+  def _CreateDependencies(self):\n+    \"\"\"Create VM dependencies.\"\"\"\n+    pass\n+\n+  def _DeleteDependencies(self):\n+    \"\"\"Delete VM dependencies.\"\"\"\n+    pass\n+\n+  def _Create(self):\n+    \"\"\"Create a DigitalOcean VM instance (droplet).\"\"\"\n+    super(DigitaloceanVirtualMachine, self)._Create()\n+    with open(self.ssh_public_key) as f:\n+      public_key = f.read().rstrip('\\n')\n+\n+    stdout, ret = util.RunCurlCommand(\n+        'POST', 'droplets', {\n+            'name': self.name,\n+            'region': self.zone,\n+            'size': self.machine_type,\n+            'image': self.image,\n+            'backups': False,\n+            'ipv6': False,\n+            'ssh_keys': [],\n+            'user_data': CLOUD_CONFIG_TEMPLATE.format(\n+                self.user_name, public_key)\n+            })\n+    if ret != 0:\n+      raise errors.Error('Creation failed: %s' % stdout)\n+    response = json.loads(stdout)\n+    self.droplet_id = response['droplet']['id']\n+\n+    # The freshly created droplet will be in a locked and unusable\n+    # state for a while, and it cannot be deleted or modified in\n+    # this state. Wait for the action to finish and check the\n+    # reported result.\n+    if not self._GetActionResult(response['links']['actions'][0]['id']):\n+      raise errors.Resource.RetryableCreationError('Creation failed.')\n+\n+  def _GetActionResult(self, action_id, wait_seconds=10, max_tries=30):\n+    \"\"\"Wait until a VM action completes.\"\"\"\n+    for _ in xrange(max_tries):\n+      time.sleep(wait_seconds)\n+      stdout, ret = util.RunCurlCommand('GET', 'actions/%s' % action_id)\n+      if ret != 0:\n+        raise errors.Error('Unexpected action failure: %s' % stdout)\n+      response = json.loads(stdout)\n+      status = response['action']['status']\n+      if status == 'completed':\n+        return True\n+      elif status == 'errored':\n+        return False\n+    return False  # Timeout, treat as failure.\n+\n+  @vm_util.Retry()\n+  def _PostCreate(self):\n+    \"\"\"Get the instance's data.\"\"\"\n+    stdout, _ = util.RunCurlCommand(\n+        'GET', 'droplets/%s' % self.droplet_id)\n+    response = json.loads(stdout)['droplet']\n+    network_interface = response['networks']['v4'][0]\n+    # Not currently using private addresses. Do we need to?\n+    self.internal_ip = network_interface['ip_address']\n+    self.ip_address = network_interface['ip_address']\n+\n+  @vm_util.Retry()","path":"perfkitbenchmarker/digitalocean/digitalocean_virtual_machine.py","position":119,"original_position":119,"commit_id":"c0d78eda37bf1dede01a29609f1b510db194d01d","original_commit_id":"c0d78eda37bf1dede01a29609f1b510db194d01d","user":{"login":"ehankland","id":8193699,"avatar_url":"https://avatars.githubusercontent.com/u/8193699?v=3","gravatar_id":"","url":"https://api.github.com/users/ehankland","html_url":"https://github.com/ehankland","followers_url":"https://api.github.com/users/ehankland/followers","following_url":"https://api.github.com/users/ehankland/following{/other_user}","gists_url":"https://api.github.com/users/ehankland/gists{/gist_id}","starred_url":"https://api.github.com/users/ehankland/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehankland/subscriptions","organizations_url":"https://api.github.com/users/ehankland/orgs","repos_url":"https://api.github.com/users/ehankland/repos","events_url":"https://api.github.com/users/ehankland/events{/privacy}","received_events_url":"https://api.github.com/users/ehankland/received_events","type":"User","site_admin":false},"body":"Do you need the retry around this function? If deleting a VM that doesn't exist any more is an error (non zero retcode), you'll get stuck in a loop until the retry timeout.","created_at":"2015-06-04T18:52:58Z","updated_at":"2015-06-04T18:52:58Z","html_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/pull/291#discussion_r31752818","pull_request_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291","_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/comments/31752818"},"html":{"href":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/pull/291#discussion_r31752818"},"pull_request":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291"}}},"pull_request":{"url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291","id":36891704,"html_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/pull/291","diff_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/pull/291.diff","patch_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/pull/291.patch","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/291","number":291,"state":"open","locked":false,"title":"pkb: Add DigitalOcean cloud support.","user":{"login":"klausw","id":1392351,"avatar_url":"https://avatars.githubusercontent.com/u/1392351?v=3","gravatar_id":"","url":"https://api.github.com/users/klausw","html_url":"https://github.com/klausw","followers_url":"https://api.github.com/users/klausw/followers","following_url":"https://api.github.com/users/klausw/following{/other_user}","gists_url":"https://api.github.com/users/klausw/gists{/gist_id}","starred_url":"https://api.github.com/users/klausw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klausw/subscriptions","organizations_url":"https://api.github.com/users/klausw/orgs","repos_url":"https://api.github.com/users/klausw/repos","events_url":"https://api.github.com/users/klausw/events{/privacy}","received_events_url":"https://api.github.com/users/klausw/received_events","type":"User","site_admin":false},"body":"Add initial support for DigitalOcean as a cloud provider.\r\n\r\nThis uses the `curl` tool to access the DigitalOcean v2 API. You must set\r\n up authentication before use, see README.md for instructions.\r\n\r\nSince DigitalOcean does not provide add-on disks, droplets always use local\r\nSSD storage as mounted on a single root partition, and AFAIK this cannot be\r\nrepartitioned. Benchmarks that request a data directory via vm.GetScratchDir()\r\nwill use a subdirectory of the root partition.\r\n\r\nBenchmarks that need multiple scratch disks or raw devices are **NOT**\r\nsupported and will fail to run in such configurations. This includes\r\n*copy_throughput* in disk-to-disk mode, or *aerospike* when using\r\nnon-memory storage modes.\r\n\r\nUsage example:\r\n\r\n```\r\n./pkb.py --cloud=DigitalOcean --machine_type=16gb --benchmarks=iperf\r\n```\r\n\r\nWorking benchmarks on a 16gb VM (droplet):\r\n\r\n* aerospike, block_storage_workload, bonnie++, cassandra_stress,\r\n  cluster_boot, coremark, fio, hpcc, iperf, mesh_network, mongodb, netperf,\r\n  oldisim, ping, redis, scimark2, silo, sysbench_oltp, unixbench\r\n\r\nTest in progress:\r\n\r\n* speccpu2006\r\n\r\nNot yet tested:\r\n\r\n* hadoop_terasort, hbase_ycsb\r\n\r\nUnsupported benchmarks:\r\n\r\n* _copy_throughput:_ this needs multiple scratch disks.\r\n* _object_storage_service:_ DigitalOcean doesn't offer an object store.\r\n  It should work to run the benchmark using an external object store\r\n  provider, I haven't tested that.","created_at":"2015-06-04T00:17:07Z","updated_at":"2015-06-04T18:52:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8b06525854ee0945bdb3aa8885711a02daee1b00","assignee":{"login":"ehankland","id":8193699,"avatar_url":"https://avatars.githubusercontent.com/u/8193699?v=3","gravatar_id":"","url":"https://api.github.com/users/ehankland","html_url":"https://github.com/ehankland","followers_url":"https://api.github.com/users/ehankland/followers","following_url":"https://api.github.com/users/ehankland/following{/other_user}","gists_url":"https://api.github.com/users/ehankland/gists{/gist_id}","starred_url":"https://api.github.com/users/ehankland/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehankland/subscriptions","organizations_url":"https://api.github.com/users/ehankland/orgs","repos_url":"https://api.github.com/users/ehankland/repos","events_url":"https://api.github.com/users/ehankland/events{/privacy}","received_events_url":"https://api.github.com/users/ehankland/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291/commits","review_comments_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291/comments","review_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/comments{/number}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/291/comments","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/statuses/c0d78eda37bf1dede01a29609f1b510db194d01d","head":{"label":"GoogleCloudPlatform:dev-klausw-do","ref":"dev-klausw-do","sha":"c0d78eda37bf1dede01a29609f1b510db194d01d","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":21950910,"name":"PerfKitBenchmarker","full_name":"GoogleCloudPlatform/PerfKitBenchmarker","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker","description":"Perfkit Benchmarker contains set of benchmarks to measure and compare cloud offerings. The benchmarks are not tuned (i.e. use defaults) to reflect what most users will see. PerfKit Benchmarker is licensed under the Apache 2 license terms. Please make sure to read, understand and agree to the terms of the LICENSE and CONTRIBUTING files before proceeding.","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/releases{/id}","created_at":"2014-07-17T17:23:26Z","updated_at":"2015-06-02T15:15:00Z","pushed_at":"2015-06-04T16:49:40Z","git_url":"git://github.com/GoogleCloudPlatform/PerfKitBenchmarker.git","ssh_url":"git@github.com:GoogleCloudPlatform/PerfKitBenchmarker.git","clone_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker.git","svn_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker","homepage":"","size":153011,"stargazers_count":447,"watchers_count":447,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":52,"mirror_url":null,"open_issues_count":69,"forks":52,"open_issues":69,"watchers":447,"default_branch":"master"}},"base":{"label":"GoogleCloudPlatform:dev","ref":"dev","sha":"97345c53631d3971a052747bdb4c201eaf160d5a","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":21950910,"name":"PerfKitBenchmarker","full_name":"GoogleCloudPlatform/PerfKitBenchmarker","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker","description":"Perfkit Benchmarker contains set of benchmarks to measure and compare cloud offerings. The benchmarks are not tuned (i.e. use defaults) to reflect what most users will see. PerfKit Benchmarker is licensed under the Apache 2 license terms. Please make sure to read, understand and agree to the terms of the LICENSE and CONTRIBUTING files before proceeding.","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/releases{/id}","created_at":"2014-07-17T17:23:26Z","updated_at":"2015-06-02T15:15:00Z","pushed_at":"2015-06-04T16:49:40Z","git_url":"git://github.com/GoogleCloudPlatform/PerfKitBenchmarker.git","ssh_url":"git@github.com:GoogleCloudPlatform/PerfKitBenchmarker.git","clone_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker.git","svn_url":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker","homepage":"","size":153011,"stargazers_count":447,"watchers_count":447,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":52,"mirror_url":null,"open_issues_count":69,"forks":52,"open_issues":69,"watchers":447,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291"},"html":{"href":"https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/pull/291"},"issue":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/291"},"comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/issues/291/comments"},"review_comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291/comments"},"review_comment":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/pulls/291/commits"},"statuses":{"href":"https://api.github.com/repos/GoogleCloudPlatform/PerfKitBenchmarker/statuses/c0d78eda37bf1dede01a29609f1b510db194d01d"}}}}