{"action":"created","comment":{"url":"https://api.github.com/repos/kubernetes/kubernetes/pulls/comments/38035469","id":38035469,"diff_hunk":"@@ -763,3 +767,157 @@ func (os *OpenStack) GetZone() (cloudprovider.Zone, error) {\n func (os *OpenStack) Routes() (cloudprovider.Routes, bool) {\n \treturn nil, false\n }\n+\n+// Attaches given cinder volume to the compute running kubelet\n+func (os *OpenStack) AttachDisk(diskName string) (string, error) {\n+\tdisk, err := os.getVolume(diskName)\n+\tif err != nil {\n+\t\treturn \"\", err\n+\t}\n+\tcClient, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{\n+\t\tRegion: os.region,\n+\t})\n+\tif err != nil || cClient == nil {\n+\t\tglog.Errorf(\"Unable to initialize nova client for region: %s\", os.region)\n+\t\treturn \"\", err\n+\t}\n+\tcompute_id, err := os.getComputeIDbyHostname(cClient)\n+\tif err != nil || len(compute_id) == 0 {\n+\t\tglog.Errorf(\"Unable to get minion's id by minion's hostname\")\n+\t\treturn \"\", err\n+\t}\n+\n+\tif len(disk.Attachments) > 0 && disk.Attachments[0][\"server_id\"] != nil {\n+\t\tif compute_id == disk.Attachments[0][\"server_id\"] {\n+\t\t\tglog.V(4).Infof(\"Disk: %q is already attached to compute: %q\", diskName, compute_id)\n+\t\t\treturn disk.ID, nil\n+\t\t} else {\n+\t\t\terrMsg := fmt.Sprintf(\"Disk %q is attached to a different compute: %q, should be detached before proceeding\", diskName, disk.Attachments[0][\"server_id\"])\n+\t\t\tglog.Errorf(errMsg)\n+\t\t\treturn \"\", errors.New(errMsg)\n+\t\t}\n+\t}\n+\t// add read only flag here if possible spothanis\n+\t_, err = volumeattach.Create(cClient, compute_id, &volumeattach.CreateOpts{\n+\t\tVolumeID: disk.ID,\n+\t}).Extract()\n+\tif err != nil {\n+\t\tglog.Errorf(\"Failed to attach %s volume to %s compute\", diskName, compute_id)\n+\t\treturn \"\", err\n+\t}\n+\tglog.V(2).Infof(\"Successfully attached %s volume to %s compute\", diskName, compute_id)\n+\treturn disk.ID, nil\n+}\n+\n+// Detaches given cinder volume from the compute running kubelet\n+func (os *OpenStack) DetachDisk(partialDiskId string) error {\n+\tdisk, err := os.getVolume(partialDiskId)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tcClient, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{\n+\t\tRegion: os.region,\n+\t})\n+\tif err != nil || cClient == nil {\n+\t\tglog.Errorf(\"Unable to initialize nova client for region: %s\", os.region)\n+\t\treturn err\n+\t}\n+\tcompute_id, err := os.getComputeIDbyHostname(cClient)\n+\tif err != nil || len(compute_id) == 0 {\n+\t\tglog.Errorf(\"Unable to get compute id while detaching disk\")\n+\t\treturn err\n+\t}\n+\tif len(disk.Attachments) > 0 && disk.Attachments[0][\"server_id\"] != nil && compute_id == disk.Attachments[0][\"server_id\"] {\n+\t\t// This is a blocking call and effects kubelet's performance directly.\n+\t\t// We should consider kicking it out into a separate routine, if it is bad.\n+\t\terr = volumeattach.Delete(cClient, compute_id, disk.ID).ExtractErr()\n+\t\tif err != nil {\n+\t\t\tglog.Errorf(\"Failed to delete volume %s from compute %s attached %v\", disk.ID, compute_id, err)\n+\t\t\treturn err\n+\t\t}\n+\t\tglog.V(2).Infof(\"Successfully detached volume: %s from compute: %s\", disk.ID, compute_id)\n+\t} else {\n+\t\terrMsg := fmt.Sprintf(\"Disk: %s has no attachments or is not attached to compute: %s\", disk.Name, compute_id)\n+\t\tglog.Errorf(errMsg)\n+\t\treturn errors.New(errMsg)\n+\t}\n+\treturn nil\n+}\n+\n+// Takes a partial/full disk id or diskname\n+func (os *OpenStack) getVolume(diskName string) (volumes.Volume, error) {\n+\tsClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{\n+\t\tRegion: os.region,\n+\t})\n+\n+\tvar volume volumes.Volume\n+\tif err != nil || sClient == nil {\n+\t\tglog.Errorf(\"Unable to initialize cinder client for region: %s\", os.region)\n+\t\treturn volume, err\n+\t}\n+\n+\terr = volumes.List(sClient, nil).EachPage(func(page pagination.Page) (bool, error) {\n+\t\tvols, err := volumes.ExtractVolumes(page)\n+\t\tif err != nil {\n+\t\t\tglog.Errorf(\"Failed to extract volumes: %v\", err)\n+\t\t\treturn false, err\n+\t\t} else {\n+\t\t\tfor _, v := range vols {\n+\t\t\t\tglog.V(4).Infof(\"%s %s %v\", v.ID, v.Name, v.Attachments)\n+\t\t\t\tif v.Name == diskName || strings.Contains(v.ID, diskName) {\n+\t\t\t\t\tvolume = v\n+\t\t\t\t\treturn true, nil\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\t// if it reached here then no disk with the given name was found.\n+\t\terrmsg := fmt.Sprintf(\"Unable to find disk: %s in region %s\", diskName, os.region)\n+\t\treturn false, errors.New(errmsg)\n+\t})\n+\tif err != nil {\n+\t\tglog.Errorf(\"Error occured getting volume: %s\", diskName)\n+\t\treturn volume, err\n+\t}\n+\treturn volume, err\n+}\n+\n+func (os *OpenStack) getComputeIDbyHostname(cClient *gophercloud.ServiceClient) (string, error) {\n+\n+\thostname, err := ossys.Hostname()\n+\n+\tif err != nil {\n+\t\tglog.Errorf(\"Failed to get Minion's hostname: %v\", err)\n+\t\treturn \"\", err\n+\t}\n+\n+\ti, ok := os.Instances()\n+\tif !ok {\n+\t\tglog.Errorf(\"Unable to get instances\")","path":"pkg/cloudprovider/providers/openstack/openstack.go","position":146,"original_position":146,"commit_id":"c841a20361c86ea94acf5e5aff9f319aaa629e89","original_commit_id":"c841a20361c86ea94acf5e5aff9f319aaa629e89","user":{"login":"pmorie","id":366488,"avatar_url":"https://avatars.githubusercontent.com/u/366488?v=3","gravatar_id":"","url":"https://api.github.com/users/pmorie","html_url":"https://github.com/pmorie","followers_url":"https://api.github.com/users/pmorie/followers","following_url":"https://api.github.com/users/pmorie/following{/other_user}","gists_url":"https://api.github.com/users/pmorie/gists{/gist_id}","starred_url":"https://api.github.com/users/pmorie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pmorie/subscriptions","organizations_url":"https://api.github.com/users/pmorie/orgs","repos_url":"https://api.github.com/users/pmorie/repos","events_url":"https://api.github.com/users/pmorie/events{/privacy}","received_events_url":"https://api.github.com/users/pmorie/received_events","type":"User","site_admin":false},"body":"\"Unable to get OpenStack instances\" would be more helpful here.","created_at":"2015-08-26T21:11:58Z","updated_at":"2015-08-26T21:11:58Z","html_url":"https://github.com/kubernetes/kubernetes/pull/6689#discussion_r38035469","pull_request_url":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689","_links":{"self":{"href":"https://api.github.com/repos/kubernetes/kubernetes/pulls/comments/38035469"},"html":{"href":"https://github.com/kubernetes/kubernetes/pull/6689#discussion_r38035469"},"pull_request":{"href":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689"}}},"pull_request":{"url":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689","id":33068144,"html_url":"https://github.com/kubernetes/kubernetes/pull/6689","diff_url":"https://github.com/kubernetes/kubernetes/pull/6689.diff","patch_url":"https://github.com/kubernetes/kubernetes/pull/6689.patch","issue_url":"https://api.github.com/repos/kubernetes/kubernetes/issues/6689","number":6689,"state":"open","locked":false,"title":"Volume Plugin for Cinder; Openstack Block Storage","user":{"login":"spothanis","id":4702326,"avatar_url":"https://avatars.githubusercontent.com/u/4702326?v=3","gravatar_id":"","url":"https://api.github.com/users/spothanis","html_url":"https://github.com/spothanis","followers_url":"https://api.github.com/users/spothanis/followers","following_url":"https://api.github.com/users/spothanis/following{/other_user}","gists_url":"https://api.github.com/users/spothanis/gists{/gist_id}","starred_url":"https://api.github.com/users/spothanis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spothanis/subscriptions","organizations_url":"https://api.github.com/users/spothanis/orgs","repos_url":"https://api.github.com/users/spothanis/repos","events_url":"https://api.github.com/users/spothanis/events{/privacy}","received_events_url":"https://api.github.com/users/spothanis/received_events","type":"User","site_admin":false},"body":"The PR implements cinder as a volume plugin. Cinder is openstack's block storage component.\r\nThe functionality is very similar to GCE's pd ","created_at":"2015-04-10T17:50:11Z","updated_at":"2015-08-26T21:11:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f4ea4603e6fc0a8f06f5ccaacae0039846da966e","assignee":{"login":"thockin","id":5595220,"avatar_url":"https://avatars.githubusercontent.com/u/5595220?v=3","gravatar_id":"","url":"https://api.github.com/users/thockin","html_url":"https://github.com/thockin","followers_url":"https://api.github.com/users/thockin/followers","following_url":"https://api.github.com/users/thockin/following{/other_user}","gists_url":"https://api.github.com/users/thockin/gists{/gist_id}","starred_url":"https://api.github.com/users/thockin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thockin/subscriptions","organizations_url":"https://api.github.com/users/thockin/orgs","repos_url":"https://api.github.com/users/thockin/repos","events_url":"https://api.github.com/users/thockin/events{/privacy}","received_events_url":"https://api.github.com/users/thockin/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689/commits","review_comments_url":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689/comments","review_comment_url":"https://api.github.com/repos/kubernetes/kubernetes/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kubernetes/kubernetes/issues/6689/comments","statuses_url":"https://api.github.com/repos/kubernetes/kubernetes/statuses/c841a20361c86ea94acf5e5aff9f319aaa629e89","head":{"label":"spothanis:cinder-vol-plugin","ref":"cinder-vol-plugin","sha":"c841a20361c86ea94acf5e5aff9f319aaa629e89","user":{"login":"spothanis","id":4702326,"avatar_url":"https://avatars.githubusercontent.com/u/4702326?v=3","gravatar_id":"","url":"https://api.github.com/users/spothanis","html_url":"https://github.com/spothanis","followers_url":"https://api.github.com/users/spothanis/followers","following_url":"https://api.github.com/users/spothanis/following{/other_user}","gists_url":"https://api.github.com/users/spothanis/gists{/gist_id}","starred_url":"https://api.github.com/users/spothanis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spothanis/subscriptions","organizations_url":"https://api.github.com/users/spothanis/orgs","repos_url":"https://api.github.com/users/spothanis/repos","events_url":"https://api.github.com/users/spothanis/events{/privacy}","received_events_url":"https://api.github.com/users/spothanis/received_events","type":"User","site_admin":false},"repo":{"id":30397993,"name":"kubernetes","full_name":"spothanis/kubernetes","owner":{"login":"spothanis","id":4702326,"avatar_url":"https://avatars.githubusercontent.com/u/4702326?v=3","gravatar_id":"","url":"https://api.github.com/users/spothanis","html_url":"https://github.com/spothanis","followers_url":"https://api.github.com/users/spothanis/followers","following_url":"https://api.github.com/users/spothanis/following{/other_user}","gists_url":"https://api.github.com/users/spothanis/gists{/gist_id}","starred_url":"https://api.github.com/users/spothanis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spothanis/subscriptions","organizations_url":"https://api.github.com/users/spothanis/orgs","repos_url":"https://api.github.com/users/spothanis/repos","events_url":"https://api.github.com/users/spothanis/events{/privacy}","received_events_url":"https://api.github.com/users/spothanis/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/spothanis/kubernetes","description":"Container Cluster Manager","fork":true,"url":"https://api.github.com/repos/spothanis/kubernetes","forks_url":"https://api.github.com/repos/spothanis/kubernetes/forks","keys_url":"https://api.github.com/repos/spothanis/kubernetes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/spothanis/kubernetes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/spothanis/kubernetes/teams","hooks_url":"https://api.github.com/repos/spothanis/kubernetes/hooks","issue_events_url":"https://api.github.com/repos/spothanis/kubernetes/issues/events{/number}","events_url":"https://api.github.com/repos/spothanis/kubernetes/events","assignees_url":"https://api.github.com/repos/spothanis/kubernetes/assignees{/user}","branches_url":"https://api.github.com/repos/spothanis/kubernetes/branches{/branch}","tags_url":"https://api.github.com/repos/spothanis/kubernetes/tags","blobs_url":"https://api.github.com/repos/spothanis/kubernetes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/spothanis/kubernetes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/spothanis/kubernetes/git/refs{/sha}","trees_url":"https://api.github.com/repos/spothanis/kubernetes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/spothanis/kubernetes/statuses/{sha}","languages_url":"https://api.github.com/repos/spothanis/kubernetes/languages","stargazers_url":"https://api.github.com/repos/spothanis/kubernetes/stargazers","contributors_url":"https://api.github.com/repos/spothanis/kubernetes/contributors","subscribers_url":"https://api.github.com/repos/spothanis/kubernetes/subscribers","subscription_url":"https://api.github.com/repos/spothanis/kubernetes/subscription","commits_url":"https://api.github.com/repos/spothanis/kubernetes/commits{/sha}","git_commits_url":"https://api.github.com/repos/spothanis/kubernetes/git/commits{/sha}","comments_url":"https://api.github.com/repos/spothanis/kubernetes/comments{/number}","issue_comment_url":"https://api.github.com/repos/spothanis/kubernetes/issues/comments{/number}","contents_url":"https://api.github.com/repos/spothanis/kubernetes/contents/{+path}","compare_url":"https://api.github.com/repos/spothanis/kubernetes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/spothanis/kubernetes/merges","archive_url":"https://api.github.com/repos/spothanis/kubernetes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/spothanis/kubernetes/downloads","issues_url":"https://api.github.com/repos/spothanis/kubernetes/issues{/number}","pulls_url":"https://api.github.com/repos/spothanis/kubernetes/pulls{/number}","milestones_url":"https://api.github.com/repos/spothanis/kubernetes/milestones{/number}","notifications_url":"https://api.github.com/repos/spothanis/kubernetes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/spothanis/kubernetes/labels{/name}","releases_url":"https://api.github.com/repos/spothanis/kubernetes/releases{/id}","created_at":"2015-02-06T06:08:33Z","updated_at":"2015-03-25T02:35:51Z","pushed_at":"2015-08-25T22:15:22Z","git_url":"git://github.com/spothanis/kubernetes.git","ssh_url":"git@github.com:spothanis/kubernetes.git","clone_url":"https://github.com/spothanis/kubernetes.git","svn_url":"https://github.com/spothanis/kubernetes","homepage":"http://kubernetes.io","size":103391,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"kubernetes:master","ref":"master","sha":"e228300f4b33563681fabd395094d181de6663fa","user":{"login":"kubernetes","id":13629408,"avatar_url":"https://avatars.githubusercontent.com/u/13629408?v=3","gravatar_id":"","url":"https://api.github.com/users/kubernetes","html_url":"https://github.com/kubernetes","followers_url":"https://api.github.com/users/kubernetes/followers","following_url":"https://api.github.com/users/kubernetes/following{/other_user}","gists_url":"https://api.github.com/users/kubernetes/gists{/gist_id}","starred_url":"https://api.github.com/users/kubernetes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kubernetes/subscriptions","organizations_url":"https://api.github.com/users/kubernetes/orgs","repos_url":"https://api.github.com/users/kubernetes/repos","events_url":"https://api.github.com/users/kubernetes/events{/privacy}","received_events_url":"https://api.github.com/users/kubernetes/received_events","type":"Organization","site_admin":false},"repo":{"id":20580498,"name":"kubernetes","full_name":"kubernetes/kubernetes","owner":{"login":"kubernetes","id":13629408,"avatar_url":"https://avatars.githubusercontent.com/u/13629408?v=3","gravatar_id":"","url":"https://api.github.com/users/kubernetes","html_url":"https://github.com/kubernetes","followers_url":"https://api.github.com/users/kubernetes/followers","following_url":"https://api.github.com/users/kubernetes/following{/other_user}","gists_url":"https://api.github.com/users/kubernetes/gists{/gist_id}","starred_url":"https://api.github.com/users/kubernetes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kubernetes/subscriptions","organizations_url":"https://api.github.com/users/kubernetes/orgs","repos_url":"https://api.github.com/users/kubernetes/repos","events_url":"https://api.github.com/users/kubernetes/events{/privacy}","received_events_url":"https://api.github.com/users/kubernetes/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kubernetes/kubernetes","description":"Container Cluster Manager from Google","fork":false,"url":"https://api.github.com/repos/kubernetes/kubernetes","forks_url":"https://api.github.com/repos/kubernetes/kubernetes/forks","keys_url":"https://api.github.com/repos/kubernetes/kubernetes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kubernetes/kubernetes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kubernetes/kubernetes/teams","hooks_url":"https://api.github.com/repos/kubernetes/kubernetes/hooks","issue_events_url":"https://api.github.com/repos/kubernetes/kubernetes/issues/events{/number}","events_url":"https://api.github.com/repos/kubernetes/kubernetes/events","assignees_url":"https://api.github.com/repos/kubernetes/kubernetes/assignees{/user}","branches_url":"https://api.github.com/repos/kubernetes/kubernetes/branches{/branch}","tags_url":"https://api.github.com/repos/kubernetes/kubernetes/tags","blobs_url":"https://api.github.com/repos/kubernetes/kubernetes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kubernetes/kubernetes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kubernetes/kubernetes/git/refs{/sha}","trees_url":"https://api.github.com/repos/kubernetes/kubernetes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kubernetes/kubernetes/statuses/{sha}","languages_url":"https://api.github.com/repos/kubernetes/kubernetes/languages","stargazers_url":"https://api.github.com/repos/kubernetes/kubernetes/stargazers","contributors_url":"https://api.github.com/repos/kubernetes/kubernetes/contributors","subscribers_url":"https://api.github.com/repos/kubernetes/kubernetes/subscribers","subscription_url":"https://api.github.com/repos/kubernetes/kubernetes/subscription","commits_url":"https://api.github.com/repos/kubernetes/kubernetes/commits{/sha}","git_commits_url":"https://api.github.com/repos/kubernetes/kubernetes/git/commits{/sha}","comments_url":"https://api.github.com/repos/kubernetes/kubernetes/comments{/number}","issue_comment_url":"https://api.github.com/repos/kubernetes/kubernetes/issues/comments{/number}","contents_url":"https://api.github.com/repos/kubernetes/kubernetes/contents/{+path}","compare_url":"https://api.github.com/repos/kubernetes/kubernetes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kubernetes/kubernetes/merges","archive_url":"https://api.github.com/repos/kubernetes/kubernetes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kubernetes/kubernetes/downloads","issues_url":"https://api.github.com/repos/kubernetes/kubernetes/issues{/number}","pulls_url":"https://api.github.com/repos/kubernetes/kubernetes/pulls{/number}","milestones_url":"https://api.github.com/repos/kubernetes/kubernetes/milestones{/number}","notifications_url":"https://api.github.com/repos/kubernetes/kubernetes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kubernetes/kubernetes/labels{/name}","releases_url":"https://api.github.com/repos/kubernetes/kubernetes/releases{/id}","created_at":"2014-06-06T22:56:04Z","updated_at":"2015-08-26T20:36:23Z","pushed_at":"2015-08-26T21:07:55Z","git_url":"git://github.com/kubernetes/kubernetes.git","ssh_url":"git@github.com:kubernetes/kubernetes.git","clone_url":"https://github.com/kubernetes/kubernetes.git","svn_url":"https://github.com/kubernetes/kubernetes","homepage":"http://kubernetes.io","size":362190,"stargazers_count":9902,"watchers_count":9902,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2406,"mirror_url":null,"open_issues_count":1700,"forks":2406,"open_issues":1700,"watchers":9902,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689"},"html":{"href":"https://github.com/kubernetes/kubernetes/pull/6689"},"issue":{"href":"https://api.github.com/repos/kubernetes/kubernetes/issues/6689"},"comments":{"href":"https://api.github.com/repos/kubernetes/kubernetes/issues/6689/comments"},"review_comments":{"href":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689/comments"},"review_comment":{"href":"https://api.github.com/repos/kubernetes/kubernetes/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kubernetes/kubernetes/pulls/6689/commits"},"statuses":{"href":"https://api.github.com/repos/kubernetes/kubernetes/statuses/c841a20361c86ea94acf5e5aff9f319aaa629e89"}}}}