DNF (Fork of YUM) Command to Manage Packages on Fedora, CentOS 8 and RHEL 8 Systems

DNF stands for “Dandified Yum”. This is the next generation of yum package manager (Fork of Yum).

The DNF command uses the libsolv, hawkey, ibrepo and libcomps libraries to manage RPM packages.

It was introduced in Fedora 18, which has been the default package manager since Fedora 22.

DNF is a software package manager that installs, updates, and removes packages on RPM-based Linux distributions. It automatically computes dependencies and determines the actions required to install packages.

Yum has been replaced by DNF due to several chronic issues which have not been solved in yum like, poor performance, high memory usage, slowness for dependency resolution, etc.

This is not just about fixing pending issues in yum. Furthermore, DNF added many features to enable seamless management of packages in an RPM-based system.

1) How to Install DNF on RHEL 7/CentOS 7 Linux

DNF is installed on RHEL 8 and CentOS 8 systems by default. Run the following command to install on CentOS 7 and RHEL 8 systems.

The DNF package can be installed on the CentOS 7 system by the yum command, as it was part of the Extras Repo. Enable “rhel-7-server-extras-rpms” repo for RHEL 7 system.

# yum install dnf

The General Syntax of the DNF Command

The syntax of the DNF command resembles YUM, and you can see a lot of similarity between them.

dnf [Option] [Command] [Package_Name]

Location of the DNF Configuration Files

Main Configuration: /etc/dnf/dnf.conf
Repository: /etc/yum.repos.d/
Cache Files: /var/cache/dnf

Popular DNF Commands are as follows

+---------------------+-------------------------------------------------------------------------------------------+
|      Command        |                                         Description                                       |
+---------------------+-------------------------------------------------------------------------------------------+
|repolist             | Display the configured software repositories                                              |
|install              | Install a single or multiple packages on your system                                      |
|upgrade              | Upgrade a package or packages on your system                                              |
|upgrade-minimal      | Upgrade, but only 'newest' package match which fixes a problem that affects your system   |
|list                 | List a package or groups of packages                                                      |
|info                 | Display details about a package or group of packages                                      |
|updateinfo           | Display advisories about packages                                                         |
|search               | Search package details for the given string                                               |
|check-update         | Check for available package upgrades                                                      |
|remove               | Remove a package or packages from your system                                             |
|reinstall            | Reinstall a package                                                                       |
|downgrade            | Downgrade a package                                                                       |
|autoremove           | Remove all unneeded packages that were originally installed as dependencies               |
|distro-sync          | Synchronize installed packages to the latest available versions                           |
|makecache            | Generate the metadata cache                                                               |
|repository-packages  | Run commands on top of all packages in given repository                                   |
|provides             | Find what package provides the given value                                                |
|group                | Display, or use, the groups information                                                   |
|history              | Display, or use, the transaction history                                                  |
|clean                | Remove cached data                                                                        |
|help                 | Display a helpful usage message                                                           |
+---------------------+-------------------------------------------------------------------------------------------+

2) How to List Repositories on CentOS 8/RHEL 8/Fedora Systems Using the dnf Command

This command lists all repositories that are enabled by default and gives you the options to list other information. This provides more detailed information when adding the -v option with the dnf command.

Also, it does not force synchronization of expired metadata and you can force sync all repositories enabled with the --refresh switch.

This is the standard command to list repositories that are enabled on the system.

$ sudo dnf repolist
Last metadata expiration check: 0:01:18 ago on Tue 10 Dec 2019 02:05:20 PM IST.
repo id                       repo name                                                           status
AppStream                     CentOS-8 - AppStream                                                5,089
BaseOS                        CentOS-8 - Base                                                     2,843
*epel                         Extra Packages for Enterprise Linux 8 - x86_64                      3,625
extras                        CentOS-8 - Extras                                                       3

Alternatively, you can run the following command to list the enabled repositories on the system.

$ dnf repolist enabled
or
$ dnf repolist --enabled

Run the following command to list the disabled repositories on the system.

$ dnf repolist disabled
or
$ dnf repolist --disabled

Run the following command to list all repositories (enabled and disabled) on the system.

$ dnf repolist all
or
$ dnf repolist --all

To see detailed information about each of the repositories, add the -v switch with the dnf command. It displays repo-id, repo-name and so on.

$ dnf repolist -v
.
.
Repo-id      : BaseOS
Repo-name    : CentOS-8 - Base
Repo-revision: 8.0.1905
Repo-distro-tags: [cpe:/o:centos:centos:8]:  , 8, C, O, S, e, n, t
Repo-updated : Fri 01 Nov 2019 01:44:36 AM IST
Repo-pkgs    : 2,843
Repo-size    : 3.8 G
Repo-mirrors : http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=BaseOS&infra=stock
Repo-baseurl : http://mirrors.piconets.webwerks.in/centos-mirror/8.0.1905/BaseOS/x86_64/os/ (9 more)
Repo-expire  : 172,800 second(s) (last: Tue 10 Dec 2019 02:05:01 PM IST)
Repo-filename: /etc/yum.repos.d/CentOS-Base.repo
.
.

3) How to Install a Package or Packages on CentOS/RHEL/Fedora Systems Using the dnf Command

To install a package or package on CentOS/RHEL/Fedora systems, use the below dnf command.

In our case, we are going to install nano, MariaDB-server and MariaDB-client packages. By default, every time DNF asks for your confirmation to install a package, and add the -y option to avoid confirmation.

To install a single package

$ sudo dnf install nano

To install multiple packages

$ sudo dnf install MariaDB-server MariaDB-client

Add the -y option with dnf to install a package without your confirmation.

$ sudo dnf install nano -y

Use the following command to install a package from a specific repository. In this case, we are installing the “htop” package from the EPEL repository.

# dnf --disablerepo="*" --enablerepo=epel install htop

To install local rpm file, run the below command.

$ sudo dnf install /path/to/file.rpm

To install an rpm package directly from the URL, run the command below.

$ sudo dnf install https://xyz.com/file.rpm

To install a package that provides /usr/bin/[xxx] file, run the below command. For example, the sar application is part of the “systat” package, but most of us don’t know their parent package name. However, it is difficult to find their parent package name, but this command allows you to install it without knowing the parent package name.

$ sudo dnf install /usr/bin/sar

Run the following command to install all packages that belong to “FEDORA-2018-b7b99fe852” advisory.

$ sudo dnf install --advisory=FEDORA-2018-b7b99fe852 \*

4) How to Remove a Package or Packages on CentOS/RHEL/Fedora Systems Using the dnf Command

As part of package removal, the dnf command deletes a given package or packages with its dependencies.

In our case, we are going to remove the nano package from the system.

# dnf remove nano -y

Alternatively, you can use the following command. It’s deprecated alias for the remove command.

# dnf erase nano -y

The following command deletes the old version of the duplicate packages.

# dnf remove --duplicates

5) How to Remove All “leaf” Packages on CentOS/RHEL/Fedora Systems Using the dnf Command

This removes all the packages that were originally installed as dependencies for other packages that are no longer needed.

# dnf autoremove

6) How to Update a Package or Packages on CentOS/RHEL/Fedora Systems Using the dnf Command

These commands allow you to upgrade a package or all installed packages, or a package to a specific version and more.

Run the below command to update all installed packages to the latest available version.

# dnf upgrade

The below command performs similar functions as above. This will install all available updates on your computer.

# dnf distro-sync

Run the below command to update a given package or packages to the latest available version.

# dnf upgrade [Package_Name]
# dnf upgrade nano

Run the below command to upgrade a given package or packages to the specified versions.

# dnf upgrade [Package_Version]
# dnf upgrade nano-2.9.8-1

7) How to Check Information about Update Advisories on CentOS/RHEL/Fedora Systems Using the dnf Command

The below commands will display information about update advisories. This shows how many package updates are available for Security, Bug Fixes and Enhancement.

These packages can be upgraded through “dnf upgrade” command.

Run the command below to display the number of advisory types.

# dnf updateinfo summary

Last metadata expiration check: 0:21:19 ago on Wed 11 Dec 2019 10:36:15 AM IST.
Updates Information Summary: available
    1 Bugfix notice(s)

This command displays list of advisories.

# dnf updateinfo list

Last metadata expiration check: 0:21:23 ago on Wed 11 Dec 2019 10:36:15 AM IST.
FEDORA-EPEL-2019-1897c58d3f bugfix epel-release-8-7.el8.noarch

This command will give you detailed information about the given advisory ID.

# dnf updateinfo info FEDORA-EPEL-2019-1897c58d3f

Last metadata expiration check: 0:20:57 ago on Wed 11 Dec 2019 10:36:15 AM IST.
===============================================================================
  epel-release-8-7.el8
===============================================================================
  Update ID: FEDORA-EPEL-2019-1897c58d3f
       Type: bugfix
    Updated: 2019-12-10 07:26:18
       Bugs: 1760182 - Unknown confg values are set
Description: Remove failovermethod from EPEL8 tree. It is no longer needed.
   Severity: None

8) How to Update Only Advisories Available on CentOS/RHEL/Fedora Systems Using the dnf Command

If you only want to update the bugfix, enhancement or security fix packages on CentOS/RHEL/Fedora systems, use the following command.

This command updates each package to the latest version that provides a bugfix, enhancement or security fix.

# dnf upgrade-minimal

This command updates the given package or packages to the latest version that provides a bugfix, enhancement or security fix.

# dnf upgrade-minimal [Package_Name]

9) How to Check Package Updates Available on CentOS/RHEL/Fedora Systems Using the dnf Command

This command checks if any package updates are available on the system.

This command checks whether any updates to your system.

# dnf check-update

Alternatively, you can use the command below to check the available update.

# dnf list updates

The following command checks for updates to the specified package.

# dnf check-update [Package_Name]
# dnf check-update nano

10) How to Check the “Packagedb” Problem on CentOS/RHEL/Fedora Systems Using the dnf Command

This command checks the local packaging and generates information on any issues it has detected. You can limit the “packagedb” check by passing the options --dependencies, --duplicates, --obsoleted or --provides.

# dnf check

11) How to List Installed Packages on CentOS/RHEL/Fedora Systems Using the dnf Command

The dnf list command prints all the packages we know, whether in RPMDB, in a repo, or both. You can control the output according to your needs.

Run the below command to list all packages, present in the RPMDB, in a repo or in both.

# dnf list
or
# dnf list all

Run the below command to list only installed packages in RPMDB.

# dnf list installed

Run the below command to list available packages from repos, excluding installed packages.

# dnf list available

Run the command below to see if a given package is installed. If yes, it shows an output like the one below. Otherwise, it displays the following error message “Error: No matching packages to list”

# dnf list installed httpd
Installed Packages
httpd.x86_64                     2.4.37-12.module_el8.0.0+185+5908b0db                      @AppStream

To list packages installed on the system that are obsoleted.

# dnf list obsoletes

Run the below command to list packages recently added into the repositories.

# dnf list recent

Run the below command to list upgrades available for the installed packages.

# dnf list upgrades

Run the below command to list packages which will be removed by dnf auto-remove command.

# dnf list autoremove

12) How to Search a Package on CentOS/RHEL/Fedora Systems Using the dnf Command

The dnf search command allows you to find a list of available packages based on the given string. It’s very useful when you don’t know exact package name to install.

It search package metadata for the given keywords. Keywords are matched as case-insensitive substrings, globbing is supported. By default lists packages that match all requested keys. Keys are searched in package names and summaries.

In our case, we are going to search the ftpd string and see what will heppen.

# dnf search ftpd

Last metadata expiration check: 0:09:00 ago on Thu 12 Dec 2019 11:23:07 AM IST.
=================================== Name & Summary Matched: ftpd ====================================
pure-ftpd-selinux.x86_64 : SELinux support for Pure-FTPD
======================================== Name Matched: ftpd =========================================
vsftpd.x86_64 : Very Secure Ftp Daemon
pure-ftpd.x86_64 : Lightweight, fast and secure FTP server
nordugrid-arc-gridftpd.x86_64 : ARC gridftp server

The above output shows matching string for ftpd keyword.

13) How to View Installed Package Information on CentOS/RHEL/Fedora Systems Using the dnf Command

The following command is used to list description and summary information about installed and available packages.

This command allows you to check detailed information about any packages available in repos. It shows you varies information about a package like Name, Arch, version, Release, Size, repo name, etc,.

# dnf info httpd
Last metadata expiration check: 23:44:19 ago on Wed 11 Dec 2019 11:35:25 AM IST.
Installed Packages
Name         : httpd
Version      : 2.4.37
Release      : 12.module_el8.0.0+185+5908b0db
Arch         : x86_64
Size         : 4.9 M
Source       : httpd-2.4.37-12.module_el8.0.0+185+5908b0db.src.rpm
Repo         : @System
From repo    : AppStream
Summary      : Apache HTTP Server
URL          : https://httpd.apache.org/
License      : ASL 2.0
Description  : The Apache HTTP Server is a powerful, efficient, and extensible
             : web server.

14) How to Use the “dnf provides” Command

The dnf provides command will find packages that provide the given file. This is useful if you want to find out which package (installed or not) provides this file.

For example, we all know about sar use, and most of us do not know which package provides this file. Use the following command to find it.

# dnf provides sar
Last metadata expiration check: 0:27:57 ago on Thu 12 Dec 2019 11:23:07 AM IST.
sysstat-11.7.3-2.el8.x86_64 : Collection of performance monitoring tools for Linux
Repo        : AppStream
Matched from:
Filename    : /usr/bin/sar

15) How to Use the “dnf makecache” Command

Makecache is used to download and make usable all the metadata for the currently enabled repository on your system.

# dnf makecache
CentOS-8 - AppStream                                                1.6 kB/s | 4.3 kB     00:02    
CentOS-8 - Base                                                     1.4 kB/s | 3.9 kB     00:02    
CentOS-8 - Extras                                                   503  B/s | 1.5 kB     00:03    
Extra Packages for Enterprise Linux 8 - x86_64                      5.6 kB/s |  10 kB     00:01    
Extra Packages for Enterprise Linux 8 - x86_64                      710 kB/s | 4.2 MB     00:06    
Metadata cache created.

16) How to Check Available Package Update on CentOS/RHEL/Fedora Systems Using the dnf Command

This command checks if any updates are available for your system. If any updates are available it will print a list of available updates.

# dnf check-update

Run the following command if you want to check update is available for a given package.

# dnf check-update [Package_Name]
# dnf check-update nano

Run the following command if you want to quickly check what changes have been made to the given package before updating.

# dnf check-update ghostscript.x86_64 --changelog
Last metadata expiration check: 0:01:44 ago on Fri 13 Dec 2019 11:25:15 AM IST.

ghostscript.x86_64                                                                                     9.25-2.el8_0.3                                                                                     AppStream
Changelogs for ghostscript-9.25-2.el8_0.3.x86_64
* Thu Aug 22 12:00:00 AM 2019 Martin Osvald  - 9.25-2.3
- Resolves: #1744010 - CVE-2019-14811 ghostscript: Safer Mode Bypass by .forceput Exposure in .pdf_hook_DSC_Creator (701445)
- Resolves: #1744014 - CVE-2019-14812 ghostscript: Safer Mode Bypass by .forceput Exposure in setuserparams (701444)
- Resolves: #1744005 - CVE-2019-14813 ghostscript: Safer Mode Bypass by .forceput Exposure in setsystemparams (701443)
- Resolves: #1744230 - CVE-2019-14817 ghostscript: Safer Mode Bypass by .forceput Exposure in .pdfexectoken and other procedures (701450)

* Mon Aug 05 12:00:00 AM 2019 Martin Osvald  - 9.25-2.2
- Resolves: #1737336 - CVE-2019-10216 ghostscript: -dSAFER escape via .buildfont1 (701394)

* Thu Mar 28 12:00:00 AM 2019 Martin Osvald  - 9.25-2.1
- Resolves: #1692798 - CVE-2019-3839 ghostscript: missing attack vector
  protections for CVE-2019-6116
- Resolves: #1678170 - CVE-2019-3835 ghostscript: superexec operator
  is available (700585)
- Resolves: #1691414 - CVE-2019-3838 ghostscript: forceput in DefineResource
  is still accessible (700576)
- fix included for ghostscript: Regression: double comment chars
  '%' in gs_init.ps leading to missing metadata
- fix for pdf2dsc regression added to allow fix for CVE-2019-3839

17) How to Downgrade a Package on CentOS/RHEL/Fedora Systems Using the dnf Command

The dnf downgrade command used to downgrade the specified package to lower (previous) version if possible. If you give any specific version of installed package then it downgrades to target version.

# dnf downgrade nano

18) How to Re-Install a Package on CentOS/RHEL/Fedora Systems Using the dnf Command

This command is used to reinstall if they package has already installed. If it’s not installed, you will be getting the following message.

Package nano available, but not installed.
No match for argument: nano
Error: No packages marked for reinstall.

Run the following command to re-install the given package.

# dnf reinstall nano

19) How to List Package Groups Available on CentOS/RHEL/Fedora Systems Using the dnf Command

A list of packages related to each other is grouped together in a group package. Run the following command to list the package groups available on your system.

# dnf group list
or
# dnf grouplist

Last metadata expiration check: 1:38:20 ago on Fri 13 Dec 2019 11:25:15 AM IST.
Available Environment Groups:
   Server with GUI
   Server
   Minimal Install
   KDE Plasma Workspaces
   Virtualization Host
   Custom Operating System
Installed Environment Groups:
   Workstation
Available Groups:
   Container Management
   .NET Core Development
   RPM Development Tools
   Smart Card Support
   Development Tools
   Graphical Administration Tools
   Headless Management
   Legacy UNIX Compatibility
   Network Servers
   Scientific Support
   Security Tools
   System Tools
   Fedora Packager

20) How to View Summary of Groups Available on CentOS/RHEL/Fedora Systems Using the dnf Command

This display overview of how many groups are installed and available on your system.

# dnf group summary
Last metadata expiration check: 1:48:35 ago on Fri 13 Dec 2019 11:25:15 AM IST.
Available Groups: 13

21) How to View a Specified Group Info on CentOS/RHEL/Fedora Systems Using the dnf Command

This command displays the list of packages available in this group.

Each group has three parts and the details are as follows:

  • Mandatory Packages
  • Default Packages
  • Optional Packages
# dnf group info 'Development Tools'

Last metadata expiration check: 1:54:38 ago on Fri 13 Dec 2019 11:25:15 AM IST.

Group: Development Tools
 Description: A basic development environment.
 Mandatory Packages:
   autoconf
   automake
   binutils
   bison
   flex
   gcc
   gcc-c++
   gdb
   glibc-devel
   libtool
   make
   pkgconf
   pkgconf-m4
   pkgconf-pkg-config
   redhat-rpm-config
   rpm-build
   rpm-sign
   strace
 Default Packages:
   asciidoc
   byacc
   ctags
   diffstat
   git
   intltool
   ltrace
   patchutils
   perl-Fedora-VSP
   perl-generators
   pesign
   source-highlight
   systemtap
   valgrind
   valgrind-devel
 Optional Packages:
   cmake
   expect
   rpmdevtools
   rpmlint

22) How to Install a Package Group on CentOS/RHEL/Fedora Systems Using the dnf Command

Run the following command to install a package group.

In this case we are going to install “Development Tools” package group. The editors group has bundled with a lots of packages that are related to editor.

# dnf group install 'Development Tools' -y
or
# dnf groupinstall 'Development Tools' -y

23) How to Update a Package Group on CentOS/RHEL/Fedora Systems Using the dnf Command

Similarly run the following command to update package group to available latest version.

# dnf group update 'Development Tools' -y
or
# dnf groupupdate 'Development Tools' -y

24) How to Remove a Package Group on CentOS/RHEL/Fedora Systems Using the dnf Command

Use the below command to remove the given installed package group.

# dnf group remove 'Development Tools'
or
# dnf group erase 'Development Tools'

25) How to Clear Cached Data on CentOS/RHEL/Fedora Systems Using the dnf Command

By default dnf will cache data such as package and repository metadata to the “/var/cache/dnf” directory when you perform varies dnf operation. This cache can take up a lot space over the period of time. This will allow you to remove all cached data.

Run the below command to remove cache files generated from the repository metadata.

# dnf clean dbcache

Run the below command to mark the repository metadata expired.

# dnf clean expire-cache

Run the below command to remove repository metadata.

# dnf clean metadata

Run the below command to remove any cached packages from the system.

# dnf clean packages

This command eoes all of the above action in one go.

# dnf clean all

26) How to Print dnf History on CentOS/RHEL/Fedora Systems Using the dnf Command

The dnf history command allows the user to view what action has happened in past transactions. All transactions showed in a table.

# dnf history

ID     | Command line             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
     9 | install nano             | 2019-12-12 12:49 | Install        |    1   
     8 | erase nano -y            | 2019-12-11 08:09 | Removed        |    1   
     7 | install nano -y          | 2019-12-11 08:09 | Install        |    1   
     6 | remove nano              | 2019-12-11 08:09 | Removed        |    1   
     5 | install httpd -y         | 2019-12-11 08:08 | Install        |    9   
     4 |                          | 2019-11-10 21:27 | Install        |    4   
     3 | install fping            | 2019-11-09 10:09 | Install        |    1   
     2 | install epel-release     | 2019-11-09 10:04 | Install        |    1   
     1 |                          | 2019-11-09 09:10 | Install        | 1441 EE

Alternatively, you can get the same result using the following command.

# dnf history list

It shows you detailed information about the given transactions. When no transaction is specified, describe what happened during the latest transaction.

# dnf history info
Transaction ID : 9
Begin time     : Thu 12 Dec 2019 12:49:17 PM IST
Begin rpmdb    : 1442:1d39bf569934f62170179ac566e748a34156008a
End time       : Thu 12 Dec 2019 12:49:18 PM IST (1 seconds)
End rpmdb      : 1443:e5cdaaca00923c394bd2533c642c175ec6ce2cf7
User           : root 
Return-Code    : Success
Releasever     : 8
Command Line   : install nano
Packages Altered:
    Install nano-2.9.8-1.el8.x86_64 @BaseOS

Run the following command to view the detailed information about the given ID transactions.

# dnf history info 3
Transaction ID : 3
Begin time     : Sat 09 Nov 2019 10:09:19 AM IST
Begin rpmdb    : 1429:4ea1748d2132285a5bc1929f522f97f80bc5cede
End time       : Sat 09 Nov 2019 10:09:20 AM IST (1 seconds)
End rpmdb      : 1430:7c974a655a4f3a6c0ad5c6b8ab968279e0144581
User           : root 
Return-Code    : Success
Releasever     : 8
Command Line   : install fping
Packages Altered:
    Install fping-4.2-2.el8.x86_64 @epel

Repeat the same action for the specified transaction ID.

# dnf history redo 3

Perform the opposite operation to all operations performed in the specified transaction.

# dnf history undo 3

Undo all transactions performed after the specified transaction.

# dnf history rollback 7

27) How to Enable DNF Automatic Updates on CentOS/RHEL/Fedora Systems Using the dnf Command

You can enable automatic package update by installing the dnf-automatic package.

To do so run the following command.

# dnf install dnf-automatic

After installaing the pacakge, make sure you edit the /etc/dnf/automatic.conf file and replace apply_updates = yes instead of apply_updates = no.

Enable the “dnf-automatic-timer” service once you made the changes in the configuration file.

# systemctl enable dnf-automatic.timer
Created symlink from /etc/systemd/system/basic.target.wants/dnf-automatic.timer to /usr/lib/systemd/system/dnf-automatic.timer

Finally start the service.

systemctl start dnf-automatic.timer

28) How to Mark/Un-Mark a Package on CentOS/RHEL/Fedora Systems Using the dnf Command

The dnf mark command allows you to always keep the specified package on the system, and doesn’t remove this package from the system when the auto-removal command is running.

Run the following command to mark the specified packages as installed by user.

# dnf mark install nano
nano-2.9.8-1.el8.x86_64 marked as user installed.

Run the following command to unmark the specified packages as installed by user.

# dnf mark remove nano
nano-2.9.8-1.el8.x86_64 unmarked as user installed.

29) How Query a Package From the Enabled Repos on CentOS/RHEL/Fedora Systems Using the dnf Command

It searches the given package on the enabled repositories and displays the information. This is equivalent to the rpm “-q” command.

# dnf repoquery htop
Last metadata expiration check: 0:22:18 ago on Sat 14 Dec 2019 02:44:16 PM IST.
htop-0:2.2.0-6.el8.x86_64

30) Visit the dnf Man Page

We have added all possible options in this article but if you are looking for any other option, which is not listed in this article visit man page.

# dnf -help
or
# man dnf

That’s all about the DNF command now, we’ll be bringing you a new topic soon, please stay tune with us..!

Reference link

  • More details about DNF
  • About Magesh Maruthamuthu

    Love to play with all Linux distribution

    View all posts by Magesh Maruthamuthu

    Leave a Reply

    Your email address will not be published. Required fields are marked *