diff --git a/.travis.yml b/.travis.yml
index c4552c6f..2875f639 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
 language: go
 
 go:
-  - 1.7
   - 1.8
 
diff --git a/Gopkg.lock b/Gopkg.lock
index 0587848c..bc967282 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -2,10 +2,10 @@
 
 
 [[projects]]
-  branch = "master"
-  name = "github.com/Azure/azure-storage-go"
-  packages = ["."]
-  revision = "32cfbe17a139c17f84be16bdf8f9c45c840a046b"
+  name = "github.com/Azure/azure-sdk-for-go"
+  packages = ["storage"]
+  revision = "59c277f1b488b81b1a5f944212f25b69bea8ece3"
+  version = "v10.1.0-beta"
 
 [[projects]]
   name = "github.com/Azure/go-autorest"
@@ -14,10 +14,10 @@
   version = "v8.1.0"
 
 [[projects]]
-  branch = "master"
   name = "github.com/BurntSushi/toml"
   packages = ["."]
-  revision = "a368813c5e648fee92e5f6c30e3944ff9d5e8895"
+  revision = "b26d9c308763d68093482582cea63d69be07a0f0"
+  version = "v0.3.0"
 
 [[projects]]
   name = "github.com/asaskevich/govalidator"
@@ -27,14 +27,15 @@
 
 [[projects]]
   name = "github.com/aws/aws-sdk-go"
-  packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/request","aws/session","aws/signer/v4","private/endpoints","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","private/waiter","service/s3","service/sts"]
-  revision = "5b341290c488aa6bd76b335d819b4a68516ec3ab"
+  packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/s3","service/sts"]
+  revision = "6d7fc1a00fcae6bbb53550f4a0b98324fd7aa250"
+  version = "v1.10.12"
 
 [[projects]]
   name = "github.com/boltdb/bolt"
   packages = ["."]
-  revision = "583e8937c61f1af6513608ccc75c97b6abdf4ff9"
-  version = "v1.3.0"
+  revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8"
+  version = "v1.3.1"
 
 [[projects]]
   name = "github.com/cenkalti/backoff"
@@ -63,8 +64,8 @@
 [[projects]]
   name = "github.com/go-redis/redis"
   packages = [".","internal","internal/consistenthash","internal/hashtag","internal/pool","internal/proto"]
-  revision = "e14976b254c5bc5f399dd0ae9314b1d02a176897"
-  version = "v6.5.0"
+  revision = "da63fe7def48e378caf9539abf64b9b1e37bc01e"
+  version = "v6.5.3"
 
 [[projects]]
   name = "github.com/go-sql-driver/mysql"
@@ -109,10 +110,10 @@
   version = "0.2.2"
 
 [[projects]]
-  branch = "master"
   name = "github.com/jroimartin/gocui"
   packages = ["."]
-  revision = "612b0b2987ec1a6af46d7008cef1efd4b3898346"
+  revision = "4e9ce9a8e26f2ef33dfe297dbdfca148733b6b9b"
+  version = "v0.3.0"
 
 [[projects]]
   branch = "master"
@@ -128,9 +129,15 @@
 
 [[projects]]
   branch = "master"
+  name = "github.com/knqyf263/go-rpm-version"
+  packages = ["."]
+  revision = "74609b86c936dff800c69ec89fcf4bc52d5f13a4"
+
+[[projects]]
   name = "github.com/kotakanbe/go-cve-dictionary"
   packages = ["config","db","jvn","log","models","nvd","util"]
   revision = "89e381b4e7e5a31097bbd5779cbb555f5bd3fe87"
+  version = "v0.1.1"
 
 [[projects]]
   name = "github.com/kotakanbe/go-pingscanner"
@@ -153,14 +160,14 @@
 [[projects]]
   name = "github.com/labstack/gommon"
   packages = ["color","log"]
-  revision = "1121fd3e243c202482226a7afe4dcd07ffc4139a"
-  version = "v0.2.1"
+  revision = "779b8a8b9850a97acba6a3fe20feb628c39e17c1"
+  version = "0.2.2"
 
 [[projects]]
   branch = "master"
   name = "github.com/lib/pq"
   packages = [".","hstore","oid"]
-  revision = "8837942c3e09574accbc5f150e2c5e057189cace"
+  revision = "dd1fe2071026ce53f36a39112e645b4d4f5793a4"
 
 [[projects]]
   name = "github.com/mattn/go-colorable"
@@ -202,7 +209,7 @@
   branch = "master"
   name = "github.com/nsf/termbox-go"
   packages = ["."]
-  revision = "72800b73ab9a3c78df350738298b0361354772ff"
+  revision = "4ed959e0540971545eddb8c75514973d670cf739"
 
 [[projects]]
   name = "github.com/parnurzeal/gorequest"
@@ -232,7 +239,7 @@
   branch = "master"
   name = "github.com/sirupsen/logrus"
   packages = ["."]
-  revision = "3d4380f53a34dcdc95f0c1db702615992b38d9a4"
+  revision = "5ff5dd844dfeb4e23e27528f79f1f845bc8bb78f"
 
 [[projects]]
   branch = "master"
@@ -252,39 +259,33 @@
   packages = ["oval"]
   revision = "003ac9af5fffac6c97ab1def025d2cb73e88469a"
 
-[[projects]]
-  branch = "master"
-  name = "go4.org"
-  packages = ["syncutil"]
-  revision = "034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e"
-
 [[projects]]
   branch = "master"
   name = "golang.org/x/crypto"
   packages = ["curve25519","ed25519","ed25519/internal/edwards25519","ssh","ssh/agent","ssh/terminal"]
-  revision = "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d"
+  revision = "7f7c0c2d75ebb4e32a21396ce36e87b6dadc91c9"
 
 [[projects]]
   branch = "master"
   name = "golang.org/x/net"
   packages = ["context","idna","publicsuffix"]
-  revision = "455220fa52c866a8aa14ff5e8cc68cde16b8395e"
+  revision = "b3756b4b77d7b13260a0a2ec658753cf48922eac"
 
 [[projects]]
   branch = "master"
   name = "golang.org/x/sys"
   packages = ["unix"]
-  revision = "90796e5a05ce440b41c768bd9af257005e470461"
+  revision = "4cd6d1a821c7175768725b55ca82f14683a29ea4"
 
 [[projects]]
   branch = "master"
   name = "golang.org/x/text"
   packages = ["internal/gen","internal/triegen","internal/ucd","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
-  revision = "6353ef0f924300eea566d3438817aa4d3374817e"
+  revision = "836efe42bb4aa16aaa17b9c155d8813d336ed720"
 
 [solve-meta]
   analyzer-name = "dep"
   analyzer-version = 1
-  inputs-digest = "a6b387c74e75e1f971ee643c8904f6fd4e3dfdb7fa36119ab7bc28d9cfd66427"
+  inputs-digest = "269ff02f8e4540ba049a340068dac0ff4f0495df9f8eeb21d4a545ea5dedf2dd"
   solver-name = "gps-cdcl"
   solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
index 9e0d6fb4..da91d653 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -1,23 +1,57 @@
 
+# Gopkg.toml example
+#
+# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+#   name = "github.com/user/project"
+#   version = "1.0.0"
+#
+# [[constraint]]
+#   name = "github.com/user/project2"
+#   branch = "dev"
+#   source = "github.com/myfork/project2"
+#
+# [[override]]
+#  name = "github.com/x/y"
+#  version = "2.4.0"
+
+
 [[constraint]]
-  branch = "master"
-  name = "github.com/Azure/azure-storage-go"
-
-[[constraint]]
-  branch = "master"
   name = "github.com/BurntSushi/toml"
+  version = "0.3.0"
+
+[[constraint]]
+  name = "github.com/asaskevich/govalidator"
+  version = "6.0.0"
+
+[[constraint]]
+  name = "github.com/boltdb/bolt"
+  version = "1.3.1"
+
+[[constraint]]
+  name = "github.com/cenkalti/backoff"
+  version = "1.0.0"
 
 [[constraint]]
   branch = "master"
-  name = "github.com/sirupsen/logrus"
-
-[[constraint]]
-  name = "github.com/aws/aws-sdk-go"
-  revision = "5b341290c488aa6bd76b335d819b4a68516ec3ab"
+  name = "github.com/google/subcommands"
 
 [[constraint]]
   branch = "master"
+  name = "github.com/gosuri/uitable"
+
+[[constraint]]
+  branch = "master"
+  name = "github.com/howeyc/gopass"
+
+[[constraint]]
   name = "github.com/jroimartin/gocui"
+  version = "0.3.0"
 
 [[constraint]]
   branch = "master"
@@ -25,12 +59,28 @@
 
 [[constraint]]
   branch = "master"
-  name = "github.com/kotakanbe/go-cve-dictionary"
+  name = "github.com/knqyf263/go-deb-version"
 
 [[constraint]]
   branch = "master"
-  name = "github.com/kotakanbe/goval-dictionary"
+  name = "github.com/knqyf263/go-rpm-version"
+
+[[constraint]]
+  name = "github.com/kotakanbe/go-pingscanner"
+  version = "0.1.0"
 
 [[constraint]]
   branch = "master"
   name = "github.com/kotakanbe/logrus-prefixed-formatter"
+
+[[constraint]]
+  name = "github.com/parnurzeal/gorequest"
+  version = "0.2.15"
+
+[[constraint]]
+  name = "github.com/rifflock/lfshook"
+  version = "1.7.0"
+
+[[constraint]]
+  branch = "master"
+  name = "github.com/sirupsen/logrus"
diff --git a/README.md b/README.md
index e9f66dc6..4dc7cf46 100644
--- a/README.md
+++ b/README.md
@@ -803,12 +803,12 @@ In order to scan, the following dependencies are required, so you need to instal
 |:-------------|-------------------:|:-------------|
 | Ubuntu       |          12, 14, 16| -            |
 | Debian       |                7, 8| aptitude     |
-| CentOS       |                6, 7| yum-plugin-changelog |
-| Amazon       |                All | -            |
-| RHEL         |                  5 | yum-security |
-| RHEL         |               6, 7 | -            |
-| Oracle Linux |                  5 | yum-security |
-| Oracle Linux |               6, 7 | -            |
+| CentOS       |                6, 7| yum-plugin-changelog, yum-utils |
+| Amazon       |                All | -            | TODO yum-utils?, yum-plugin-changelog
+| RHEL         |                  5 | yum-security | TODO yum-utils?
+| RHEL         |               6, 7 | -            | TODO yum-utils?
+| Oracle Linux |                  5 | yum-security | TODO yum-utils?
+| Oracle Linux |               6, 7 | -            |TODO yum-utils?  
 | FreeBSD      |                 10 | -            |
 | Raspbian     |     Wheezy, Jessie | -            |
 
diff --git a/commands/scan.go b/commands/scan.go
index 5359be60..0ce52481 100644
--- a/commands/scan.go
+++ b/commands/scan.go
@@ -67,6 +67,7 @@ func (*ScanCmd) Usage() string {
 		[-cachedb-path=/path/to/cache.db]
 		[-ssh-native-insecure]
 		[-containers-only]
+		[-package-list-only]
 		[-skip-broken]
 		[-http-proxy=http://192.168.0.1:8080]
 		[-ask-key-password]
diff --git a/config/config.go b/config/config.go
index 2ad9c073..edbaa433 100644
--- a/config/config.go
+++ b/config/config.go
@@ -418,7 +418,7 @@ type ServerInfo struct {
 	Optional [][]interface{}
 
 	// For CentOS, RHEL, Amazon
-	Enablerepo string
+	Enablerepo []string
 
 	// used internal
 	LogMsgAnsiColor string // DebugLog Color
diff --git a/config/tomlloader.go b/config/tomlloader.go
index 7030dd0b..1cadd8cc 100644
--- a/config/tomlloader.go
+++ b/config/tomlloader.go
@@ -20,7 +20,6 @@ package config
 import (
 	"fmt"
 	"os"
-	"strings"
 
 	"github.com/BurntSushi/toml"
 	"github.com/future-architect/vuls/contrib/owasp-dependency-check/parser"
@@ -164,7 +163,7 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) error {
 			s.Enablerepo = d.Enablerepo
 		}
 		if len(s.Enablerepo) != 0 {
-			for _, repo := range strings.Split(s.Enablerepo, ",") {
+			for _, repo := range s.Enablerepo {
 				switch repo {
 				case "base", "updates":
 					// nop
diff --git a/models/models.go b/models/models.go
index bd7ab57f..96850f24 100644
--- a/models/models.go
+++ b/models/models.go
@@ -18,4 +18,4 @@ along with this program.  If not, see .
 package models
 
 // JSONVersion is JSON Version
-const JSONVersion = "0.3.0"
+const JSONVersion = 2
diff --git a/models/packages.go b/models/packages.go
index 19ed3c5f..827ca103 100644
--- a/models/packages.go
+++ b/models/packages.go
@@ -42,6 +42,7 @@ func (ps Packages) MergeNewVersion(as Packages) {
 		if pack, ok := ps[a.Name]; ok {
 			pack.NewVersion = a.NewVersion
 			pack.NewRelease = a.NewRelease
+			pack.Repository = a.Repository
 			ps[a.Name] = pack
 		}
 	}
@@ -79,6 +80,16 @@ func (ps Packages) FormatUpdatablePacksSummary() string {
 	return fmt.Sprintf("%d updatable packages", nUpdatable)
 }
 
+// FindOne search a element by name-newver-newrel-arch
+func (ps Packages) FindOne(f func(Package) bool) (string, Package, bool) {
+	for key, p := range ps {
+		if f(p) {
+			return key, p, true
+		}
+	}
+	return "", Package{}, false
+}
+
 // Package has installed packages.
 type Package struct {
 	Name        string
@@ -86,6 +97,7 @@ type Package struct {
 	Release     string
 	NewVersion  string
 	NewRelease  string
+	Arch        string
 	Repository  string
 	Changelog   Changelog
 	NotFixedYet bool // Ubuntu OVAL Only
@@ -145,8 +157,8 @@ func (p Package) FormatChangelog() string {
 }
 
 // Changelog has contents of changelog and how to get it.
-// Method: modesl.detectionMethodStr
+// Method: models.detectionMethodStr
 type Changelog struct {
 	Contents string
-	Method   string
+	Method   DetectionMethod
 }
diff --git a/models/scanresults.go b/models/scanresults.go
index aa538249..284724fb 100644
--- a/models/scanresults.go
+++ b/models/scanresults.go
@@ -32,7 +32,7 @@ type ScanResults []ScanResult
 // ScanResult has the result of scanned CVE information.
 type ScanResult struct {
 	ScannedAt   time.Time
-	JSONVersion string
+	JSONVersion int
 	Lang        string
 	ServerName  string // TOML Section key
 	Family      string
diff --git a/models/vulninfos.go b/models/vulninfos.go
index 2c31e8b7..f0e92b82 100644
--- a/models/vulninfos.go
+++ b/models/vulninfos.go
@@ -26,7 +26,8 @@ import (
 	"github.com/future-architect/vuls/config"
 )
 
-// VulnInfos is VulnInfo list, getter/setter, sortable methods.
+// VulnInfos has a map of VulnInfo
+// Key: CveID
 type VulnInfos map[string]VulnInfo
 
 // Find elements that matches the function passed in argument
@@ -198,13 +199,18 @@ type DistroAdvisory struct {
 // Score: 0 - 100
 type Confidence struct {
 	Score           int
-	DetectionMethod string
+	DetectionMethod DetectionMethod
 }
 
 func (c Confidence) String() string {
 	return fmt.Sprintf("%d / %s", c.Score, c.DetectionMethod)
 }
 
+// DetectionMethod indicates
+// - How to detect the CveID
+// - How to get the changelog difference between installed and candidate version
+type DetectionMethod string
+
 const (
 	// CpeNameMatchStr is a String representation of CpeNameMatch
 	CpeNameMatchStr = "CpeNameMatch"
diff --git a/report/azureblob.go b/report/azureblob.go
index 2220e9c1..f065accd 100644
--- a/report/azureblob.go
+++ b/report/azureblob.go
@@ -24,7 +24,7 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/Azure/azure-storage-go"
+	storage "github.com/Azure/azure-sdk-for-go/storage"
 
 	c "github.com/future-architect/vuls/config"
 	"github.com/future-architect/vuls/models"
diff --git a/report/tui.go b/report/tui.go
index 83b786f2..9f762f15 100644
--- a/report/tui.go
+++ b/report/tui.go
@@ -45,14 +45,12 @@ var currentDetailLimitY int
 func RunTui(results models.ScanResults) subcommands.ExitStatus {
 	scanResults = results
 
-	g, err := gocui.NewGui(gocui.OutputNormal)
-	if err != nil {
-		log.Errorf("%s", err)
-		return subcommands.ExitFailure
-	}
+	// g, err := gocui.NewGui(gocui.OutputNormal)
+	g := gocui.NewGui()
 	defer g.Close()
 
-	g.SetManagerFunc(layout)
+	g.SetLayout(layout)
+	// g.SetManagerFunc(layout)
 	if err := keybindings(g); err != nil {
 		log.Errorf("%s", err)
 		return subcommands.ExitFailure
@@ -177,19 +175,19 @@ func nextView(g *gocui.Gui, v *gocui.View) error {
 	var err error
 
 	if v == nil {
-		_, err = g.SetCurrentView("side")
+		err = g.SetCurrentView("side")
 	}
 	switch v.Name() {
 	case "side":
-		_, err = g.SetCurrentView("summary")
+		err = g.SetCurrentView("summary")
 	case "summary":
-		_, err = g.SetCurrentView("detail")
+		err = g.SetCurrentView("detail")
 	case "detail":
-		_, err = g.SetCurrentView("changelog")
+		err = g.SetCurrentView("changelog")
 	case "changelog":
-		_, err = g.SetCurrentView("side")
+		err = g.SetCurrentView("side")
 	default:
-		_, err = g.SetCurrentView("summary")
+		err = g.SetCurrentView("summary")
 	}
 	return err
 }
@@ -198,19 +196,19 @@ func previousView(g *gocui.Gui, v *gocui.View) error {
 	var err error
 
 	if v == nil {
-		_, err = g.SetCurrentView("side")
+		err = g.SetCurrentView("side")
 	}
 	switch v.Name() {
 	case "side":
-		_, err = g.SetCurrentView("side")
+		err = g.SetCurrentView("side")
 	case "summary":
-		_, err = g.SetCurrentView("side")
+		err = g.SetCurrentView("side")
 	case "detail":
-		_, err = g.SetCurrentView("summary")
+		err = g.SetCurrentView("summary")
 	case "changelog":
-		_, err = g.SetCurrentView("detail")
+		err = g.SetCurrentView("detail")
 	default:
-		_, err = g.SetCurrentView("side")
+		err = g.SetCurrentView("side")
 	}
 	return err
 }
@@ -393,7 +391,7 @@ func cursorPageUp(g *gocui.Gui, v *gocui.View) error {
 func previousSummary(g *gocui.Gui, v *gocui.View) error {
 	if v != nil {
 		// cursor to summary
-		if _, err := g.SetCurrentView("summary"); err != nil {
+		if err := g.SetCurrentView("summary"); err != nil {
 			return err
 		}
 		// move next line
@@ -401,7 +399,7 @@ func previousSummary(g *gocui.Gui, v *gocui.View) error {
 			return err
 		}
 		// cursor to detail
-		if _, err := g.SetCurrentView("detail"); err != nil {
+		if err := g.SetCurrentView("detail"); err != nil {
 			return err
 		}
 	}
@@ -411,7 +409,7 @@ func previousSummary(g *gocui.Gui, v *gocui.View) error {
 func nextSummary(g *gocui.Gui, v *gocui.View) error {
 	if v != nil {
 		// cursor to summary
-		if _, err := g.SetCurrentView("summary"); err != nil {
+		if err := g.SetCurrentView("summary"); err != nil {
 			return err
 		}
 		// move next line
@@ -419,7 +417,7 @@ func nextSummary(g *gocui.Gui, v *gocui.View) error {
 			return err
 		}
 		// cursor to detail
-		if _, err := g.SetCurrentView("detail"); err != nil {
+		if err := g.SetCurrentView("detail"); err != nil {
 			return err
 		}
 	}
@@ -502,7 +500,7 @@ func getLine(g *gocui.Gui, v *gocui.View) error {
 			return err
 		}
 		fmt.Fprintln(v, l)
-		if _, err := g.SetCurrentView("msg"); err != nil {
+		if err := g.SetCurrentView("msg"); err != nil {
 			return err
 		}
 	}
@@ -525,7 +523,7 @@ func showMsg(g *gocui.Gui, v *gocui.View) error {
 			return err
 		}
 		fmt.Fprintln(v, l)
-		if _, err := g.SetCurrentView("msg"); err != nil {
+		if err := g.SetCurrentView("msg"); err != nil {
 			return err
 		}
 	}
@@ -536,7 +534,7 @@ func delMsg(g *gocui.Gui, v *gocui.View) error {
 	if err := g.DeleteView("msg"); err != nil {
 		return err
 	}
-	if _, err := g.SetCurrentView("summary"); err != nil {
+	if err := g.SetCurrentView("summary"); err != nil {
 		return err
 	}
 	return nil
@@ -592,7 +590,7 @@ func setSideLayout(g *gocui.Gui) error {
 		}
 		currentScanResult = scanResults[0]
 		vinfos = scanResults[0].ScannedCves.ToSortedSlice()
-		if _, err := g.SetCurrentView("side"); err != nil {
+		if err := g.SetCurrentView("side"); err != nil {
 			return err
 		}
 	}
diff --git a/scan/debian.go b/scan/debian.go
index 17559ded..a7ecffb3 100644
--- a/scan/debian.go
+++ b/scan/debian.go
@@ -167,7 +167,7 @@ func (o *debian) checkDependencies() error {
 }
 
 func (o *debian) scanPackages() error {
-	installed, upgradable, err := o.scanInstalledPackages()
+	installed, updatable, err := o.scanInstalledPackages()
 	if err != nil {
 		o.log.Errorf("Failed to scan installed packages")
 		return err
@@ -178,7 +178,7 @@ func (o *debian) scanPackages() error {
 		return nil
 	}
 
-	unsecure, err := o.scanUnsecurePackages(upgradable)
+	unsecure, err := o.scanUnsecurePackages(updatable)
 	if err != nil {
 		o.log.Errorf("Failed to scan vulnerable packages")
 		return err
@@ -189,7 +189,7 @@ func (o *debian) scanPackages() error {
 
 func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, error) {
 	installed := models.Packages{}
-	upgradable := models.Packages{}
+	updatable := models.Packages{}
 
 	r := o.exec("dpkg-query -W", noSudo)
 	if !r.isSuccess() {
@@ -214,27 +214,27 @@ func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, erro
 		}
 	}
 
-	upgradableNames, err := o.GetUpgradablePackNames()
+	updatableNames, err := o.getUpdatablePackNames()
 	if err != nil {
 		return nil, nil, err
 	}
-	for _, name := range upgradableNames {
+	for _, name := range updatableNames {
 		for _, pack := range installed {
 			if pack.Name == name {
-				upgradable[name] = pack
+				updatable[name] = pack
 				break
 			}
 		}
 	}
 
 	// Fill the candidate versions of upgradable packages
-	err = o.fillCandidateVersion(upgradable)
+	err = o.fillCandidateVersion(updatable)
 	if err != nil {
 		return nil, nil, fmt.Errorf("Failed to fill candidate versions. err: %s", err)
 	}
-	installed.MergeNewVersion(upgradable)
+	installed.MergeNewVersion(updatable)
 
-	return installed, upgradable, nil
+	return installed, updatable, nil
 }
 
 var packageLinePattern = regexp.MustCompile(`^([^\t']+)\t(.+)$`)
@@ -263,14 +263,14 @@ func (o *debian) aptGetUpdate() error {
 	return nil
 }
 
-func (o *debian) scanUnsecurePackages(upgradable models.Packages) (models.VulnInfos, error) {
+func (o *debian) scanUnsecurePackages(updatable models.Packages) (models.VulnInfos, error) {
 	o.aptGetUpdate()
 
 	// Setup changelog cache
 	current := cache.Meta{
 		Name:   o.getServerInfo().GetServerName(),
 		Distro: o.getServerInfo().Distro,
-		Packs:  upgradable,
+		Packs:  updatable,
 	}
 
 	o.log.Debugf("Ensure changelog cache: %s", current.Name)
@@ -280,7 +280,7 @@ func (o *debian) scanUnsecurePackages(upgradable models.Packages) (models.VulnIn
 	}
 
 	// Collect CVE information of upgradable packages
-	vulnInfos, err := o.scanVulnInfos(upgradable, meta)
+	vulnInfos, err := o.scanVulnInfos(updatable, meta)
 	if err != nil {
 		return nil, fmt.Errorf("Failed to scan unsecure packages. err: %s", err)
 	}
@@ -349,7 +349,7 @@ func (o *debian) fillCandidateVersion(packages models.Packages) (err error) {
 	return
 }
 
-func (o *debian) GetUpgradablePackNames() (packNames []string, err error) {
+func (o *debian) getUpdatablePackNames() (packNames []string, err error) {
 	cmd := util.PrependProxyEnv("LANGUAGE=en_US.UTF-8 apt-get upgrade --dry-run")
 	r := o.exec(cmd, noSudo)
 	if r.isSuccess(0, 1) {
@@ -360,7 +360,7 @@ func (o *debian) GetUpgradablePackNames() (packNames []string, err error) {
 		cmd, r.ExitStatus, r.Stdout, r.Stderr)
 }
 
-func (o *debian) parseAptGetUpgrade(stdout string) (upgradableNames []string, err error) {
+func (o *debian) parseAptGetUpgrade(stdout string) (updatableNames []string, err error) {
 	startRe := regexp.MustCompile(`The following packages will be upgraded:`)
 	stopRe := regexp.MustCompile(`^(\d+) upgraded.*`)
 	startLineFound, stopLineFound := false, false
@@ -375,21 +375,21 @@ func (o *debian) parseAptGetUpgrade(stdout string) (upgradableNames []string, er
 		}
 		result := stopRe.FindStringSubmatch(line)
 		if len(result) == 2 {
-			numUpgradablePacks, err := strconv.Atoi(result[1])
+			nUpdatable, err := strconv.Atoi(result[1])
 			if err != nil {
 				return nil, fmt.Errorf(
 					"Failed to scan upgradable packages number. line: %s", line)
 			}
-			if numUpgradablePacks != len(upgradableNames) {
+			if nUpdatable != len(updatableNames) {
 				return nil, fmt.Errorf(
 					"Failed to scan upgradable packages, expected: %s, detected: %d",
-					result[1], len(upgradableNames))
+					result[1], len(updatableNames))
 			}
 			stopLineFound = true
 			o.log.Debugf("Found the stop line. line: %s", line)
 			break
 		}
-		upgradableNames = append(upgradableNames, strings.Fields(line)...)
+		updatableNames = append(updatableNames, strings.Fields(line)...)
 	}
 	if !startLineFound {
 		// no upgrades
@@ -410,20 +410,20 @@ type DetectedCveID struct {
 	Confidence models.Confidence
 }
 
-func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta) (models.VulnInfos, error) {
+func (o *debian) scanVulnInfos(updatablePacks models.Packages, meta *cache.Meta) (models.VulnInfos, error) {
 	type response struct {
 		pack           *models.Package
 		DetectedCveIDs []DetectedCveID
 	}
-	resChan := make(chan response, len(upgradablePacks))
-	errChan := make(chan error, len(upgradablePacks))
-	reqChan := make(chan models.Package, len(upgradablePacks))
+	resChan := make(chan response, len(updatablePacks))
+	errChan := make(chan error, len(updatablePacks))
+	reqChan := make(chan models.Package, len(updatablePacks))
 	defer close(resChan)
 	defer close(errChan)
 	defer close(reqChan)
 
 	go func() {
-		for _, pack := range upgradablePacks {
+		for _, pack := range updatablePacks {
 			reqChan <- pack
 		}
 	}()
@@ -431,7 +431,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
 	timeout := time.After(30 * 60 * time.Second)
 	concurrency := 10
 	tasks := util.GenWorkers(concurrency)
-	for range upgradablePacks {
+	for range updatablePacks {
 		tasks <- func() {
 			select {
 			case pack := <-reqChan:
@@ -459,7 +459,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
 	// { DetectedCveID{} : [package] }
 	cvePackages := make(map[DetectedCveID][]string)
 	errs := []error{}
-	for i := 0; i < len(upgradablePacks); i++ {
+	for i := 0; i < len(updatablePacks); i++ {
 		select {
 		case response := <-resChan:
 			o.Packages[response.pack.Name] = *response.pack
@@ -474,7 +474,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
 				cvePackages[cve] = packNames
 			}
 			o.log.Infof("(%d/%d) Scanned %s: %s",
-				i+1, len(upgradablePacks), response.pack.Name, cves)
+				i+1, len(updatablePacks), response.pack.Name, cves)
 		case err := <-errChan:
 			errs = append(errs, err)
 		case <-timeout:
@@ -500,7 +500,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
 	}
 
 	// Update meta package information of changelog cache to the latest one.
-	meta.Packs = upgradablePacks
+	meta.Packs = updatablePacks
 	if err := cache.DB.RefreshMeta(*meta); err != nil {
 		return nil, err
 	}
@@ -664,7 +664,7 @@ func (o *debian) parseChangelog(changelog, name, ver string, confidence models.C
 
 	clog := models.Changelog{
 		Contents: strings.Join(buf, "\n"),
-		Method:   string(confidence.DetectionMethod),
+		Method:   confidence.DetectionMethod,
 	}
 	pack := o.Packages[name]
 	pack.Changelog = clog
diff --git a/scan/redhat.go b/scan/redhat.go
index 2a8e28d6..c1f12708 100644
--- a/scan/redhat.go
+++ b/scan/redhat.go
@@ -18,6 +18,7 @@ along with this program.  If not, see .
 package scan
 
 import (
+	"bufio"
 	"fmt"
 	"regexp"
 	"strings"
@@ -27,7 +28,7 @@ import (
 	"github.com/future-architect/vuls/models"
 	"github.com/future-architect/vuls/util"
 
-	"github.com/k0kubun/pp"
+	ver "github.com/knqyf263/go-rpm-version"
 )
 
 // inherit OsTypeInterface
@@ -147,14 +148,14 @@ func (o *redhat) checkIfSudoNoPasswd() error {
 		if majorVersion < 6 {
 			cmds = []cmd{
 				{"yum --color=never repolist", zero},
-				{"yum --color=never check-update", []int{0, 100}},
+				// {"yum --color=never check-update", []int{0, 100}},
 				{"yum --color=never list-security --security", zero},
 				{"yum --color=never info-security", zero},
 			}
 		} else {
 			cmds = []cmd{
 				{"yum --color=never repolist", zero},
-				{"yum --color=never check-update", []int{0, 100}},
+				// {"yum --color=never check-update", []int{0, 100}},
 				{"yum --color=never --security updateinfo list updates", zero},
 				{"yum --color=never --security updateinfo updates", zero},
 			}
@@ -174,12 +175,11 @@ func (o *redhat) checkIfSudoNoPasswd() error {
 	return nil
 }
 
-// CentOS 6, 7 	... yum-plugin-changelog
+// CentOS 6, 7 	... yum-plugin-changelog, yum-utils
 // RHEL 5     	... yum-security
 // RHEL 6, 7    ... -
 // Amazon 		... -
 func (o *redhat) checkDependencies() error {
-	var packName string
 	if o.Distro.Family == config.Amazon {
 		return nil
 	}
@@ -207,12 +207,14 @@ func (o *redhat) checkDependencies() error {
 		}
 	}
 
+	//TODO Check if yum-plugin-changelog is installed when scan with --changelog option on Amazon,RHEL, Oracle
+	var packNames []string
 	switch o.Distro.Family {
 	case config.CentOS:
-		packName = "yum-plugin-changelog"
+		packNames = []string{"yum-plugin-changelog", "yum-utils"}
 	case config.RedHat, config.Oracle:
 		if majorVersion < 6 {
-			packName = "yum-security"
+			packNames = []string{"yum-security"}
 		} else {
 			// yum-plugin-security is installed by default on RHEL6, 7
 			return nil
@@ -221,27 +223,45 @@ func (o *redhat) checkDependencies() error {
 		return fmt.Errorf("Not implemented yet: %s", o.Distro)
 	}
 
-	cmd := "rpm -q " + packName
-	if r := o.exec(cmd, noSudo); !r.isSuccess() {
-		msg := fmt.Sprintf("%s is not installed", packName)
-		o.log.Errorf(msg)
-		return fmt.Errorf(msg)
+	for _, name := range packNames {
+		cmd := "rpm -q " + name
+		if r := o.exec(cmd, noSudo); !r.isSuccess() {
+			msg := fmt.Sprintf("%s is not installed", name)
+			o.log.Errorf(msg)
+			return fmt.Errorf(msg)
+		}
 	}
-	o.log.Infof("Dependencies... Pass")
+	o.log.Infof("Dependencies ... Pass")
 	return nil
 }
 
 func (o *redhat) scanPackages() error {
-	var err error
-	var packs []models.Package
-	if packs, err = o.scanInstalledPackages(); err != nil {
+	installed, err := o.scanInstalledPackages()
+	if err != nil {
 		o.log.Errorf("Failed to scan installed packages")
 		return err
 	}
-	o.setPackages(models.NewPackages(packs...))
+
+	updatable, err := o.scanUpdatablePackages()
+	if err != nil {
+		o.log.Errorf("Failed to scan installed packages")
+		return err
+	}
+	installed.MergeNewVersion(updatable)
+	o.setPackages(installed)
+
+	if config.Conf.PackageListOnly {
+		return nil
+	}
+
+	//TODO Cache changelogs to bolt
+	//TODO --with-changelog
+	if err := o.fillChangelogs(updatable); err != nil {
+		return nil
+	}
 
 	var vinfos models.VulnInfos
-	if vinfos, err = o.scanVulnInfos(); err != nil {
+	if vinfos, err = o.scanUnsecurePackages(updatable); err != nil {
 		o.log.Errorf("Failed to scan vulnerable packages")
 		return err
 	}
@@ -249,406 +269,360 @@ func (o *redhat) scanPackages() error {
 	return nil
 }
 
-func (o *redhat) scanInstalledPackages() (installed []models.Package, err error) {
-	cmd := "rpm -qa --queryformat '%{NAME}\t%{EPOCHNUM}\t%{VERSION}\t%{RELEASE}\n'"
+func (o *redhat) scanInstalledPackages() (models.Packages, error) {
+	installed := models.Packages{}
+	cmd := "rpm -qa --queryformat '%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n'"
 	r := o.exec(cmd, noSudo)
 	if r.isSuccess() {
-		//  e.g.
-		// openssl	1.0.1e	30.el6.11
+		// openssl 0 1.0.1e	30.el6.11 x86_64
 		lines := strings.Split(r.Stdout, "\n")
 		for _, line := range lines {
 			if trimed := strings.TrimSpace(line); len(trimed) != 0 {
-				var pack models.Package
-				if pack, err = o.parseScannedPackagesLine(line); err != nil {
-					return
+				pack, err := o.parseInstalledPackagesLine(line)
+				if err != nil {
+					return nil, err
 				}
-				installed = append(installed, pack)
+				installed[pack.Name] = pack
 			}
 		}
-		return
+		return installed, nil
 	}
 
-	return nil, fmt.Errorf(
-		"Scan packages failed. status: %d, stdout: %s, stderr: %s",
+	return nil, fmt.Errorf("Scan packages failed. status: %d, stdout: %s, stderr: %s",
 		r.ExitStatus, r.Stdout, r.Stderr)
+
 }
 
-func (o *redhat) parseScannedPackagesLine(line string) (models.Package, error) {
+func (o *redhat) parseInstalledPackagesLine(line string) (models.Package, error) {
 	fields := strings.Fields(line)
-	if len(fields) != 4 {
+	if len(fields) != 5 {
 		return models.Package{},
 			fmt.Errorf("Failed to parse package line: %s", line)
 	}
 	ver := ""
-	if fields[1] == "0" {
+	epoch := fields[1]
+	if epoch == "0" {
 		ver = fields[2]
 	} else {
-		ver = fmt.Sprintf("%s:%s", fields[1], fields[2])
+		ver = fmt.Sprintf("%s:%s", epoch, fields[2])
 	}
+
 	return models.Package{
 		Name:    fields[0],
 		Version: ver,
 		Release: fields[3],
+		Arch:    fields[4],
 	}, nil
 }
 
-func (o *redhat) scanVulnInfos() (models.VulnInfos, error) {
-	if o.Distro.Family != config.CentOS {
-		// Amazon, RHEL, Oracle Linux has yum updateinfo as default
-		// yum updateinfo can collenct vendor advisory information.
-		return o.scanUnsecurePackagesUsingYumPluginSecurity()
-	}
-	// CentOS does not have security channel...
-	// So, yum check-update then parse chnagelog.
-	return o.scanUnsecurePackagesUsingYumCheckUpdate()
-}
-
-// For CentOS
-func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, error) {
-	cmd := "LANGUAGE=en_US.UTF-8 yum --color=never %s check-update"
-	if o.getServerInfo().Enablerepo != "" {
-		cmd = fmt.Sprintf(cmd, "--enablerepo="+o.getServerInfo().Enablerepo)
-	} else {
-		cmd = fmt.Sprintf(cmd, "")
+func (o *redhat) scanUpdatablePackages() (models.Packages, error) {
+	cmd := "repoquery --all --pkgnarrow=updates --qf='%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{REPO}'"
+	for _, repo := range o.getServerInfo().Enablerepo {
+		cmd += " --enablerepo=" + repo
 	}
 
-	r := o.exec(util.PrependProxyEnv(cmd), noSudo)
-	if !r.isSuccess(0, 100) {
-		//returns an exit code of 100 if there are available updates.
+	r := o.exec(util.PrependProxyEnv(cmd), o.sudo())
+	if !r.isSuccess() {
 		return nil, fmt.Errorf("Failed to SSH: %s", r)
 	}
 
-	// get Updateble package name, installed, candidate version.
-	packages, err := o.parseYumCheckUpdateLines(r.Stdout)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
-	}
-	o.log.Debugf("%s", pp.Sprintf("%v", packages))
-
-	// set candidate version info
-	o.Packages.MergeNewVersion(packages)
-
-	// Collect CVE-IDs in changelog
-	type PackageCveIDs struct {
-		Package models.Package
-		CveIDs  []string
-	}
-
-	allChangelog, err := o.getAllChangelog(packages)
-	if err != nil {
-		o.log.Errorf("Failed to getAllchangelog. err: %s", err)
-		return nil, err
-	}
-
-	// { packageName: changelog-lines }
-	var rpm2changelog map[string]*string
-	rpm2changelog, err = o.divideChangelogByPackage(allChangelog)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to parseAllChangelog. err: %s", err)
-	}
-
-	for name, clog := range rpm2changelog {
-		for _, p := range o.Packages {
-			n := fmt.Sprintf("%s-%s-%s", p.Name, p.NewVersion, p.NewRelease)
-			if name == n {
-				p.Changelog = models.Changelog{
-					Contents: *clog,
-					Method:   models.ChangelogExactMatchStr,
-				}
-				o.Packages[p.Name] = p
-				break
-			}
-		}
-	}
-
-	var results []PackageCveIDs
-	i := 0
-	for name := range packages {
-		changelog := o.getChangelogCVELines(rpm2changelog, packages[name])
-
-		// Collect unique set of CVE-ID in each changelog
-		uniqueCveIDMap := make(map[string]bool)
-		lines := strings.Split(changelog, "\n")
-		for _, line := range lines {
-			cveIDs := o.parseYumUpdateinfoLineToGetCveIDs(line)
-			for _, c := range cveIDs {
-				uniqueCveIDMap[c] = true
-			}
-		}
-
-		// keys
-		var cveIDs []string
-		for k := range uniqueCveIDMap {
-			cveIDs = append(cveIDs, k)
-		}
-		p := PackageCveIDs{
-			Package: packages[name],
-			CveIDs:  cveIDs,
-		}
-		results = append(results, p)
-
-		o.log.Infof("(%d/%d) Scanned %s-%s-%s -> %s-%s : %s",
-			i+1,
-			len(packages),
-			p.Package.Name,
-			p.Package.Version,
-			p.Package.Release,
-			p.Package.NewVersion,
-			p.Package.NewRelease,
-			p.CveIDs)
-		i++
-	}
-
-	// transform datastructure
-	// - From
-	// [
-	//   {
-	//     Pack:    models.Packages,
-	//     CveIDs:      []string,
-	//   },
-	// ]
-	// - To
-	// map {
-	//   CveID: models.Packages{}
-	// }
-	cveIDPackages := make(map[string]models.Packages)
-	for _, res := range results {
-		for _, cveID := range res.CveIDs {
-			if packages, ok := cveIDPackages[cveID]; ok {
-				packages[res.Package.Name] = res.Package
-				cveIDPackages[cveID] = packages
-			} else {
-				cveIDPackages[cveID] = models.NewPackages(res.Package)
-			}
-		}
-	}
-
-	vinfos := models.VulnInfos{}
-	for cveID, packs := range cveIDPackages {
-		names := []string{}
-		for name := range packs {
-			names = append(names, name)
-		}
-
-		// Amazon, RHEL do not use this method, so VendorAdvisory do not set.
-		vinfos[cveID] = models.VulnInfo{
-			CveID:        cveID,
-			PackageNames: names,
-			Confidence:   models.ChangelogExactMatch,
-		}
-	}
-	return vinfos, nil
+	// Collect Updateble packages, installed, candidate version and repository.
+	return o.parseUpdatablePacksLines(r.Stdout)
 }
 
-// parseYumCheckUpdateLines parse yum check-update to get package name, candidate version
-func (o *redhat) parseYumCheckUpdateLines(stdout string) (models.Packages, error) {
-	results := models.Packages{}
-	needToParse := false
+// parseUpdatablePacksLines parse the stdout of repoquery to get package name, candidate version
+func (o *redhat) parseUpdatablePacksLines(stdout string) (models.Packages, error) {
+	updatable := models.Packages{}
 	lines := strings.Split(stdout, "\n")
 	for _, line := range lines {
-		// update information of packages begin after blank line.
-		if trimed := strings.TrimSpace(line); len(trimed) == 0 {
-			needToParse = true
+		// TODO remove
+		// if strings.HasPrefix(line, "Obsoleting") ||
+		// strings.HasPrefix(line, "Security:") {
+		// // see https://github.com/future-architect/vuls/issues/165
+		// continue
+		// }
+		if len(strings.TrimSpace(line)) == 0 {
 			continue
 		}
-		if needToParse {
-			if strings.HasPrefix(line, "Obsoleting") ||
-				strings.HasPrefix(line, "Security:") {
-				// see https://github.com/future-architect/vuls/issues/165
-				continue
-			}
-			candidate, err := o.parseYumCheckUpdateLine(line)
-			if err != nil {
-				return results, err
-			}
-
-			installed, found := o.Packages[candidate.Name]
-			if !found {
-				o.log.Warnf("Not found the package in rpm -qa. candidate: %s-%s-%s",
-					candidate.Name, candidate.Version, candidate.Release)
-				results[candidate.Name] = candidate
-				continue
-			}
-			installed.NewVersion = candidate.NewVersion
-			installed.NewRelease = candidate.NewRelease
-			installed.Repository = candidate.Repository
-			results[installed.Name] = installed
+		pack, err := o.parseUpdatablePacksLine(line)
+		if err != nil {
+			return updatable, err
 		}
+		updatable[pack.Name] = pack
 	}
-	return results, nil
+	return updatable, nil
 }
 
-func (o *redhat) parseYumCheckUpdateLine(line string) (models.Package, error) {
+func (o *redhat) parseUpdatablePacksLine(line string) (models.Package, error) {
 	fields := strings.Fields(line)
-	if len(fields) < 3 {
-		return models.Package{}, fmt.Errorf("Unknown format: %s", line)
+	if len(fields) < 5 {
+		return models.Package{}, fmt.Errorf("Unknown format: %s, fields: %s", line, fields)
 	}
-	splitted := strings.Split(fields[0], ".")
-	packName := ""
-	if len(splitted) == 1 {
-		packName = fields[0]
+
+	ver := ""
+	epoch := fields[1]
+	if epoch == "0" {
+		ver = fields[2]
 	} else {
-		packName = strings.Join(strings.Split(fields[0], ".")[0:(len(splitted)-1)], ".")
+		ver = fmt.Sprintf("%s:%s", epoch, fields[2])
 	}
 
-	verfields := strings.Split(fields[1], "-")
-	if len(verfields) != 2 {
-		return models.Package{}, fmt.Errorf("Unknown format: %s", line)
-	}
-	release := verfields[1]
-	repos := strings.Join(fields[2:len(fields)], " ")
+	repos := strings.Join(fields[4:len(fields)], " ")
 
-	return models.Package{
-		Name:       packName,
-		NewVersion: verfields[0],
-		NewRelease: release,
+	p := models.Package{
+		Name:       fields[0],
+		NewVersion: ver,
+		NewRelease: fields[3],
 		Repository: repos,
-	}, nil
-}
-
-func (o *redhat) mkPstring() *string {
-	str := ""
-	return &str
-}
-
-func (o *redhat) regexpReplace(src string, pat string, rep string) string {
-	re := regexp.MustCompile(pat)
-	return re.ReplaceAllString(src, rep)
-}
-
-var changeLogCVEPattern = regexp.MustCompile(`CVE-[0-9]+-[0-9]+`)
-
-func (o *redhat) getChangelogCVELines(rpm2changelog map[string]*string, pack models.Package) string {
-	rpm := fmt.Sprintf("%s-%s-%s", pack.Name, pack.NewVersion, pack.NewRelease)
-	retLine := ""
-	if rpm2changelog[rpm] != nil {
-		lines := strings.Split(*rpm2changelog[rpm], "\n")
-		for _, line := range lines {
-			if changeLogCVEPattern.MatchString(line) {
-				retLine += fmt.Sprintf("%s\n", line)
-			}
-		}
 	}
-	return retLine
+	return p, nil
 }
 
-func (o *redhat) divideChangelogByPackage(allChangelog string) (map[string]*string, error) {
-	var majorVersion int
-	var err error
-	if o.Distro.Family == config.CentOS {
-		majorVersion, err = o.Distro.MajorVersion()
-		if err != nil {
-			return nil, fmt.Errorf("Not implemented yet: %s, err: %s", o.Distro, err)
+func (o *redhat) scanUnsecurePackages(updatable models.Packages) (models.VulnInfos, error) {
+	if o.Distro.Family != config.CentOS {
+		// Amazon, RHEL, Oracle Linux has yum updateinfo as default
+		// yum updateinfo can collenct vendor advisory information.
+		return o.scanCveIDsByCommands(updatable)
+	}
+
+	// Parse chnagelog because CentOS does not have security channel...
+	return o.scanCveIDsInChangelog(updatable)
+}
+
+func (o *redhat) fillChangelogs(updatables models.Packages) error {
+	names := []string{}
+	for name := range updatables {
+		names = append(names, name)
+	}
+
+	if err := o.fillDiffChangelogs(names); err != nil {
+		return err
+	}
+
+	emptyChangelogPackNames := []string{}
+	for _, pack := range o.Packages {
+		if pack.NewVersion != "" && pack.Changelog.Contents == "" {
+			emptyChangelogPackNames = append(emptyChangelogPackNames, pack.Name)
 		}
 	}
 
-	orglines := strings.Split(allChangelog, "\n")
-	tmpline := ""
-	var lines []string
-	var prev, now bool
-	for i := range orglines {
-		if majorVersion == 5 {
-			/* for CentOS5 (yum-util < 1.1.20) */
-			prev = false
-			now = false
-			if 0 < i {
-				prev, err = o.isRpmPackageNameLine(orglines[i-1])
-				if err != nil {
-					return nil, err
-				}
-			}
-			now, err = o.isRpmPackageNameLine(orglines[i])
-			if err != nil {
-				return nil, err
-			}
-			if prev && now {
-				tmpline = fmt.Sprintf("%s, %s", tmpline, orglines[i])
-				continue
-			}
-			if !prev && now {
-				tmpline = fmt.Sprintf("%s%s", tmpline, orglines[i])
-				continue
-			}
-			if tmpline != "" {
-				lines = append(lines, fmt.Sprintf("%s", tmpline))
-				tmpline = ""
-			}
-			lines = append(lines, fmt.Sprintf("%s", orglines[i]))
-		} else {
-			/* for CentOS6,7 (yum-util >= 1.1.20) */
-			line := orglines[i]
-			line = o.regexpReplace(line, `^ChangeLog for: `, "")
-			line = o.regexpReplace(line, `^\*\*\sNo\sChangeLog\sfor:.*`, "")
-			lines = append(lines, line)
+	i := 0
+	for _, name := range emptyChangelogPackNames {
+		i++
+		o.log.Infof("(%d/%d) Fetched Changelogs %s", i, len(emptyChangelogPackNames), name)
+		if err := o.fillDiffChangelogs([]string{name}); err != nil {
+			return err
 		}
 	}
 
-	rpm2changelog := make(map[string]*string)
-	writePointer := o.mkPstring()
-	for _, line := range lines {
-		match, err := o.isRpmPackageNameLine(line)
-		if err != nil {
-			return nil, err
-		}
-		if match {
-			rpms := strings.Split(line, ",")
-			pNewString := o.mkPstring()
-			writePointer = pNewString
-			for _, rpm := range rpms {
-				rpm = strings.TrimSpace(rpm)
-				rpm = o.regexpReplace(rpm, `\.(i386|i486|i586|i686|k6|athlon|x86_64|noarch|ppc|alpha|sparc)$`, "")
-				if ss := strings.Split(rpm, ":"); 1 < len(ss) {
-					epoch := ss[0]
-					packVersion := strings.Join(ss[1:len(ss)], ":")
-					if sss := strings.Split(packVersion, "-"); 2 < len(sss) {
-						version := strings.Join(sss[len(sss)-2:len(sss)], "-")
-						name := strings.Join(sss[0:len(sss)-2], "-")
-						rpm = fmt.Sprintf("%s-%s:%s", name, epoch, version)
-					}
-				}
-
-				rpm2changelog[rpm] = pNewString
-			}
-		} else {
-			if strings.HasPrefix(line, "Dependencies Resolved") {
-				return rpm2changelog, nil
-			}
-			*writePointer += fmt.Sprintf("%s\n", line)
-		}
-	}
-	return rpm2changelog, nil
+	return nil
 }
 
-// CentOS
-func (o *redhat) getAllChangelog(packages models.Packages) (stdout string, err error) {
-	packageNames := ""
-	for _, pack := range packages {
-		packageNames += fmt.Sprintf("%s ", pack.Name)
-	}
-
-	command := ""
-	if 0 < len(config.Conf.HTTPProxy) {
-		command += util.ProxyEnv()
-	}
-
+func (o *redhat) getAvailableChangelogs(packNames []string) (map[string]string, error) {
 	yumopts := ""
-	if o.getServerInfo().Enablerepo != "" {
-		yumopts = " --enablerepo=" + o.getServerInfo().Enablerepo
+	if 0 < len(o.getServerInfo().Enablerepo) {
+		yumopts = " --enablerepo=" + strings.Join(o.getServerInfo().Enablerepo, ",")
 	}
 	if config.Conf.SkipBroken {
 		yumopts += " --skip-broken"
 	}
+	cmd := `yum --color=never %s changelog all %s | grep -A 10000 '==================== Available Packages ===================='`
+	cmd = fmt.Sprintf(cmd, yumopts, strings.Join(packNames, " "))
 
-	// yum update --changelog doesn't have --color option.
-	command += fmt.Sprintf(" LANGUAGE=en_US.UTF-8 yum --changelog --assumeno update %s ", yumopts) + packageNames
-
-	r := o.exec(command, sudo)
+	r := o.exec(util.PrependProxyEnv(cmd), noSudo)
 	if !r.isSuccess(0, 1) {
-		return "", fmt.Errorf(
-			"Failed to get changelog. status: %d, stdout: %s, stderr: %s",
-			r.ExitStatus, r.Stdout, r.Stderr)
+		return nil, fmt.Errorf("Failed to SSH: %s", r)
 	}
-	return strings.Replace(r.Stdout, "\r", "", -1), nil
+
+	return o.divideChangelogsIntoEachPackages(r.Stdout), nil
+}
+
+// Divide available change logs of all updatable packages into each package's changelog
+func (o *redhat) divideChangelogsIntoEachPackages(stdout string) map[string]string {
+	changelogs := make(map[string]string)
+	scanner := bufio.NewScanner(strings.NewReader(stdout))
+
+	crlf, newBlock := false, true
+	packNameVer, contents := "", []string{}
+	for scanner.Scan() {
+		line := scanner.Text()
+		if strings.HasPrefix(line, "==================== Available Packages ====================") {
+			continue
+		}
+		if newBlock {
+			left := strings.Fields(line)[0]
+			// ss := strings.Split(left, ".")
+			// packNameVer = strings.Join(ss[0:len(ss)-1], ".")
+			packNameVer = left
+			newBlock = false
+			continue
+		}
+		if len(strings.TrimSpace(line)) == 0 {
+			if crlf {
+				changelogs[packNameVer] = strings.Join(contents, "\n")
+				packNameVer = ""
+				contents = []string{}
+				newBlock = true
+				crlf = false
+			} else {
+				contents = append(contents, line)
+				crlf = true
+			}
+		} else {
+			contents = append(contents, line)
+			crlf = false
+		}
+	}
+	if 0 < len(contents) {
+		changelogs[packNameVer] = strings.Join(contents, "\n")
+	}
+	return changelogs
+}
+
+func (o *redhat) fillDiffChangelogs(packNames []string) error {
+	changelogs, err := o.getAvailableChangelogs(packNames)
+	if err != nil {
+		return err
+	}
+
+	for s := range changelogs {
+		// name, pack, found := o.Packages.FindOne(func(p models.Package) bool {
+		name, pack, found := o.Packages.FindOne(func(p models.Package) bool {
+			var epochNameVerRel string
+			if index := strings.Index(p.NewVersion, ":"); 0 < index {
+				epoch := p.NewVersion[0:index]
+				ver := p.NewVersion[index+1 : len(p.NewVersion)]
+				epochNameVerRel = fmt.Sprintf("%s:%s-%s",
+					epoch, p.Name, ver)
+			} else {
+				epochNameVerRel = fmt.Sprintf("%s-%s",
+					p.Name, p.NewVersion)
+			}
+			return strings.HasPrefix(s, epochNameVerRel)
+		})
+
+		if found {
+			diff, err := o.getDiffChangelog(pack, changelogs[s])
+			detectionMethod := models.ChangelogExactMatchStr
+
+			if err != nil {
+				o.log.Debug(err)
+				// Try without epoch
+				if index := strings.Index(pack.Version, ":"); 0 < index {
+					pack.Version = pack.Version[index+1 : len(pack.Version)]
+					o.log.Debug("Try without epoch", pack)
+					diff, err = o.getDiffChangelog(pack, changelogs[s])
+					if err != nil {
+						o.log.Debugf("Failed to find the version in changelog: %s-%s-%s",
+							pack.Name, pack.Version, pack.Release)
+						detectionMethod = models.FailedToFindVersionInChangelog
+					} else {
+						o.log.Debugf("Found the version in changelog without epoch: %s-%s-%s",
+							pack.Name, pack.Version, pack.Release)
+						detectionMethod = models.ChangelogLenientMatchStr
+					}
+				}
+			}
+
+			pack = o.Packages[name]
+			pack.Changelog = models.Changelog{
+				Contents: diff,
+				Method:   models.DetectionMethod(detectionMethod),
+			}
+			o.Packages[name] = pack
+		}
+	}
+	return nil
+}
+
+func (o *redhat) getDiffChangelog(pack models.Package, availableChangelog string) (string, error) {
+	installedVer := ver.NewVersion(fmt.Sprintf("%s-%s", pack.Version, pack.Release))
+	scanner := bufio.NewScanner(strings.NewReader(availableChangelog))
+	diff := []string{}
+	found := false
+	for scanner.Scan() {
+		line := scanner.Text()
+		if !strings.HasPrefix(line, "* ") {
+			diff = append(diff, line)
+			continue
+		}
+
+		// openssh on RHEL
+		//   openssh-server-6.6.1p1-35.el7_3.x86_64   rhui-rhel-7-server-rhui-rpms
+		//   Wed Mar  1 21:00:00 2017 Jakub Jelen  - 6.6.1p1-35 + 0.9.3-9
+		ss := strings.Split(line, " + ")
+		if 1 < len(ss) {
+			line = ss[0]
+		}
+
+		ss = strings.Split(line, " ")
+		if len(ss) < 2 {
+			diff = append(diff, line)
+			continue
+		}
+		v := ss[len(ss)-1]
+		v = strings.TrimPrefix(v, "-")
+		v = strings.TrimPrefix(v, "[")
+		v = strings.TrimSuffix(v, "]")
+		version := ver.NewVersion(v)
+		if installedVer.Equal(version) || installedVer.GreaterThan(version) {
+			found = true
+			break
+		}
+		diff = append(diff, line)
+	}
+
+	if len(diff) == 0 || !found {
+		return availableChangelog,
+			fmt.Errorf("Failed to find the version in changelog: %s-%s-%s",
+				pack.Name, pack.Version, pack.Release)
+	}
+	return strings.TrimSpace(strings.Join(diff, "\n")), nil
+}
+
+func (o *redhat) scanCveIDsInChangelog(updatable models.Packages) (models.VulnInfos, error) {
+	packCveIDs := make(map[string][]string)
+	for name := range updatable {
+		cveIDs := []string{}
+		pack := o.Packages[name]
+		if pack.Changelog.Method == models.FailedToFindVersionInChangelog {
+			continue
+		}
+		scanner := bufio.NewScanner(strings.NewReader(pack.Changelog.Contents))
+		for scanner.Scan() {
+			if matches := cveRe.FindAllString(scanner.Text(), -1); 0 < len(matches) {
+				for _, m := range matches {
+					cveIDs = util.AppendIfMissing(cveIDs, m)
+				}
+			}
+		}
+		packCveIDs[name] = cveIDs
+	}
+
+	// transform datastructure
+	// - From
+	//	  "packname": []{"CVE-2017-1111", ".../
+	//
+	// - To
+	//	   map {
+	//		 "CVE-2017-1111": "packname",
+	//	   }
+	vinfos := models.VulnInfos{}
+	for name, cveIDs := range packCveIDs {
+		for _, cid := range cveIDs {
+			if v, ok := vinfos[cid]; ok {
+				v.PackageNames = append(v.PackageNames, name)
+				vinfos[cid] = v
+			} else {
+				vinfos[cid] = models.VulnInfo{
+					CveID:        cid,
+					PackageNames: []string{name},
+					Confidence:   models.ChangelogExactMatch,
+				}
+			}
+		}
+	}
+	return vinfos, nil
 }
 
 type distroAdvisoryCveIDs struct {
@@ -658,7 +632,7 @@ type distroAdvisoryCveIDs struct {
 
 // Scaning unsecure packages using yum-plugin-security.
 // Amazon, RHEL, Oracle Linux
-func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos, error) {
+func (o *redhat) scanCveIDsByCommands(updatable models.Packages) (models.VulnInfos, error) {
 	if o.Distro.Family == config.CentOS {
 		// CentOS has no security channel.
 		// So use yum check-update && parse changelog
@@ -689,22 +663,6 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
 	}
 	advIDPackNamesList, err := o.parseYumUpdateinfoListAvailable(r.Stdout)
 
-	// get package name, version, rel to be upgrade.
-	cmd = "LANGUAGE=en_US.UTF-8 yum --color=never check-update"
-	r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
-	if !r.isSuccess(0, 100) {
-		//returns an exit code of 100 if there are available updates.
-		return nil, fmt.Errorf("Failed to SSH: %s", r)
-	}
-	updatable, err := o.parseYumCheckUpdateLines(r.Stdout)
-	if err != nil {
-		return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
-	}
-	o.log.Debugf("%s", pp.Sprintf("%v", updatable))
-
-	// set candidate version info
-	o.Packages.MergeNewVersion(updatable)
-
 	dict := make(map[string]models.Packages)
 	for _, advIDPackNames := range advIDPackNamesList {
 		packages := models.Packages{}
@@ -796,8 +754,6 @@ func (o *redhat) parseYumUpdateinfo(stdout string) (result []distroAdvisoryCveID
 				for cveID := range cveIDsSetInThisSection {
 					foundCveIDs = append(foundCveIDs, cveID)
 				}
-				//TODO remove
-				//  sort.Strings(foundCveIDs)
 
 				result = append(result, distroAdvisoryCveIDs{
 					DistroAdvisory: advisory,
@@ -883,24 +839,6 @@ func (o *redhat) changeSectionState(state int) (newState int) {
 	return newState
 }
 
-var rpmPackageArchPattern = regexp.MustCompile(
-	`^[^ ]+\.(i386|i486|i586|i686|k6|athlon|x86_64|noarch|ppc|alpha|sparc)$`)
-
-func (o *redhat) isRpmPackageNameLine(line string) (bool, error) {
-	s := strings.TrimPrefix(line, "ChangeLog for: ")
-	ss := strings.Split(s, ", ")
-	if len(ss) == 0 {
-		return false, nil
-	}
-	for _, s := range ss {
-		s = strings.TrimRight(s, " \r\n")
-		if !rpmPackageArchPattern.MatchString(s) {
-			return false, nil
-		}
-	}
-	return true, nil
-}
-
 var yumCveIDPattern = regexp.MustCompile(`(CVE-\d{4}-\d{4,})`)
 
 func (o *redhat) parseYumUpdateinfoLineToGetCveIDs(line string) []string {
@@ -1032,9 +970,10 @@ func (o *redhat) clone() osTypeInterface {
 
 func (o *redhat) sudo() bool {
 	switch o.Distro.Family {
-	case config.Amazon:
+	case config.Amazon, config.CentOS:
 		return false
 	default:
+		// RHEL
 		return true
 	}
 }
diff --git a/scan/redhat_test.go b/scan/redhat_test.go
index f3bf219a..e5414fe7 100644
--- a/scan/redhat_test.go
+++ b/scan/redhat_test.go
@@ -6,9 +6,7 @@ it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
@@ -20,6 +18,7 @@ package scan
 import (
 	"reflect"
 	"sort"
+	"strings"
 	"testing"
 	"time"
 
@@ -42,7 +41,7 @@ func TestParseScanedPackagesLineRedhat(t *testing.T) {
 		pack models.Package
 	}{
 		{
-			"openssl	0	1.0.1e	30.el6.11",
+			"openssl	0	1.0.1e	30.el6.11 x86_64",
 			models.Package{
 				Name:    "openssl",
 				Version: "1.0.1e",
@@ -50,7 +49,7 @@ func TestParseScanedPackagesLineRedhat(t *testing.T) {
 			},
 		},
 		{
-			"Percona-Server-shared-56	1	5.6.19	rel67.0.el6",
+			"Percona-Server-shared-56	1	5.6.19	rel67.0.el6 x84_64",
 			models.Package{
 				Name:    "Percona-Server-shared-56",
 				Version: "1:5.6.19",
@@ -60,7 +59,7 @@ func TestParseScanedPackagesLineRedhat(t *testing.T) {
 	}
 
 	for _, tt := range packagetests {
-		p, _ := r.parseScannedPackagesLine(tt.in)
+		p, _ := r.parseInstalledPackagesLine(tt.in)
 		if p.Name != tt.pack.Name {
 			t.Errorf("name: expected %s, actual %s", tt.pack.Name, p.Name)
 		}
@@ -262,54 +261,6 @@ func TestIsDescriptionLine(t *testing.T) {
 	}
 }
 
-func TestIsRpmPackageNameLine(t *testing.T) {
-	r := newRedhat(config.ServerInfo{})
-	var tests = []struct {
-		in    string
-		found bool
-	}{
-		{
-			"stunnel-4.15-2.el5.2.i386",
-			true,
-		},
-		{
-			"iproute-2.6.18-15.el5.i386",
-			true,
-		},
-		{
-			"1:yum-updatesd-0.9-6.el5_10.noarch",
-			true,
-		},
-		{
-			"glibc-2.12-1.192.el6.x86_64",
-			true,
-		},
-		{
-			" glibc-2.12-1.192.el6.x86_64",
-			false,
-		},
-		{
-			"glibc-2.12-1.192.el6.x86_64, iproute-2.6.18-15.el5.i386",
-			true,
-		},
-		{
-			"k6 hoge.i386",
-			false,
-		},
-		{
-			"triathlon",
-			false,
-		},
-	}
-
-	for i, tt := range tests {
-		found, err := r.isRpmPackageNameLine(tt.in)
-		if tt.found != found {
-			t.Errorf("[%d] line: %s, expected %t, actual %t, err %v", i, tt.in, tt.found, found, err)
-		}
-	}
-}
-
 func TestParseYumUpdateinfoToGetSeverity(t *testing.T) {
 	r := newRedhat(config.ServerInfo{})
 	var tests = []struct {
@@ -672,57 +623,64 @@ Description : Package updates are available for Amazon Linux AMI that fix the
 	}
 }
 
+func TestParseYumCheckUpdateLine(t *testing.T) {
+	r := newRedhat(config.ServerInfo{})
+	r.Distro = config.Distro{Family: "centos"}
+	var tests = []struct {
+		in  string
+		out models.Package
+	}{
+		{
+			"zlib 0 1.2.7 17.el7 rhui-REGION-rhel-server-releases",
+			models.Package{
+				Name:       "zlib",
+				NewVersion: "1.2.7",
+				NewRelease: "17.el7",
+				Repository: "rhui-REGION-rhel-server-releases",
+			},
+		},
+		{
+			"shadow-utils 2 4.1.5.1 24.el7 rhui-REGION-rhel-server-releases",
+			models.Package{
+				Name:       "shadow-utils",
+				NewVersion: "2:4.1.5.1",
+				NewRelease: "24.el7",
+				Repository: "rhui-REGION-rhel-server-releases",
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		aPack, err := r.parseUpdatablePacksLine(tt.in)
+		if err != nil {
+			t.Errorf("Error has occurred, err: %s\ntt.in: %v", err, tt.in)
+			return
+		}
+		if !reflect.DeepEqual(tt.out, aPack) {
+			e := pp.Sprintf("%v", tt.out)
+			a := pp.Sprintf("%v", aPack)
+			t.Errorf("expected %s, actual %s", e, a)
+		}
+	}
+}
+
 func TestParseYumCheckUpdateLines(t *testing.T) {
 	r := newRedhat(config.ServerInfo{})
 	r.Distro = config.Distro{Family: "centos"}
-	stdout := `Loaded plugins: changelog, fastestmirror, keys, protect-packages, protectbase, security
-Loading mirror speeds from cached hostfile
- * base: mirror.fairway.ne.jp
- * epel: epel.mirror.srv.co.ge
- * extras: mirror.fairway.ne.jp
- * updates: mirror.fairway.ne.jp
-0 packages excluded due to repository protections
-
-audit-libs.x86_64              2.3.7-5.el6                   base
-bash.x86_64                    4.1.2-33.el6_7.1              updates
-Obsoleting Packages
-python-libs.i686    2.6.6-64.el6   rhui-REGION-rhel-server-releases
-    python-ordereddict.noarch     1.1-3.el6ev    installed
-bind-utils.x86_64                       30:9.3.6-25.P1.el5_11.8          updates
-pytalloc.x86_64                 2.0.7-2.el6                      @CentOS 6.5/6.5
-`
+	stdout := `audit-libs 0 2.3.7 5.el6 base
+bash 0 4.1.2 33.el6_7.1 updates
+python-libs 0 2.6.6 64.el6 rhui-REGION-rhel-server-releases
+python-ordereddict 0 1.1 3.el6ev installed
+bind-utils 30 9.3.6 25.P1.el5_11.8 updates
+pytalloc 0 2.0.7 2.el6 @CentOS 6.5/6.5`
 
 	r.setPackages(models.NewPackages(
-		models.Package{
-			Name:    "audit-libs",
-			Version: "2.3.6",
-			Release: "4.el6",
-		},
-		models.Package{
-			Name:    "bash",
-			Version: "4.1.1",
-			Release: "33",
-		},
-		models.Package{
-			Name:    "python-libs",
-			Version: "2.6.0",
-			Release: "1.1-0",
-		},
-		models.Package{
-			Name:    "python-ordereddict",
-			Version: "1.0",
-			Release: "1",
-		},
-		models.Package{
-			Name:    "bind-utils",
-			Version: "1.0",
-			Release: "1",
-		},
-		models.Package{
-			Name:    "pytalloc",
-			Version: "2.0.1",
-			Release: "0",
-		},
+		models.Package{Name: "audit-libs"},
+		models.Package{Name: "bash"},
+		models.Package{Name: "python-libs"},
+		models.Package{Name: "python-ordereddict"},
+		models.Package{Name: "bind-utils"},
+		models.Package{Name: "pytalloc"},
 	))
 	var tests = []struct {
 		in  string
@@ -733,48 +691,36 @@ pytalloc.x86_64                 2.0.7-2.el6                      @CentOS 6.5/6.5
 			models.NewPackages(
 				models.Package{
 					Name:       "audit-libs",
-					Version:    "2.3.6",
-					Release:    "4.el6",
 					NewVersion: "2.3.7",
 					NewRelease: "5.el6",
 					Repository: "base",
 				},
 				models.Package{
 					Name:       "bash",
-					Version:    "4.1.1",
-					Release:    "33",
 					NewVersion: "4.1.2",
 					NewRelease: "33.el6_7.1",
 					Repository: "updates",
 				},
 				models.Package{
 					Name:       "python-libs",
-					Version:    "2.6.0",
-					Release:    "1.1-0",
 					NewVersion: "2.6.6",
 					NewRelease: "64.el6",
 					Repository: "rhui-REGION-rhel-server-releases",
 				},
 				models.Package{
 					Name:       "python-ordereddict",
-					Version:    "1.0",
-					Release:    "1",
 					NewVersion: "1.1",
 					NewRelease: "3.el6ev",
 					Repository: "installed",
 				},
 				models.Package{
 					Name:       "bind-utils",
-					Version:    "1.0",
-					Release:    "1",
 					NewVersion: "30:9.3.6",
 					NewRelease: "25.P1.el5_11.8",
 					Repository: "updates",
 				},
 				models.Package{
 					Name:       "pytalloc",
-					Version:    "2.0.1",
-					Release:    "0",
 					NewVersion: "2.0.7",
 					NewRelease: "2.el6",
 					Repository: "@CentOS 6.5/6.5",
@@ -784,7 +730,7 @@ pytalloc.x86_64                 2.0.7-2.el6                      @CentOS 6.5/6.5
 	}
 
 	for _, tt := range tests {
-		packages, err := r.parseYumCheckUpdateLines(tt.in)
+		packages, err := r.parseUpdatablePacksLines(tt.in)
 		if err != nil {
 			t.Errorf("Error has occurred, err: %s\ntt.in: %v", err, tt.in)
 			return
@@ -802,29 +748,13 @@ pytalloc.x86_64                 2.0.7-2.el6                      @CentOS 6.5/6.5
 func TestParseYumCheckUpdateLinesAmazon(t *testing.T) {
 	r := newRedhat(config.ServerInfo{})
 	r.Distro = config.Distro{Family: "amazon"}
-	stdout := `Loaded plugins: priorities, update-motd, upgrade-helper
-34 package(s) needed for security, out of 71 available
-
-bind-libs.x86_64           32:9.8.2-0.37.rc1.45.amzn1      amzn-main
-java-1.7.0-openjdk.x86_64  1.7.0.95-2.6.4.0.65.amzn1     amzn-main
-if-not-architecture        100-200                         amzn-main
-`
+	stdout := `bind-libs 32 9.8.2 0.37.rc1.45.amzn1 amzn-main
+java-1.7.0-openjdk  0 1.7.0.95 2.6.4.0.65.amzn1 amzn-main
+if-not-architecture 0 100 200 amzn-main`
 	r.Packages = models.NewPackages(
-		models.Package{
-			Name:    "bind-libs",
-			Version: "9.8.0",
-			Release: "0.33.rc1.45.amzn1",
-		},
-		models.Package{
-			Name:    "java-1.7.0-openjdk",
-			Version: "1.7.0.0",
-			Release: "2.6.4.0.0.amzn1",
-		},
-		models.Package{
-			Name:    "if-not-architecture",
-			Version: "10",
-			Release: "20",
-		},
+		models.Package{Name: "bind-libs"},
+		models.Package{Name: "java-1.7.0-openjdk"},
+		models.Package{Name: "if-not-architecture"},
 	)
 	var tests = []struct {
 		in  string
@@ -835,24 +765,18 @@ if-not-architecture        100-200                         amzn-main
 			models.NewPackages(
 				models.Package{
 					Name:       "bind-libs",
-					Version:    "9.8.0",
-					Release:    "0.33.rc1.45.amzn1",
 					NewVersion: "32:9.8.2",
 					NewRelease: "0.37.rc1.45.amzn1",
 					Repository: "amzn-main",
 				},
 				models.Package{
 					Name:       "java-1.7.0-openjdk",
-					Version:    "1.7.0.0",
-					Release:    "2.6.4.0.0.amzn1",
 					NewVersion: "1.7.0.95",
 					NewRelease: "2.6.4.0.65.amzn1",
 					Repository: "amzn-main",
 				},
 				models.Package{
 					Name:       "if-not-architecture",
-					Version:    "10",
-					Release:    "20",
 					NewVersion: "100",
 					NewRelease: "200",
 					Repository: "amzn-main",
@@ -862,7 +786,7 @@ if-not-architecture        100-200                         amzn-main
 	}
 
 	for _, tt := range tests {
-		packages, err := r.parseYumCheckUpdateLines(tt.in)
+		packages, err := r.parseUpdatablePacksLines(tt.in)
 		if err != nil {
 			t.Errorf("Error has occurred, err: %s\ntt.in: %v", err, tt.in)
 			return
@@ -976,308 +900,407 @@ func TestExtractPackNameVerRel(t *testing.T) {
 
 }
 
-const (
-	/* for CentOS6,7 (yum-util >= 1.1.20) */
-	stdoutCentos6 = `---> Package libaio.x86_64 0:0.3.107-10.el6 will be installed
---> Finished Dependency Resolution
-
-Changes in packages about to be updated:
-
-ChangeLog for: binutils-2.20.51.0.2-5.44.el6.x86_64
-* Mon Dec  7 21:00:00 2015 Nick Clifton  - 2.20.51.0.2-5.44
-- Backport upstream RELRO fixes. (#1227839)
-
-** No ChangeLog for: chkconfig-1.3.49.5-1.el6.x86_64
-
-ChangeLog for: coreutils-8.4-43.el6.x86_64, coreutils-libs-8.4-43.el6.x86_64
-* Wed Feb 10 21:00:00 2016 Ondrej Vasik  - 8.4-43
-- sed should actually be /bin/sed (related #1222140)
-
-* Wed Jan  6 21:00:00 2016 Ondrej Vasik  - 8.4-41
-- colorls.sh,colorls.csh - call utilities with complete path (#1222140)
-- mkdir, mkfifo, mknod - respect default umask/acls when
-  COREUTILS_CHILD_DEFAULT_ACLS envvar is set (to match rhel 7 behaviour,
-
-ChangeLog for: centos-release-6-8.el6.centos.12.3.x86_64
-* Wed May 18 21:00:00 2016 Johnny Hughes  6-8.el6.centos.12.3
-- CentOS-6.8 Released
-- TESTSTRING CVE-0000-0000
-
-ChangeLog for: 12:dhclient-4.1.1-51.P1.el6.centos.x86_64, 12:dhcp-common-4.1.1-51.P1.el6.centos.x86_64
-* Tue May 10 21:00:00 2016 Johnny Hughes  - 12:4.1.1-51.P1
-- created patch 1000 for CentOS Branding
-- replaced vvendor variable with CentOS in the SPEC file
-- TESTSTRING CVE-1111-1111
-
-* Mon Jan 11 21:00:00 2016 Jiri Popelka  - 12:4.1.1-51.P1
-- send unicast request/release via correct interface (#1297445)
-
-* Thu Dec  3 21:00:00 2015 Jiri Popelka  - 12:4.1.1-50.P1
-- Lease table overflow crash. (#1133917)
-- Add ignore-client-uids option. (#1196768)
-- dhclient-script: it's OK if the arping reply comes from our system. (#1204095)
-- VLAN ID is only bottom 12-bits of TCI. (#1259552)
-- dhclient: Make sure link-local address is ready in stateless mode. (#1263466)
-- dhclient-script: make_resolv_conf(): Keep old nameservers
-  if server sends domain-name/search, but no nameservers. (#1269595)
-
-ChangeLog for: file-5.04-30.el6.x86_64, file-libs-5.04-30.el6.x86_64
-* Tue Feb 16 21:00:00 2016 Jan Kaluza  5.04-30
-- fix CVE-2014-3538 (unrestricted regular expression matching)
-
-* Tue Jan  5 21:00:00 2016 Jan Kaluza  5.04-29
-- fix #1284826 - try to read ELF header to detect corrupted one
-
-* Wed Dec 16 21:00:00 2015 Jan Kaluza  5.04-28
-- fix #1263987 - fix bugs found by coverity in the patch
-
-* Thu Nov 26 21:00:00 2015 Jan Kaluza  5.04-27
-- fix CVE-2014-3587 (incomplete fix for CVE-2012-1571)
-- fix CVE-2014-3710 (out-of-bounds read in elf note headers)
-- fix CVE-2014-8116 (multiple DoS issues (resource consumption))
-- fix CVE-2014-8117 (denial of service issue (resource consumption))
-- fix CVE-2014-9620 (limit the number of ELF notes processed)
-- fix CVE-2014-9653 (malformed elf file causes access to uninitialized memory)
-
-
-Dependencies Resolved
-
-`
-	/* for CentOS5 (yum-util < 1.1.20) */
-	stdoutCentos5 = `---> Package portmap.i386 0:4.0-65.2.2.1 set to be updated
---> Finished Dependency Resolution
-
-Changes in packages about to be updated:
-
-libuser-0.54.7-3.el5.i386
-nss_db-2.2-38.el5_11.i386
-* Thu Nov 20 23:00:00 2014 Nalin Dahyabhai  - 2.2-38
-- build without strict aliasing (internal build tooling)
-
-* Sat Nov 15 23:00:00 2014 Nalin Dahyabhai  - 2.2-37
-- pull in fix for a memory leak in nss_db (#1163493)
-
-acpid-1.0.4-12.el5.i386
-* Thu Oct  6 00:00:00 2011 Jiri Skala  - 1.0.4-12
-- Resolves: #729769 - acpid dumping useless info to log
-
-nash-5.1.19.6-82.el5.i386, mkinitrd-5.1.19.6-82.el5.i386
-* Tue Apr 15 00:00:00 2014 Brian C. Lane  5.1.19.6-82
-- Use ! instead of / when searching sysfs for ccis device
-  Resolves: rhbz#988020
-- Always include ahci module (except on s390) (bcl)
-  Resolves: rhbz#978245
-- Prompt to recreate default initrd (karsten)
-  Resolves: rhbz#472764
-
-util-linux-2.13-0.59.el5_8.i386
-* Wed Oct 17 00:00:00 2012 Karel Zak  2.13-0.59.el5_8
-- fix #865791 - fdisk fails to partition disk not in use
-
-* Wed Dec 21 23:00:00 2011 Karel Zak  2.13-0.59
-- fix #768382 - CVE-2011-1675 CVE-2011-1677 util-linux various flaws
-
-* Wed Oct 26 00:00:00 2011 Karel Zak  2.13-0.58
-- fix #677452 - util-linux fails to build with gettext-0.17
-
-30:bind-utils-9.3.6-25.P1.el5_11.8.i386, 30:bind-libs-9.3.6-25.P1.el5_11.8.i386
-* Mon Mar 14 23:00:00 2016 Tomas Hozza  - 30:9.3.6-25.P1.8
-- Fix issue with patch for CVE-2016-1285 and CVE-2016-1286 found by test suite
-
-* Wed Mar  9 23:00:00 2016 Tomas Hozza  - 30:9.3.6-25.P1.7
-- Fix CVE-2016-1285 and CVE-2016-1286
-
-* Mon Jan 18 23:00:00 2016 Tomas Hozza  - 30:9.3.6-25.P1.6
-- Fix CVE-2015-8704
-
-* Thu Sep  3 00:00:00 2015 Tomas Hozza  - 30:9.3.6-25.P1.5
-- Fix CVE-2015-8000
-
-
-Dependencies Resolved
-
-`
-)
-
-func TestGetChangelogCVELines(t *testing.T) {
-	var testsCentos6 = []struct {
-		in  models.Package
-		out string
-	}{
-		{
-			models.Package{
-				Name:       "binutils",
-				NewVersion: "2.20.51.0.2",
-				NewRelease: "5.44.el6",
-			},
-			"",
-		},
-		{
-			models.Package{
-				Name:       "centos-release",
-				NewVersion: "6",
-				NewRelease: "8.el6.centos.12.3",
-			},
-			`- TESTSTRING CVE-0000-0000
-`,
-		},
-		{
-			models.Package{
-				Name:       "dhclient",
-				NewVersion: "12:4.1.1",
-				NewRelease: "51.P1.el6.centos",
-			},
-			`- TESTSTRING CVE-1111-1111
-`,
-		},
-		{
-			models.Package{
-				Name:       "dhcp-common",
-				NewVersion: "12:4.1.1",
-				NewRelease: "51.P1.el6.centos",
-			},
-			`- TESTSTRING CVE-1111-1111
-`,
-		},
-		{
-			models.Package{
-				Name:       "coreutils-libs",
-				NewVersion: "8.4",
-				NewRelease: "43.el6",
-			},
-			"",
-		},
-		{
-			models.Package{
-				Name:       "file",
-				NewVersion: "5.04",
-				NewRelease: "30.el6",
-			},
-			`- fix CVE-2014-3538 (unrestricted regular expression matching)
-- fix CVE-2014-3587 (incomplete fix for CVE-2012-1571)
-- fix CVE-2014-3710 (out-of-bounds read in elf note headers)
-- fix CVE-2014-8116 (multiple DoS issues (resource consumption))
-- fix CVE-2014-8117 (denial of service issue (resource consumption))
-- fix CVE-2014-9620 (limit the number of ELF notes processed)
-- fix CVE-2014-9653 (malformed elf file causes access to uninitialized memory)
-`,
-		},
-		{
-			models.Package{
-				Name:       "file-libs",
-				NewVersion: "5.04",
-				NewRelease: "30.el6",
-			},
-			`- fix CVE-2014-3538 (unrestricted regular expression matching)
-- fix CVE-2014-3587 (incomplete fix for CVE-2012-1571)
-- fix CVE-2014-3710 (out-of-bounds read in elf note headers)
-- fix CVE-2014-8116 (multiple DoS issues (resource consumption))
-- fix CVE-2014-8117 (denial of service issue (resource consumption))
-- fix CVE-2014-9620 (limit the number of ELF notes processed)
-- fix CVE-2014-9653 (malformed elf file causes access to uninitialized memory)
-`,
-		},
-	}
-
+func TestGetDiffChangelog(t *testing.T) {
 	r := newRedhat(config.ServerInfo{})
-	r.Distro = config.Distro{
-		Family:  "centos",
-		Release: "6.7",
-	}
-	for _, tt := range testsCentos6 {
-		rpm2changelog, err := r.divideChangelogByPackage(stdoutCentos6)
-		if err != nil {
-			t.Errorf("err: %s", err)
-		}
-		changelog := r.getChangelogCVELines(rpm2changelog, tt.in)
-		if tt.out != changelog {
-			t.Errorf("line: expected %s, actual %s, tt: %#v", tt.out, changelog, tt)
-		}
+	type in struct {
+		pack      models.Package
+		changelog string
 	}
 
-	var testsCentos5 = []struct {
-		in  models.Package
+	var tests = []struct {
+		in  in
 		out string
 	}{
+		// 0
 		{
-			models.Package{
-				Name:       "libuser",
-				NewVersion: "0.54.7",
-				NewRelease: "3.el5",
+			in: in{
+				pack: models.Package{
+					Version: "2017a",
+					Release: "1",
+				},
+				changelog: `* Mon Mar 20 12:00:00 2017 Patsy Franklin  - 2017b-1
+- Rebase to tzdata-2017b.
+  - Haiti resumed DST on March 12, 2017.
+
+* Thu Mar  2 12:00:00 2017 Patsy Franklin  - 2017a-1
+- Rebase to tzdata-2017a
+  - Mongolia no longer observes DST. (BZ #1425222)
+  - Add upstream patch to fix over-runing of POSIX limit on zone abbreviations.
+- Add zone1970.tab file to the install list. (BZ #1427694)
+
+* Wed Nov 23 12:00:00 2016 Patsy Franklin  - 2016j-1
+- Rebase to tzdata-2016ij
+  - Saratov region of Russia is moving from +03 offset to +04 offset
+    on 2016-12-04.`,
 			},
-			"",
+			out: `* Mon Mar 20 12:00:00 2017 Patsy Franklin  - 2017b-1
+- Rebase to tzdata-2017b.
+  - Haiti resumed DST on March 12, 2017.`,
 		},
+		// 1
 		{
-			models.Package{
-				Name:       "nss_db",
-				NewVersion: "2.2",
-				NewRelease: "38.el5_11",
+			in: in{
+				pack: models.Package{
+					Version: "2004e",
+					Release: "2",
+				},
+				changelog: `* Mon Mar 20 12:00:00 2017 Patsy Franklin  - 2017b-1
+- Rebase to tzdata-2017b.
+  - Haiti resumed DST on March 12, 2017.
+
+* Wed Nov 23 12:00:00 2016 Patsy Franklin  - 2016j-1
+- Rebase to tzdata-2016ij
+  - Saratov region of Russia is moving from +03 offset to +04 offset
+    on 2016-12-04.
+
+* Mon Nov 29 12:00:00 2004 Jakub Jelinek  2004g-1
+- 2004g (#141107)
+- updates for Cuba
+
+* Mon Oct 11 12:00:00 2004 Jakub Jelinek  2004e-2
+- 2004e (#135194)
+- updates for Brazil, Uruguay and Argentina`,
 			},
-			"",
+			out: `* Mon Mar 20 12:00:00 2017 Patsy Franklin  - 2017b-1
+- Rebase to tzdata-2017b.
+  - Haiti resumed DST on March 12, 2017.
+
+* Wed Nov 23 12:00:00 2016 Patsy Franklin  - 2016j-1
+- Rebase to tzdata-2016ij
+  - Saratov region of Russia is moving from +03 offset to +04 offset
+    on 2016-12-04.
+
+* Mon Nov 29 12:00:00 2004 Jakub Jelinek  2004g-1
+- 2004g (#141107)
+- updates for Cuba`,
 		},
+		// 2
 		{
-			models.Package{
-				Name:       "acpid",
-				NewVersion: "1.0.4",
-				NewRelease: "82.el5",
+			in: in{
+				pack: models.Package{
+					Version: "2016j",
+					Release: "1",
+				},
+				changelog: `* Mon Mar 20 12:00:00 2017 Patsy Franklin  -2017b-1
+- Rebase to tzdata-2017b.
+  - Haiti resumed DST on March 12, 2017.
+
+* Wed Nov 23 12:00:00 2016 Patsy Franklin  -2016j-1
+- Rebase to tzdata-2016ij
+  - Saratov region of Russia is moving from +03 offset to +04 offset
+    on 2016-12-04.`,
 			},
-			"",
+			out: `* Mon Mar 20 12:00:00 2017 Patsy Franklin  -2017b-1
+- Rebase to tzdata-2017b.
+  - Haiti resumed DST on March 12, 2017.`,
 		},
+		// 3
 		{
-			models.Package{
-				Name:       "mkinitrd",
-				NewVersion: "5.1.19.6",
-				NewRelease: "82.el5",
+			in: in{
+				pack: models.Package{
+					Version: "3.10.0",
+					Release: "327.22.1.el7",
+				},
+				changelog: `* Thu Jun  9 21:00:00 2016 Alexander Gordeev  [3.10.0-327.22.2.el7]
+- [infiniband] security: Restrict use of the write() interface (Don Dutile) [1332553 1316685] {CVE-2016-4565}
+
+* Mon May 16 21:00:00 2016 Alexander Gordeev  [3.10.0-327.22.1.el7]
+- [mm] mmu_notifier: fix memory corruption (Jerome Glisse) [1335727 1307042]
+- [misc] cxl: Increase timeout for detection of AFU mmio hang (Steve Best) [1335419 1329682]
+- [misc] cxl: Configure the PSL for two CAPI ports on POWER8NVL (Steve Best) [1336389 1278793]`,
 			},
-			"",
+			out: `* Thu Jun  9 21:00:00 2016 Alexander Gordeev  [3.10.0-327.22.2.el7]
+- [infiniband] security: Restrict use of the write() interface (Don Dutile) [1332553 1316685] {CVE-2016-4565}`,
 		},
+		// 4
 		{
-			models.Package{
-				Name:       "util-linux",
-				NewVersion: "2.13",
-				NewRelease: "0.59.el5_8",
+			in: in{
+				pack: models.Package{
+					Version: "6.6.1p1",
+					Release: "34",
+				},
+
+				changelog: `* Wed Mar  1 21:00:00 2017 Jakub Jelen  - 6.6.1p1-35 + 0.9.3-9
+- Do not send SD_NOTIFY from forked childern (#1381997)
+
+* Fri Feb 24 21:00:00 2017 Jakub Jelen  - 6.6.1p1-34 + 0.9.3-9
+- Add SD_NOTIFY code to help systemd to track running service (#1381997)`,
 			},
-			`- fix #768382 - CVE-2011-1675 CVE-2011-1677 util-linux various flaws
-`,
+			out: `* Wed Mar  1 21:00:00 2017 Jakub Jelen  - 6.6.1p1-35
+- Do not send SD_NOTIFY from forked childern (#1381997)`,
 		},
+		// 5
 		{
-			models.Package{
-				Name:       "bind-libs",
-				NewVersion: "30:9.3.6",
-				NewRelease: "25.P1.el5_11.8",
+			in: in{
+				pack: models.Package{
+					Version: "2.1.23",
+					Release: "15.el6",
+				},
+				changelog: `* Fri Feb 27 12:00:00 2015 Jakub Jelen  2.1.23-15.2
+- Support AIX SASL GSSAPI (#1174315)
+
+* Tue Nov 18 12:00:00 2014 Petr Lautrbach  2.1.23-15.1
+- check a context value in sasl_gss_encode() (#1087221)
+
+* Mon Jun 23 12:00:00 2014 Petr Lautrbach  2.1.23-15
+- don't use " for saslauth user's description (#1081445)
+- backport the ad_compat option (#994242)
+- fixed a memory leak in the client side DIGEST-MD5 code (#838628)`,
 			},
-			`- Fix issue with patch for CVE-2016-1285 and CVE-2016-1286 found by test suite
-- Fix CVE-2016-1285 and CVE-2016-1286
-- Fix CVE-2015-8704
-- Fix CVE-2015-8000
-`,
+			out: `* Fri Feb 27 12:00:00 2015 Jakub Jelen  2.1.23-15.2
+- Support AIX SASL GSSAPI (#1174315)
+
+* Tue Nov 18 12:00:00 2014 Petr Lautrbach  2.1.23-15.1
+- check a context value in sasl_gss_encode() (#1087221)`,
 		},
+		// 6
 		{
-			models.Package{
-				Name:       "bind-utils",
-				NewVersion: "30:9.3.6",
-				NewRelease: "25.P1.el5_11.8",
+			in: in{
+				pack: models.Package{
+					Version: "3.6.20",
+					Release: "1.el6",
+				},
+				changelog: `* Wed Jul 29 12:00:00 2015 Jan Stanek  - 3.6.20-1.2
+- Add patch for compiler warnings highlighted by rpmdiff.
+  Related: rhbz#1244727
+
+* Wed Jul 22 12:00:00 2015 Viktor Jancik  - 3.6.20-1.el6_7.1
+- fix for CVE-2015-3416
+  Resolves: #1244727
+
+* Tue Nov 17 12:00:00 2009 Panu Matilainen  - 3.6.20-1
+- update to 3.6.20 (http://www.sqlite.org/releaselog/3_6_20.html)
+
+* Tue Oct  6 12:00:00 2009 Panu Matilainen  - 3.6.18-1
+- update to 3.6.18 (http://www.sqlite.org/releaselog/3_6_18.html)
+- drop no longer needed test-disabler patches`,
 			},
-			`- Fix issue with patch for CVE-2016-1285 and CVE-2016-1286 found by test suite
-- Fix CVE-2016-1285 and CVE-2016-1286
-- Fix CVE-2015-8704
-- Fix CVE-2015-8000
-`,
+			out: `* Wed Jul 29 12:00:00 2015 Jan Stanek  - 3.6.20-1.2
+- Add patch for compiler warnings highlighted by rpmdiff.
+  Related: rhbz#1244727
+
+* Wed Jul 22 12:00:00 2015 Viktor Jancik  - 3.6.20-1.el6_7.1
+- fix for CVE-2015-3416
+  Resolves: #1244727`,
+		},
+		/*
+					// 7
+					{
+						in: in{
+							pack: models.Package{
+								Version: "2:7.4.160",
+								Release: "1.el7",
+							},
+							changelog: `* Mon Dec 12 21:00:00 2016 Karsten Hopp  7.4.160-1.1
+			- add fix for CVE-2016-1248
+
+			* Wed Jan 29 21:00:00 2014 Karsten Hopp  7.4.160-1
+			- patchlevel 160
+			- Resolves: rhbz#1059321`,
+						},
+						out: `* Mon Dec 12 21:00:00 2016 Karsten Hopp  7.4.160-1.1
+			- add fix for CVE-2016-1248`,
+					},
+					// 8
+					{
+						in: in{
+							pack: models.Package{
+								Version: "2:1.26",
+								Release: "29.el7",
+							},
+							changelog: `* Mon Jun 20 21:00:00 2016 Pavel Raiskup  - 1.26-31
+			- avoid double free in selinux code (rhbz#1347396)
+
+			* Thu Jun  4 21:00:00 2015 Pavel Raiskup  - 1.26-30
+			- don't mistakenly set default ACLs (#1220890)
+
+			* Fri Jan 24 21:00:00 2014 Daniel Mach  - 2:1.26-29
+			- Mass rebuild 2014-01-24`,
+						},
+						out: `* Mon Jun 20 21:00:00 2016 Pavel Raiskup  - 1.26-31
+			- avoid double free in selinux code (rhbz#1347396)
+
+			* Thu Jun  4 21:00:00 2015 Pavel Raiskup  - 1.26-30
+			- don't mistakenly set default ACLs (#1220890)`,
+					},
+					// 9
+					{
+						in: in{
+							pack: models.Package{
+								Version: "1:1.0.1e",
+								Release: "51.el7_2.5",
+							},
+							changelog: `* Mon Feb  6 21:00:00 2017 Tomáš Mráz  1.0.1e-60.1
+			- fix CVE-2017-3731 - DoS via truncated packets with RC4-MD5 cipher
+			- fix CVE-2016-8610 - DoS of single-threaded servers via excessive alerts
+
+			* Fri Dec  4 21:00:00 2015 Tomáš Mráz  1.0.1e-52
+			- fix CVE-2015-3194 - certificate verify crash with missing PSS parameter
+			- fix CVE-2015-3195 - X509_ATTRIBUTE memory leak
+			- fix CVE-2015-3196 - race condition when handling PSK identity hint
+
+			* Tue Jun 23 21:00:00 2015 Tomáš Mráz  1.0.1e-51
+			- fix the CVE-2015-1791 fix (broken server side renegotiation)`,
+						},
+						out: `* Mon Feb  6 21:00:00 2017 Tomáš Mráz  1.0.1e-60.1
+			- fix CVE-2017-3731 - DoS via truncated packets with RC4-MD5 cipher
+			- fix CVE-2016-8610 - DoS of single-threaded servers via excessive alerts
+
+			* Fri Dec  4 21:00:00 2015 Tomáš Mráz  1.0.1e-52
+			- fix CVE-2015-3194 - certificate verify crash with missing PSS parameter
+			- fix CVE-2015-3195 - X509_ATTRIBUTE memory leak
+			- fix CVE-2015-3196 - race condition when handling PSK identity hint`,
+					},
+					// 10
+					{
+						in: in{
+							pack: models.Package{
+								Version: "1:5.5.47",
+								Release: "1.el7_2",
+							},
+							changelog: `* Wed Sep 21 21:00:00 2016 Honza Horak  - 5.5.52-1
+			- Rebase to 5.5.52, that also include fix for CVE-2016-6662
+			  Resolves: #1377974
+
+			* Thu Feb 18 21:00:00 2016 Jakub Dorňák  - 1:5.5.47-2
+			- Add warning to /usr/lib/tmpfiles.d/mariadb.conf
+			  Resolves: #1241623
+
+			* Wed Feb  3 21:00:00 2016 Jakub Dorňák  - 1:5.5.47-1
+			- Rebase to 5.5.47
+			  Also fixes: CVE-2015-4792 CVE-2015-4802 CVE-2015-4815 CVE-2015-4816
+			  CVE-2015-4819 CVE-2015-4826 CVE-2015-4830 CVE-2015-4836 CVE-2015-4858
+			  CVE-2015-4861 CVE-2015-4870 CVE-2015-4879 CVE-2015-4913 CVE-2015-7744
+			  CVE-2016-0505 CVE-2016-0546 CVE-2016-0596 CVE-2016-0597 CVE-2016-0598
+			  CVE-2016-0600 CVE-2016-0606 CVE-2016-0608 CVE-2016-0609 CVE-2016-0616
+			  CVE-2016-2047
+			  Resolves: #1300621`,
+						},
+						out: `* Wed Sep 21 21:00:00 2016 Honza Horak  - 5.5.52-1
+			- Rebase to 5.5.52, that also include fix for CVE-2016-6662
+			  Resolves: #1377974
+
+			* Thu Feb 18 21:00:00 2016 Jakub Dorňák  - 1:5.5.47-2
+			- Add warning to /usr/lib/tmpfiles.d/mariadb.conf
+			  Resolves: #1241623`,
+					},
+		*/
+		// 11
+		{
+			in: in{
+				pack: models.Package{
+					Version: "0.252",
+					Release: "8.1.el7",
+				},
+				changelog: `* Thu Sep 29 21:00:00 2016 Vitezslav Crhonek  - 0.252-8.4
+- Remove wrong entry from usb ids.
+  Resolves: #1380159
+
+* Mon Sep 26 21:00:00 2016 Vitezslav Crhonek  - 0.252-8.3
+- Updated pci, usb and vendor ids.
+- Resolves: rhbz#1292382
+
+* Tue Jun 28 21:00:00 2016 Michal Minar  0.252-8.2
+- Updated pci, usb and vendor ids.
+- Resolves: rhbz#1292382
+- Resolves: rhbz#1291614
+- Resolves: rhbz#1324198
+
+* Fri Oct 23 21:00:00 2015 Michal Minar  0.252-8.1
+- Updated pci, usb and vendor ids.`,
+			},
+			out: `* Thu Sep 29 21:00:00 2016 Vitezslav Crhonek  - 0.252-8.4
+- Remove wrong entry from usb ids.
+  Resolves: #1380159
+
+* Mon Sep 26 21:00:00 2016 Vitezslav Crhonek  - 0.252-8.3
+- Updated pci, usb and vendor ids.
+- Resolves: rhbz#1292382
+
+* Tue Jun 28 21:00:00 2016 Michal Minar  0.252-8.2
+- Updated pci, usb and vendor ids.
+- Resolves: rhbz#1292382
+- Resolves: rhbz#1291614
+- Resolves: rhbz#1324198`,
+		},
+		// 12
+		{
+			in: in{
+				pack: models.Package{
+					Version: "1:2.02",
+					Release: "0.34.el7_2",
+				},
+				changelog: `* Mon Aug 29 21:00:00 2016 Peter Jones  - 2.02-0.44
+- Work around tftp servers that don't work with multiple consecutive slashes in
+  file paths.
+  Resolves: rhbz#1217243`,
+			},
+			out: `* Mon Aug 29 21:00:00 2016 Peter Jones  - 2.02-0.44
+- Work around tftp servers that don't work with multiple consecutive slashes in
+  file paths.
+  Resolves: rhbz#1217243`,
 		},
 	}
 
-	r.Distro = config.Distro{
-		Family:  "centos",
-		Release: "5.6",
-	}
-	for _, tt := range testsCentos5 {
-		rpm2changelog, err := r.divideChangelogByPackage(stdoutCentos5)
-		if err != nil {
-			t.Errorf("err: %s", err)
-		}
-		changelog := r.getChangelogCVELines(rpm2changelog, tt.in)
-		if tt.out != changelog {
-			t.Errorf("line: expected %s, actual %s, tt: %#v", tt.out, changelog, tt)
+	for i, tt := range tests {
+		diff, _ := r.getDiffChangelog(tt.in.pack, tt.in.changelog)
+		if tt.out != diff {
+			t.Errorf("[%d] name: expected \n%s\nactual \n%s", i, tt.out, diff)
 		}
 	}
+
+}
+
+func TestDivideChangelogsIntoEachPackages(t *testing.T) {
+	r := newRedhat(config.ServerInfo{})
+	type in struct {
+		pack      models.Package
+		changelog string
+	}
+
+	var tests = []struct {
+		in  string
+		out map[string]string
+	}{
+		{
+			in: `==================== Available Packages ====================
+1:NetworkManager-1.4.0-20.el7_3.x86_64   rhui-rhel-7-server-rhui-rpms
+* Mon Apr 24 21:00:00 2017 Beniamino Galvani  - 1:1.4.0-20
+- vlan: use parent interface mtu as default (rh#1414186)
+
+* Wed Mar 29 21:00:00 2017 Beniamino Galvani  - 1:1.4.0-19
+- core: alyways force a sync of the default route (rh#1431268)
+
+
+1:NetworkManager-0.9.9.1-25.git20140326. rhui-rhel-7-server-rhui-optional-rpms
+* Tue Jul  1 21:00:00 2014 Jiří Klimeš  - 1:0.9.9.1-25.git20140326
+- core: fix MTU handling while merging/subtracting IP configs (rh #1093231)
+
+* Mon Jun 23 21:00:00 2014 Thomas Haller  - 1:0.9.9.1-24.git20140326
+- core: fix crash on failure of reading bridge sysctl values (rh #1112020)`,
+			out: map[string]string{
+				"1:NetworkManager-1.4.0-20.el7_3.x86_64": `* Mon Apr 24 21:00:00 2017 Beniamino Galvani  - 1:1.4.0-20
+- vlan: use parent interface mtu as default (rh#1414186)
+
+* Wed Mar 29 21:00:00 2017 Beniamino Galvani  - 1:1.4.0-19
+- core: alyways force a sync of the default route (rh#1431268)`,
+
+				"1:NetworkManager-0.9.9.1-25.git20140326.": `* Tue Jul  1 21:00:00 2014 Jiří Klimeš  - 1:0.9.9.1-25.git20140326
+- core: fix MTU handling while merging/subtracting IP configs (rh #1093231)
+
+* Mon Jun 23 21:00:00 2014 Thomas Haller  - 1:0.9.9.1-24.git20140326
+- core: fix crash on failure of reading bridge sysctl values (rh #1112020)`,
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		changelogs := r.divideChangelogsIntoEachPackages(tt.in)
+		for k, v := range tt.out {
+			if strings.TrimSpace(v) != strings.TrimSpace(changelogs[k]) {
+				t.Errorf("expected: %v\nactual: %v", pp.Sprint(tt.out), pp.Sprint(changelogs))
+			}
+		}
+	}
+
 }