{"action":"created","comment":{"url":"https://api.github.com/repos/digitalocean/go-qemu/pulls/comments/83992524","pull_request_review_id":4797938,"id":83992524,"diff_hunk":"@@ -0,0 +1,327 @@\n+// Copyright 2016 The go-qemu Authors.\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+package qmp\n+\n+import (\n+\t\"errors\"\n+\t\"log\"\n+\t\"os\"\n+\t\"sync\"\n+\t\"time\"\n+\n+\tlibvirt \"github.com/rgbkrk/libvirt-go\"\n+)\n+\n+// LibvirtGoEventsInterval constant used by the getPollInterval\n+// method.\n+const LibvirtGoEventsInterval = \"LIBVIRTGO_EVENTS_INTERVAL\"\n+\n+type libvirtGoMonitorLinux struct {\n+\tLibvirtGoMonitor\n+\tdomainName string\n+\tdomain     *libvirt.VirDomain\n+\turi        string\n+\tvirConn    *libvirt.VirConnection\n+\tonce       sync.Once\n+\tdoneChan   chan bool\n+\teventsChan chan Event\n+}\n+\n+// NewLibvirtGoMonitor configures a connection to the provided hypervisor\n+// and domain.\n+// An error is returned if the provided libvirt connection URI is invalid.\n+//\n+// Hypervisor URIs may be local or remote, e.g.,\n+//\tqemu:///system\n+//\tqemu+ssh://libvirt@example.com/system\n+func NewLibvirtGoMonitor(uri, domain string) Monitor {\n+\treturn &libvirtGoMonitorLinux{\n+\t\turi:        uri,\n+\t\tdomainName: domain,\n+\t}\n+}\n+\n+// Connect  sets up QEMU QMP connection via libvirt using\n+// the libvirt-go package.\n+// An error is returned if the libvirtd daemon is unreachable.\n+func (mon *libvirtGoMonitorLinux) Connect() error {\n+\n+\t// As per the libvirt core library:\n+\t// For proper event handling, it is important\n+\t// that the event implementation is registered\n+\t// before a connection to the Hypervisor is opened.\n+\t// We only do this once the first a Connect is called.\n+\tmon.once.Do(eventRegisterDefaultImpl)\n+\n+\t// Already connected?\n+\tif mon.virConn != nil {\n+\t\treturn nil\n+\t}\n+\n+\tvirConn, err := newVirConnectionInternal(mon.uri)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\tdomain, err := lookupDomainByName(&virConn, mon.domainName)\n+\tif err != nil {\n+\t\tcloseConnectionInternal(&virConn)\n+\t\treturn err\n+\t}\n+\n+\tmon.domain = &domain\n+\tmon.virConn = &virConn\n+\tmon.eventsChan = make(chan Event)\n+\tmon.doneChan = make(chan bool)\n+\n+\treturn err\n+}\n+\n+var newVirConnectionInternal = func(\n+\turi string) (libvirt.VirConnection, error) {\n+\treturn libvirt.NewVirConnection(uri)\n+}\n+\n+// Disconnect tears down open QMP socket connections.\n+func (mon *libvirtGoMonitorLinux) Disconnect() error {\n+\tvar err error\n+\tif mon.domain != nil {\n+\t\tmon.domain.Free()\n+\t\tmon.domain = nil\n+\t}\n+\n+\tif mon.virConn != nil {\n+\t\t_, err = closeConnectionInternal(mon.virConn)\n+\t\tmon.virConn = nil\n+\t\tclose(mon.doneChan)   // stop listenning to events\n+\t\tclose(mon.eventsChan) // stop sending events to clients\n+\t}\n+\n+\treturn err\n+}\n+\n+var closeConnectionInternal = func(\n+\tvirConn *libvirt.VirConnection) (int, error) {\n+\treturn virConn.CloseConnection()\n+}\n+\n+// Run executes the given QAPI command against a domain's QEMU instance.\n+// For a list of available QAPI commands, see:\n+//\thttp://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD\n+func (mon *libvirtGoMonitorLinux) Run(cmd []byte) ([]byte, error) {\n+\tif mon.virConn == nil {\n+\t\treturn nil, errors.New(\"Run() need a established connection to proceed.\")\n+\t}\n+\n+\tresult, err := qemuMonitorCommandInternal(mon.domain, string(cmd))\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\treturn []byte(result), nil\n+}\n+\n+var qemuMonitorCommandInternal = func(\n+\tdomain *libvirt.VirDomain, cmd string) (string, error) {\n+\treturn domain.QemuMonitorCommand(\n+\t\tlibvirt.VIR_DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT,\n+\t\tcmd)\n+}\n+\n+// Events streams QEMU QMP Events.\n+// If a problem is encountered setting up the event monitor connection\n+// an error will be returned. Errors encountered during streaming will\n+// cause the returned event channel to be closed.\n+func (mon *libvirtGoMonitorLinux) Events() (<-chan Event, error) {\n+\n+\tif mon.virConn == nil {\n+\t\treturn nil,\n+\t\t\terrors.New(\"Events() need a established connection to proceed.\")\n+\t}\n+\n+\tcallbackID, err := domainEventRegister(mon)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tgo pollEventsLoop(mon.doneChan)\n+\n+\tgo domainEventDeregister(mon, callbackID)\n+\n+\treturn mon.eventsChan, nil\n+}\n+\n+var lookupDomainByName = func(\n+\tvirConn *libvirt.VirConnection,\n+\tdomainName string) (libvirt.VirDomain, error) {\n+\treturn virConn.LookupDomainByName(domainName)\n+}\n+\n+// eventRegisterDefaultImpl registers a default event implementation.\n+func eventRegisterDefaultImpl() {\n+\teventRegisterID := eventRegisterDefaultImplInternal()\n+\tif eventRegisterID == -1 {\n+\t\tlog.Printf(\n+\t\t\t\"EventRegisterDefaultImpl returned an unexpected value %d\\n\",\n+\t\t\teventRegisterID)\n+\t\t//TODO: panic or what???\n+\t}\n+}\n+\n+var eventRegisterDefaultImplInternal = func() int {\n+\treturn libvirt.EventRegisterDefaultImpl()\n+}\n+\n+// domainEventRegister register with libvirt to receive events for the\n+// specified domain.\n+func domainEventRegister(mon *libvirtGoMonitorLinux) (int, error) {\n+\tcallback :=\n+\t\tlibvirt.DomainEventCallback(newEventCallback(mon))\n+\n+\t//TODO: add ability to register for more event types\n+\tcallbackID := domainEventRegisterInternal(\n+\t\tmon,\n+\t\t&callback,\n+\t\tfunc() {\n+\t\t\t// empty on purpose until it's decided\n+\t\t\t// what to do here.\n+\t\t},\n+\t)\n+\tif callbackID == -1 {\n+\t\treturn -1, errors.New(\"Domain event registration failed!\")\n+\t}\n+\n+\treturn callbackID, nil\n+}\n+\n+var domainEventRegisterInternal = func(\n+\tmon *libvirtGoMonitorLinux,\n+\tcallback *libvirt.DomainEventCallback,\n+\tfn func()) int {\n+\treturn mon.virConn.DomainEventRegister(\n+\t\t*mon.domain,\n+\t\tlibvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,\n+\t\tcallback,\n+\t\tfn,\n+\t)\n+}\n+\n+// domainEventDeregister stops the registration with libvirt from receiving\n+// events for the specified domain.\n+func domainEventDeregister(\n+\tmon *libvirtGoMonitorLinux,\n+\tcallbackID int) {\n+\t<-mon.doneChan\n+\tret := domainEventDeregisterInternal(mon.virConn, callbackID)\n+\tif ret != 0 {\n+\t\tlog.Printf(\"DomainEventDeregister returned an unexpected value: %d\\n\",\n+\t\t\tret)\n+\t}\n+}\n+\n+var domainEventDeregisterInternal = func(virConn *libvirt.VirConnection,\n+\tcallbackID int) int {\n+\treturn virConn.DomainEventDeregister(callbackID)\n+}\n+\n+// newEventCallback convenient function to provide access\n+// to the eventChan to the returned closure/callback.\n+func newEventCallback(mon *libvirtGoMonitorLinux) libvirt.DomainEventCallback {\n+\treturn func(c *libvirt.VirConnection,\n+\t\td *libvirt.VirDomain,\n+\t\teventDetails interface{}, f func()) int {\n+\n+\t\t// if monitor is not connected,\n+\t\t// we should not continue processing messages\n+\t\t// as the mon.eventsChan will be closed.\n+\t\tif mon.virConn == nil {\n+\t\t\treturn 0\n+\t\t}\n+\n+\t\t// We only support lifecycleEvents for now\n+\t\tif lifecycleEvent, ok :=\n+\t\t\teventDetails.(libvirt.DomainLifecycleEvent); ok {\n+\t\t\tmon.eventsChan <- constructEvent(lifecycleEvent)\n+\t\t\tf()\n+\t\t}\n+\n+\t\t// according to the libvirt-do\n+\t\t// the return code is ignored\n+\t\treturn 0\n+\t}\n+}\n+\n+// pollEventsLoop keeps polling libvirt for new domain events\n+func pollEventsLoop(doneChan chan bool) {\n+\tcheckInterval := time.Tick(getPollInterval())\n+\tfor {\n+\t\tselect {\n+\t\tcase <-doneChan: // stop polling for events\n+\t\t\treturn\n+\t\tcase <-checkInterval:\n+\t\t\tret := eventRunDefaultImplInternal()\n+\t\t\tif ret == -1 {\n+\t\t\t\tdoneChan <- true\n+\t\t\t\treturn\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+var eventRunDefaultImplInternal = func() int {\n+\treturn libvirt.EventRunDefaultImpl()\n+}\n+\n+// getPollInterval retreives the events poll interval from the\n+// LIBVIRTGO_EVENTS_INTERVAL environment variable. Defaults to 1s.\n+func getPollInterval() time.Duration {\n+\tintervalStr := os.Getenv(LibvirtGoEventsInterval)\n+\tinterval, _ := time.ParseDuration(\"1s\")\n+\tif intervalStr != \"\" {\n+\t\tdesiredInterval, err := time.ParseDuration(intervalStr)\n+\t\tif err != nil {\n+\t\t\tlog.Printf(\n+\t\t\t\t\"Unable value specified in 'LIBVIRTGO_EVENTS_INTERVAL': %v\\n\",\n+\t\t\t\terr)\n+\t\t\treturn interval\n+\t\t}\n+\t\tinterval = desiredInterval\n+\t}\n+\treturn interval\n+}\n+\n+// constructEvent helper function to map DomainLifecycleEvent\n+// into Event.\n+func constructEvent(eventDetails libvirt.DomainLifecycleEvent) Event {\n+\t// This timestamp represents the moment in time when\n+\t// the event was received on this end and not when it\n+\t// actually occurred.\n+\tnow := time.Now()\n+\ttype TimeStamp struct {\n+\t\tSeconds      int64 `json:\"seconds\"`\n+\t\tMicroseconds int64 `json:\"microseconds\"`\n+\t}\n+\ttimestamp := TimeStamp{\n+\t\tint64(now.Second()),\n+\t\tint64(now.Second() / int(time.Microsecond)),","path":"qmp/libvirtgo_linux.go","position":318,"original_position":318,"commit_id":"4838752df5c5365cae86c5e471449164a588f2ef","original_commit_id":"4838752df5c5365cae86c5e471449164a588f2ef","user":{"login":"mdlayher","id":1926905,"avatar_url":"https://avatars.githubusercontent.com/u/1926905?v=3","gravatar_id":"","url":"https://api.github.com/users/mdlayher","html_url":"https://github.com/mdlayher","followers_url":"https://api.github.com/users/mdlayher/followers","following_url":"https://api.github.com/users/mdlayher/following{/other_user}","gists_url":"https://api.github.com/users/mdlayher/gists{/gist_id}","starred_url":"https://api.github.com/users/mdlayher/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdlayher/subscriptions","organizations_url":"https://api.github.com/users/mdlayher/orgs","repos_url":"https://api.github.com/users/mdlayher/repos","events_url":"https://api.github.com/users/mdlayher/events{/privacy}","received_events_url":"https://api.github.com/users/mdlayher/received_events","type":"User","site_admin":false},"body":"Used keyed struct literals.","created_at":"2016-10-19T03:33:48Z","updated_at":"2016-10-19T03:33:48Z","html_url":"https://github.com/digitalocean/go-qemu/pull/129#discussion_r83992524","pull_request_url":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129","_links":{"self":{"href":"https://api.github.com/repos/digitalocean/go-qemu/pulls/comments/83992524"},"html":{"href":"https://github.com/digitalocean/go-qemu/pull/129#discussion_r83992524"},"pull_request":{"href":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129"}}},"pull_request":{"url":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129","id":89918067,"html_url":"https://github.com/digitalocean/go-qemu/pull/129","diff_url":"https://github.com/digitalocean/go-qemu/pull/129.diff","patch_url":"https://github.com/digitalocean/go-qemu/pull/129.patch","issue_url":"https://api.github.com/repos/digitalocean/go-qemu/issues/129","number":129,"state":"open","locked":false,"title":"Issue 30","user":{"login":"robertojrojas","id":2787728,"avatar_url":"https://avatars.githubusercontent.com/u/2787728?v=3","gravatar_id":"","url":"https://api.github.com/users/robertojrojas","html_url":"https://github.com/robertojrojas","followers_url":"https://api.github.com/users/robertojrojas/followers","following_url":"https://api.github.com/users/robertojrojas/following{/other_user}","gists_url":"https://api.github.com/users/robertojrojas/gists{/gist_id}","starred_url":"https://api.github.com/users/robertojrojas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robertojrojas/subscriptions","organizations_url":"https://api.github.com/users/robertojrojas/orgs","repos_url":"https://api.github.com/users/robertojrojas/repos","events_url":"https://api.github.com/users/robertojrojas/events{/privacy}","received_events_url":"https://api.github.com/users/robertojrojas/received_events","type":"User","site_admin":false},"body":"Here is one implementation of the Monitor using the https://github.com/rgbkrk/libvirt-go package. \r\nLet me know if you there is anything you would like me to change.","created_at":"2016-10-18T23:35:05Z","updated_at":"2016-10-19T03:36:13Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4b9ffc0279fa512515a15bf7fc15ff0d11a4b439","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129/commits","review_comments_url":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129/comments","review_comment_url":"https://api.github.com/repos/digitalocean/go-qemu/pulls/comments{/number}","comments_url":"https://api.github.com/repos/digitalocean/go-qemu/issues/129/comments","statuses_url":"https://api.github.com/repos/digitalocean/go-qemu/statuses/4838752df5c5365cae86c5e471449164a588f2ef","head":{"label":"robertojrojas:issue_30","ref":"issue_30","sha":"4838752df5c5365cae86c5e471449164a588f2ef","user":{"login":"robertojrojas","id":2787728,"avatar_url":"https://avatars.githubusercontent.com/u/2787728?v=3","gravatar_id":"","url":"https://api.github.com/users/robertojrojas","html_url":"https://github.com/robertojrojas","followers_url":"https://api.github.com/users/robertojrojas/followers","following_url":"https://api.github.com/users/robertojrojas/following{/other_user}","gists_url":"https://api.github.com/users/robertojrojas/gists{/gist_id}","starred_url":"https://api.github.com/users/robertojrojas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robertojrojas/subscriptions","organizations_url":"https://api.github.com/users/robertojrojas/orgs","repos_url":"https://api.github.com/users/robertojrojas/repos","events_url":"https://api.github.com/users/robertojrojas/events{/privacy}","received_events_url":"https://api.github.com/users/robertojrojas/received_events","type":"User","site_admin":false},"repo":{"id":70205463,"name":"go-qemu","full_name":"robertojrojas/go-qemu","owner":{"login":"robertojrojas","id":2787728,"avatar_url":"https://avatars.githubusercontent.com/u/2787728?v=3","gravatar_id":"","url":"https://api.github.com/users/robertojrojas","html_url":"https://github.com/robertojrojas","followers_url":"https://api.github.com/users/robertojrojas/followers","following_url":"https://api.github.com/users/robertojrojas/following{/other_user}","gists_url":"https://api.github.com/users/robertojrojas/gists{/gist_id}","starred_url":"https://api.github.com/users/robertojrojas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robertojrojas/subscriptions","organizations_url":"https://api.github.com/users/robertojrojas/orgs","repos_url":"https://api.github.com/users/robertojrojas/repos","events_url":"https://api.github.com/users/robertojrojas/events{/privacy}","received_events_url":"https://api.github.com/users/robertojrojas/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/robertojrojas/go-qemu","description":"Go packages to interact with QEMU using the QEMU Machine Protocol (QMP).  Apache 2.0 Licensed.","fork":true,"url":"https://api.github.com/repos/robertojrojas/go-qemu","forks_url":"https://api.github.com/repos/robertojrojas/go-qemu/forks","keys_url":"https://api.github.com/repos/robertojrojas/go-qemu/keys{/key_id}","collaborators_url":"https://api.github.com/repos/robertojrojas/go-qemu/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/robertojrojas/go-qemu/teams","hooks_url":"https://api.github.com/repos/robertojrojas/go-qemu/hooks","issue_events_url":"https://api.github.com/repos/robertojrojas/go-qemu/issues/events{/number}","events_url":"https://api.github.com/repos/robertojrojas/go-qemu/events","assignees_url":"https://api.github.com/repos/robertojrojas/go-qemu/assignees{/user}","branches_url":"https://api.github.com/repos/robertojrojas/go-qemu/branches{/branch}","tags_url":"https://api.github.com/repos/robertojrojas/go-qemu/tags","blobs_url":"https://api.github.com/repos/robertojrojas/go-qemu/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/robertojrojas/go-qemu/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/robertojrojas/go-qemu/git/refs{/sha}","trees_url":"https://api.github.com/repos/robertojrojas/go-qemu/git/trees{/sha}","statuses_url":"https://api.github.com/repos/robertojrojas/go-qemu/statuses/{sha}","languages_url":"https://api.github.com/repos/robertojrojas/go-qemu/languages","stargazers_url":"https://api.github.com/repos/robertojrojas/go-qemu/stargazers","contributors_url":"https://api.github.com/repos/robertojrojas/go-qemu/contributors","subscribers_url":"https://api.github.com/repos/robertojrojas/go-qemu/subscribers","subscription_url":"https://api.github.com/repos/robertojrojas/go-qemu/subscription","commits_url":"https://api.github.com/repos/robertojrojas/go-qemu/commits{/sha}","git_commits_url":"https://api.github.com/repos/robertojrojas/go-qemu/git/commits{/sha}","comments_url":"https://api.github.com/repos/robertojrojas/go-qemu/comments{/number}","issue_comment_url":"https://api.github.com/repos/robertojrojas/go-qemu/issues/comments{/number}","contents_url":"https://api.github.com/repos/robertojrojas/go-qemu/contents/{+path}","compare_url":"https://api.github.com/repos/robertojrojas/go-qemu/compare/{base}...{head}","merges_url":"https://api.github.com/repos/robertojrojas/go-qemu/merges","archive_url":"https://api.github.com/repos/robertojrojas/go-qemu/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/robertojrojas/go-qemu/downloads","issues_url":"https://api.github.com/repos/robertojrojas/go-qemu/issues{/number}","pulls_url":"https://api.github.com/repos/robertojrojas/go-qemu/pulls{/number}","milestones_url":"https://api.github.com/repos/robertojrojas/go-qemu/milestones{/number}","notifications_url":"https://api.github.com/repos/robertojrojas/go-qemu/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/robertojrojas/go-qemu/labels{/name}","releases_url":"https://api.github.com/repos/robertojrojas/go-qemu/releases{/id}","deployments_url":"https://api.github.com/repos/robertojrojas/go-qemu/deployments","created_at":"2016-10-07T01:08:51Z","updated_at":"2016-10-07T01:08:52Z","pushed_at":"2016-10-18T23:29:32Z","git_url":"git://github.com/robertojrojas/go-qemu.git","ssh_url":"git@github.com:robertojrojas/go-qemu.git","clone_url":"https://github.com/robertojrojas/go-qemu.git","svn_url":"https://github.com/robertojrojas/go-qemu","homepage":null,"size":200,"stargazers_count":0,"watchers_count":0,"language":"Go","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":"digitalocean:master","ref":"master","sha":"8eb38f26928d2d6656c316122a6374863d4aca67","user":{"login":"digitalocean","id":4650108,"avatar_url":"https://avatars.githubusercontent.com/u/4650108?v=3","gravatar_id":"","url":"https://api.github.com/users/digitalocean","html_url":"https://github.com/digitalocean","followers_url":"https://api.github.com/users/digitalocean/followers","following_url":"https://api.github.com/users/digitalocean/following{/other_user}","gists_url":"https://api.github.com/users/digitalocean/gists{/gist_id}","starred_url":"https://api.github.com/users/digitalocean/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/digitalocean/subscriptions","organizations_url":"https://api.github.com/users/digitalocean/orgs","repos_url":"https://api.github.com/users/digitalocean/repos","events_url":"https://api.github.com/users/digitalocean/events{/privacy}","received_events_url":"https://api.github.com/users/digitalocean/received_events","type":"Organization","site_admin":false},"repo":{"id":57146365,"name":"go-qemu","full_name":"digitalocean/go-qemu","owner":{"login":"digitalocean","id":4650108,"avatar_url":"https://avatars.githubusercontent.com/u/4650108?v=3","gravatar_id":"","url":"https://api.github.com/users/digitalocean","html_url":"https://github.com/digitalocean","followers_url":"https://api.github.com/users/digitalocean/followers","following_url":"https://api.github.com/users/digitalocean/following{/other_user}","gists_url":"https://api.github.com/users/digitalocean/gists{/gist_id}","starred_url":"https://api.github.com/users/digitalocean/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/digitalocean/subscriptions","organizations_url":"https://api.github.com/users/digitalocean/orgs","repos_url":"https://api.github.com/users/digitalocean/repos","events_url":"https://api.github.com/users/digitalocean/events{/privacy}","received_events_url":"https://api.github.com/users/digitalocean/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/digitalocean/go-qemu","description":"Go packages to interact with QEMU using the QEMU Machine Protocol (QMP).  Apache 2.0 Licensed.","fork":false,"url":"https://api.github.com/repos/digitalocean/go-qemu","forks_url":"https://api.github.com/repos/digitalocean/go-qemu/forks","keys_url":"https://api.github.com/repos/digitalocean/go-qemu/keys{/key_id}","collaborators_url":"https://api.github.com/repos/digitalocean/go-qemu/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/digitalocean/go-qemu/teams","hooks_url":"https://api.github.com/repos/digitalocean/go-qemu/hooks","issue_events_url":"https://api.github.com/repos/digitalocean/go-qemu/issues/events{/number}","events_url":"https://api.github.com/repos/digitalocean/go-qemu/events","assignees_url":"https://api.github.com/repos/digitalocean/go-qemu/assignees{/user}","branches_url":"https://api.github.com/repos/digitalocean/go-qemu/branches{/branch}","tags_url":"https://api.github.com/repos/digitalocean/go-qemu/tags","blobs_url":"https://api.github.com/repos/digitalocean/go-qemu/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/digitalocean/go-qemu/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/digitalocean/go-qemu/git/refs{/sha}","trees_url":"https://api.github.com/repos/digitalocean/go-qemu/git/trees{/sha}","statuses_url":"https://api.github.com/repos/digitalocean/go-qemu/statuses/{sha}","languages_url":"https://api.github.com/repos/digitalocean/go-qemu/languages","stargazers_url":"https://api.github.com/repos/digitalocean/go-qemu/stargazers","contributors_url":"https://api.github.com/repos/digitalocean/go-qemu/contributors","subscribers_url":"https://api.github.com/repos/digitalocean/go-qemu/subscribers","subscription_url":"https://api.github.com/repos/digitalocean/go-qemu/subscription","commits_url":"https://api.github.com/repos/digitalocean/go-qemu/commits{/sha}","git_commits_url":"https://api.github.com/repos/digitalocean/go-qemu/git/commits{/sha}","comments_url":"https://api.github.com/repos/digitalocean/go-qemu/comments{/number}","issue_comment_url":"https://api.github.com/repos/digitalocean/go-qemu/issues/comments{/number}","contents_url":"https://api.github.com/repos/digitalocean/go-qemu/contents/{+path}","compare_url":"https://api.github.com/repos/digitalocean/go-qemu/compare/{base}...{head}","merges_url":"https://api.github.com/repos/digitalocean/go-qemu/merges","archive_url":"https://api.github.com/repos/digitalocean/go-qemu/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/digitalocean/go-qemu/downloads","issues_url":"https://api.github.com/repos/digitalocean/go-qemu/issues{/number}","pulls_url":"https://api.github.com/repos/digitalocean/go-qemu/pulls{/number}","milestones_url":"https://api.github.com/repos/digitalocean/go-qemu/milestones{/number}","notifications_url":"https://api.github.com/repos/digitalocean/go-qemu/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/digitalocean/go-qemu/labels{/name}","releases_url":"https://api.github.com/repos/digitalocean/go-qemu/releases{/id}","deployments_url":"https://api.github.com/repos/digitalocean/go-qemu/deployments","created_at":"2016-04-26T16:58:05Z","updated_at":"2016-10-19T00:06:46Z","pushed_at":"2016-10-18T23:35:05Z","git_url":"git://github.com/digitalocean/go-qemu.git","ssh_url":"git@github.com:digitalocean/go-qemu.git","clone_url":"https://github.com/digitalocean/go-qemu.git","svn_url":"https://github.com/digitalocean/go-qemu","homepage":null,"size":362,"stargazers_count":97,"watchers_count":97,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":8,"mirror_url":null,"open_issues_count":8,"forks":8,"open_issues":8,"watchers":97,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129"},"html":{"href":"https://github.com/digitalocean/go-qemu/pull/129"},"issue":{"href":"https://api.github.com/repos/digitalocean/go-qemu/issues/129"},"comments":{"href":"https://api.github.com/repos/digitalocean/go-qemu/issues/129/comments"},"review_comments":{"href":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129/comments"},"review_comment":{"href":"https://api.github.com/repos/digitalocean/go-qemu/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/digitalocean/go-qemu/pulls/129/commits"},"statuses":{"href":"https://api.github.com/repos/digitalocean/go-qemu/statuses/4838752df5c5365cae86c5e471449164a588f2ef"}}}}
{"actor":{"display_login":"mdlayher"}}