{"action":"created","comment":{"url":"https://api.github.com/repos/axsh/wakame-vdc/pulls/comments/32005885","id":32005885,"diff_hunk":"@@ -154,45 +154,137 @@ def ipv4_u32_dynamic_range_array\n     end\n \n     def add_ipv4_dynamic_range(range_begin, range_end)\n-      range_begin = IPAddress::IPv4.new(\"#{range_begin}/#{self[:prefix]}\")\n-      range_end = IPAddress::IPv4.new(\"#{range_end}/#{self[:prefix]}\")\n-      test_inclusion(*validate_range_args(range_begin, range_end)) { |range, op|\n-         case op\n-         when :coverbegin\n-           range.range_end = range_begin\n-         when :coverend\n-           range.range_begin = range_end\n-         when :inccur\n-           range.destroy\n-         end\n-         range.save_changes\n-      }\n+      range_begin_u32, range_end_u32 = validate_range_args(range_begin, range_end)\n+      dhcp_range_dataset.included_ranges(range_begin_u32, range_end_u32).destroy\n+      hit_range_ds = dhcp_range_dataset.hit_ranges(range_begin_u32, range_end_u32)\n+      if hit_range_ds.empty?\n+        # no overwrap ranges. add new range.\n+        return self.add_dhcp_range(range_begin: range_begin_u32,\n+                                   range_end: range_end_u32)\n+      end\n \n-      self.add_dhcp_range(:range_begin=>range_begin, :range_end=>range_end)\n+      to_be_merged=[nil, nil]\n+      hit_range_ds.each { |r|\n+        existing_range = (r.range_begin.to_u32 .. r.range_end.to_u32)\n+        case [existing_range.include?(range_begin_u32), existing_range.include?(range_end_u32)]\n+        when [true, true]\n+          # exsiting range includes given range.\n+          # => this case can be ignored.\n+        when [true, false]\n+          # given begin address is in existing range but\n+          # given end address is higher than existing range.\n+          # existing: 192.168.0.10-20\n+          # given: 192.168.0.19-21\n+          # result: 192.168.0.10-21\n+          # => expand r.range_end or merge\n+          #    perform it after all iteration.\n+          to_be_merged[0] = r\n+        when [false, true]\n+          # given begin address is lower than existing range but\n+          # given end address is in existing range.\n+          # => expand r.range_begin or merge\n+          #    perform it after all iteration.\n+          to_be_merged[1] = r\n+        when [false, false]\n+          # given range includes existing range.\n+          # => this case sholud be handled at above ``included_ranges().destroy``\n+          raise \"BUG: Dead Code Path\"\n+        end\n+      }\n \n-      self\n+      case to_be_merged.map(&:class)\n+      when [NilClass, NilClass]\n+        # no marge targets.\n+        # Here comes when given range includes one or more exsisting\n+        # ranges so that they are destroyed and add the given range as new.\n+        # existing: 192.168.0.10-20, 30-40\n+        # given: 192.168.0.9-41\n+        # result: destroy => 10-20 & 30-40, add 9-41.\n+        self.add_dhcp_range(range_begin: range_begin_u32,\n+                            range_end: range_end_u32)\n+      when [DhcpRange, NilClass]\n+        # expand its end address\n+        to_be_merged[0].tap { |r|\n+          r.range_end = range_end_u32\n+          r.save_changes\n+        }\n+      when [NilClass, DhcpRange]\n+        # expand its end address\n+        to_be_merged[1].tap { |r|\n+          r.range_begin = range_begin_u32\n+          r.save_changes\n+        }\n+      when [DhcpRange, DhcpRange]\n+        # merge two ranges.\n+        to_be_merged[0].tap { |r|\n+          r.range_end = to_be_merged[1].range_end\n+          r.save_changes\n+        }\n+        to_be_merged[1].destroy\n+      else\n+        raise \"BUG: Dead Code Path\"\n+      end\n     end\n \n     def del_ipv4_dynamic_range(range_begin, range_end)\n-      range_begin = IPAddress::IPv4.new(\"#{range_begin}/#{self[:prefix]}\")\n-      range_end = IPAddress::IPv4.new(\"#{range_end}/#{self[:prefix]}\")\n-      test_inclusion(*validate_range_args(range_begin, range_end)) { |range, op|\n-        case op\n-        when :coverbegin\n-          range.range_end = range_begin\n-        when :coverend\n-          range.range_begin = range_end\n-        when :inccur\n-          range.destroy\n-        when :incnew\n-          t = range.range_end\n-          range.range_end = range_begin\n-          self.add_dhcp_range(:range_begin=>range_end, :range_end=>t)\n+      range_begin_u32, range_end_u32 = validate_range_args(range_begin, range_end)\n+      dhcp_range_dataset.included_ranges(range_begin_u32, range_end_u32).destroy\n+      hit_range_ds = dhcp_range_dataset.hit_ranges(range_begin_u32, range_end_u32)\n+      if hit_range_ds.empty?\n+        return nil\n+      end\n+      \n+      hit_range_ds.each { |r|\n+        # make existing range smaller for the case that the give range\n+        # hits the edges for \"r\".\n+        existing_range = ((r.range_begin.to_u32 + 1) .. (r.range_end.to_u32 - 1))\n+        case [existing_range.include?(range_begin_u32), existing_range.include?(range_end_u32)]\n+        when [true, true]\n+          # exsiting range includes given range.\n+          # => split the existing range \"r\"\n+          self.add_dhcp_range(range_begin: range_end_u32+1,\n+                              range_end: r.range_end.to_u32)\n+          r.range_end = range_begin_u32 - 1\n+          r.save_changes\n+        when [true, false]\n+          # given begin address is in existing range but\n+          # given end address is higher than existing range.\n+          # existing: 192.168.0.10-20\n+          # given1: 192.168.0.19-21\n+          # result2: 192.168.0.10-18\n+          # => shorten r.range_end\n+          r.range_end = range_begin_u32 - 1\n+          r.save_changes\n+        when [false, true]\n+          # given begin address is lower than existing range but\n+          # given end address is in existing range.\n+          # existing: 192.168.0.10-20\n+          # given: 192.168.0.9-11\n+          # result: 192.168.0.12-20\n+          # => shorten r.range_begin\n+          r.range_begin = range_end_u32 + 1\n+          r.save_changes\n+        when [false, false]\n+          if range_begin == range_end","path":"dcmgr/lib/dcmgr/models/network.rb","position":144,"original_position":144,"commit_id":"3bddc50231cccd0d7a17de75d6c2195b93b5ec43","original_commit_id":"3bddc50231cccd0d7a17de75d6c2195b93b5ec43","user":{"login":"unakatsuo","id":95236,"avatar_url":"https://avatars.githubusercontent.com/u/95236?v=3","gravatar_id":"","url":"https://api.github.com/users/unakatsuo","html_url":"https://github.com/unakatsuo","followers_url":"https://api.github.com/users/unakatsuo/followers","following_url":"https://api.github.com/users/unakatsuo/following{/other_user}","gists_url":"https://api.github.com/users/unakatsuo/gists{/gist_id}","starred_url":"https://api.github.com/users/unakatsuo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/unakatsuo/subscriptions","organizations_url":"https://api.github.com/users/unakatsuo/orgs","repos_url":"https://api.github.com/users/unakatsuo/repos","events_url":"https://api.github.com/users/unakatsuo/events{/privacy}","received_events_url":"https://api.github.com/users/unakatsuo/received_events","type":"User","site_admin":false},"body":"```\r\nif range_begin_u32 == range_end_u32\r\n```","created_at":"2015-06-09T12:10:10Z","updated_at":"2015-06-09T12:10:10Z","html_url":"https://github.com/axsh/wakame-vdc/pull/605#discussion_r32005885","pull_request_url":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605","_links":{"self":{"href":"https://api.github.com/repos/axsh/wakame-vdc/pulls/comments/32005885"},"html":{"href":"https://github.com/axsh/wakame-vdc/pull/605#discussion_r32005885"},"pull_request":{"href":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605"}}},"pull_request":{"url":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605","id":37010119,"html_url":"https://github.com/axsh/wakame-vdc/pull/605","diff_url":"https://github.com/axsh/wakame-vdc/pull/605.diff","patch_url":"https://github.com/axsh/wakame-vdc/pull/605.patch","issue_url":"https://api.github.com/repos/axsh/wakame-vdc/issues/605","number":605,"state":"open","locked":false,"title":"Fix ``vdc-manage network dhcp addrange/delrange``","user":{"login":"unakatsuo","id":95236,"avatar_url":"https://avatars.githubusercontent.com/u/95236?v=3","gravatar_id":"","url":"https://api.github.com/users/unakatsuo","html_url":"https://github.com/unakatsuo","followers_url":"https://api.github.com/users/unakatsuo/followers","following_url":"https://api.github.com/users/unakatsuo/following{/other_user}","gists_url":"https://api.github.com/users/unakatsuo/gists{/gist_id}","starred_url":"https://api.github.com/users/unakatsuo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/unakatsuo/subscriptions","organizations_url":"https://api.github.com/users/unakatsuo/orgs","repos_url":"https://api.github.com/users/unakatsuo/repos","events_url":"https://api.github.com/users/unakatsuo/events{/privacy}","received_events_url":"https://api.github.com/users/unakatsuo/received_events","type":"User","site_admin":false},"body":"This is a long living bug which add/del IP address range fails some cases.\r\n\r\n\r\n","created_at":"2015-06-05T08:20:54Z","updated_at":"2015-06-09T12:10:10Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b655de8652faf6fc6b64a78f5ede03de20916789","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605/commits","review_comments_url":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605/comments","review_comment_url":"https://api.github.com/repos/axsh/wakame-vdc/pulls/comments{/number}","comments_url":"https://api.github.com/repos/axsh/wakame-vdc/issues/605/comments","statuses_url":"https://api.github.com/repos/axsh/wakame-vdc/statuses/3bddc50231cccd0d7a17de75d6c2195b93b5ec43","head":{"label":"axsh:fix-add-del-dhcp-ranges","ref":"fix-add-del-dhcp-ranges","sha":"3bddc50231cccd0d7a17de75d6c2195b93b5ec43","user":{"login":"axsh","id":95230,"avatar_url":"https://avatars.githubusercontent.com/u/95230?v=3","gravatar_id":"","url":"https://api.github.com/users/axsh","html_url":"https://github.com/axsh","followers_url":"https://api.github.com/users/axsh/followers","following_url":"https://api.github.com/users/axsh/following{/other_user}","gists_url":"https://api.github.com/users/axsh/gists{/gist_id}","starred_url":"https://api.github.com/users/axsh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/axsh/subscriptions","organizations_url":"https://api.github.com/users/axsh/orgs","repos_url":"https://api.github.com/users/axsh/repos","events_url":"https://api.github.com/users/axsh/events{/privacy}","received_events_url":"https://api.github.com/users/axsh/received_events","type":"Organization","site_admin":false},"repo":{"id":610415,"name":"wakame-vdc","full_name":"axsh/wakame-vdc","owner":{"login":"axsh","id":95230,"avatar_url":"https://avatars.githubusercontent.com/u/95230?v=3","gravatar_id":"","url":"https://api.github.com/users/axsh","html_url":"https://github.com/axsh","followers_url":"https://api.github.com/users/axsh/followers","following_url":"https://api.github.com/users/axsh/following{/other_user}","gists_url":"https://api.github.com/users/axsh/gists{/gist_id}","starred_url":"https://api.github.com/users/axsh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/axsh/subscriptions","organizations_url":"https://api.github.com/users/axsh/orgs","repos_url":"https://api.github.com/users/axsh/repos","events_url":"https://api.github.com/users/axsh/events{/privacy}","received_events_url":"https://api.github.com/users/axsh/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/axsh/wakame-vdc","description":" Datacenter Hypervisor - Open Source Cloud Computing / IaaS","fork":false,"url":"https://api.github.com/repos/axsh/wakame-vdc","forks_url":"https://api.github.com/repos/axsh/wakame-vdc/forks","keys_url":"https://api.github.com/repos/axsh/wakame-vdc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/axsh/wakame-vdc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/axsh/wakame-vdc/teams","hooks_url":"https://api.github.com/repos/axsh/wakame-vdc/hooks","issue_events_url":"https://api.github.com/repos/axsh/wakame-vdc/issues/events{/number}","events_url":"https://api.github.com/repos/axsh/wakame-vdc/events","assignees_url":"https://api.github.com/repos/axsh/wakame-vdc/assignees{/user}","branches_url":"https://api.github.com/repos/axsh/wakame-vdc/branches{/branch}","tags_url":"https://api.github.com/repos/axsh/wakame-vdc/tags","blobs_url":"https://api.github.com/repos/axsh/wakame-vdc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/axsh/wakame-vdc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/axsh/wakame-vdc/git/refs{/sha}","trees_url":"https://api.github.com/repos/axsh/wakame-vdc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/axsh/wakame-vdc/statuses/{sha}","languages_url":"https://api.github.com/repos/axsh/wakame-vdc/languages","stargazers_url":"https://api.github.com/repos/axsh/wakame-vdc/stargazers","contributors_url":"https://api.github.com/repos/axsh/wakame-vdc/contributors","subscribers_url":"https://api.github.com/repos/axsh/wakame-vdc/subscribers","subscription_url":"https://api.github.com/repos/axsh/wakame-vdc/subscription","commits_url":"https://api.github.com/repos/axsh/wakame-vdc/commits{/sha}","git_commits_url":"https://api.github.com/repos/axsh/wakame-vdc/git/commits{/sha}","comments_url":"https://api.github.com/repos/axsh/wakame-vdc/comments{/number}","issue_comment_url":"https://api.github.com/repos/axsh/wakame-vdc/issues/comments{/number}","contents_url":"https://api.github.com/repos/axsh/wakame-vdc/contents/{+path}","compare_url":"https://api.github.com/repos/axsh/wakame-vdc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/axsh/wakame-vdc/merges","archive_url":"https://api.github.com/repos/axsh/wakame-vdc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/axsh/wakame-vdc/downloads","issues_url":"https://api.github.com/repos/axsh/wakame-vdc/issues{/number}","pulls_url":"https://api.github.com/repos/axsh/wakame-vdc/pulls{/number}","milestones_url":"https://api.github.com/repos/axsh/wakame-vdc/milestones{/number}","notifications_url":"https://api.github.com/repos/axsh/wakame-vdc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/axsh/wakame-vdc/labels{/name}","releases_url":"https://api.github.com/repos/axsh/wakame-vdc/releases{/id}","created_at":"2010-04-14T16:46:01Z","updated_at":"2015-06-07T18:37:22Z","pushed_at":"2015-06-09T08:59:20Z","git_url":"git://github.com/axsh/wakame-vdc.git","ssh_url":"git@github.com:axsh/wakame-vdc.git","clone_url":"https://github.com/axsh/wakame-vdc.git","svn_url":"https://github.com/axsh/wakame-vdc","homepage":"https://github.com/axsh/wakame-vdc/wiki","size":58191,"stargazers_count":96,"watchers_count":96,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":25,"mirror_url":null,"open_issues_count":71,"forks":25,"open_issues":71,"watchers":96,"default_branch":"master"}},"base":{"label":"axsh:master","ref":"master","sha":"c4c0003dba258dc81143eb5fbfc4419a63c54129","user":{"login":"axsh","id":95230,"avatar_url":"https://avatars.githubusercontent.com/u/95230?v=3","gravatar_id":"","url":"https://api.github.com/users/axsh","html_url":"https://github.com/axsh","followers_url":"https://api.github.com/users/axsh/followers","following_url":"https://api.github.com/users/axsh/following{/other_user}","gists_url":"https://api.github.com/users/axsh/gists{/gist_id}","starred_url":"https://api.github.com/users/axsh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/axsh/subscriptions","organizations_url":"https://api.github.com/users/axsh/orgs","repos_url":"https://api.github.com/users/axsh/repos","events_url":"https://api.github.com/users/axsh/events{/privacy}","received_events_url":"https://api.github.com/users/axsh/received_events","type":"Organization","site_admin":false},"repo":{"id":610415,"name":"wakame-vdc","full_name":"axsh/wakame-vdc","owner":{"login":"axsh","id":95230,"avatar_url":"https://avatars.githubusercontent.com/u/95230?v=3","gravatar_id":"","url":"https://api.github.com/users/axsh","html_url":"https://github.com/axsh","followers_url":"https://api.github.com/users/axsh/followers","following_url":"https://api.github.com/users/axsh/following{/other_user}","gists_url":"https://api.github.com/users/axsh/gists{/gist_id}","starred_url":"https://api.github.com/users/axsh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/axsh/subscriptions","organizations_url":"https://api.github.com/users/axsh/orgs","repos_url":"https://api.github.com/users/axsh/repos","events_url":"https://api.github.com/users/axsh/events{/privacy}","received_events_url":"https://api.github.com/users/axsh/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/axsh/wakame-vdc","description":" Datacenter Hypervisor - Open Source Cloud Computing / IaaS","fork":false,"url":"https://api.github.com/repos/axsh/wakame-vdc","forks_url":"https://api.github.com/repos/axsh/wakame-vdc/forks","keys_url":"https://api.github.com/repos/axsh/wakame-vdc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/axsh/wakame-vdc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/axsh/wakame-vdc/teams","hooks_url":"https://api.github.com/repos/axsh/wakame-vdc/hooks","issue_events_url":"https://api.github.com/repos/axsh/wakame-vdc/issues/events{/number}","events_url":"https://api.github.com/repos/axsh/wakame-vdc/events","assignees_url":"https://api.github.com/repos/axsh/wakame-vdc/assignees{/user}","branches_url":"https://api.github.com/repos/axsh/wakame-vdc/branches{/branch}","tags_url":"https://api.github.com/repos/axsh/wakame-vdc/tags","blobs_url":"https://api.github.com/repos/axsh/wakame-vdc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/axsh/wakame-vdc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/axsh/wakame-vdc/git/refs{/sha}","trees_url":"https://api.github.com/repos/axsh/wakame-vdc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/axsh/wakame-vdc/statuses/{sha}","languages_url":"https://api.github.com/repos/axsh/wakame-vdc/languages","stargazers_url":"https://api.github.com/repos/axsh/wakame-vdc/stargazers","contributors_url":"https://api.github.com/repos/axsh/wakame-vdc/contributors","subscribers_url":"https://api.github.com/repos/axsh/wakame-vdc/subscribers","subscription_url":"https://api.github.com/repos/axsh/wakame-vdc/subscription","commits_url":"https://api.github.com/repos/axsh/wakame-vdc/commits{/sha}","git_commits_url":"https://api.github.com/repos/axsh/wakame-vdc/git/commits{/sha}","comments_url":"https://api.github.com/repos/axsh/wakame-vdc/comments{/number}","issue_comment_url":"https://api.github.com/repos/axsh/wakame-vdc/issues/comments{/number}","contents_url":"https://api.github.com/repos/axsh/wakame-vdc/contents/{+path}","compare_url":"https://api.github.com/repos/axsh/wakame-vdc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/axsh/wakame-vdc/merges","archive_url":"https://api.github.com/repos/axsh/wakame-vdc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/axsh/wakame-vdc/downloads","issues_url":"https://api.github.com/repos/axsh/wakame-vdc/issues{/number}","pulls_url":"https://api.github.com/repos/axsh/wakame-vdc/pulls{/number}","milestones_url":"https://api.github.com/repos/axsh/wakame-vdc/milestones{/number}","notifications_url":"https://api.github.com/repos/axsh/wakame-vdc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/axsh/wakame-vdc/labels{/name}","releases_url":"https://api.github.com/repos/axsh/wakame-vdc/releases{/id}","created_at":"2010-04-14T16:46:01Z","updated_at":"2015-06-07T18:37:22Z","pushed_at":"2015-06-09T08:59:20Z","git_url":"git://github.com/axsh/wakame-vdc.git","ssh_url":"git@github.com:axsh/wakame-vdc.git","clone_url":"https://github.com/axsh/wakame-vdc.git","svn_url":"https://github.com/axsh/wakame-vdc","homepage":"https://github.com/axsh/wakame-vdc/wiki","size":58191,"stargazers_count":96,"watchers_count":96,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":25,"mirror_url":null,"open_issues_count":71,"forks":25,"open_issues":71,"watchers":96,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605"},"html":{"href":"https://github.com/axsh/wakame-vdc/pull/605"},"issue":{"href":"https://api.github.com/repos/axsh/wakame-vdc/issues/605"},"comments":{"href":"https://api.github.com/repos/axsh/wakame-vdc/issues/605/comments"},"review_comments":{"href":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605/comments"},"review_comment":{"href":"https://api.github.com/repos/axsh/wakame-vdc/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/axsh/wakame-vdc/pulls/605/commits"},"statuses":{"href":"https://api.github.com/repos/axsh/wakame-vdc/statuses/3bddc50231cccd0d7a17de75d6c2195b93b5ec43"}}}}