diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 067144761df18780269fb04c690be592a3092aa7..ce7cd633462c6e932d1f51d09b7ebc92e03431cb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,6 +27,7 @@ compile:
     script:
         - echo "Estágio 'build'"
         - apt-get update && apt-get install -y build-essential cmake git
+          libudev-dev
         - git submodule init
         - git submodule update --init --recursive
         - mkdir build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 130fd6d2252116db9cf5f64f8065f998ad0fbeb5..8972ebc300e7712476913d069ca5d9739588163a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,7 +45,6 @@ if ( WIN32 )
 	add_subdirectory ( lib/dtwinver )
 endif ()
 
-
 # headers
 include_directories ( "include" )
 
@@ -66,4 +65,7 @@ target_link_libraries ( agent-v${VERSION_MAJOR}.${VERSION_MINOR} ${CPR_LIBRARIES
 
 if ( WIN32 )
 	target_link_libraries ( agent-v${VERSION_MAJOR}.${VERSION_MINOR} dtwinver )
-endif()
+else ()
+    # libudev
+    target_link_libraries ( agent-v${VERSION_MAJOR}.${VERSION_MINOR} udev )
+endif ()
diff --git a/include/agent/linux/get_disks_info.h b/include/agent/linux/get_disks_info.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a74943badb3b553b23684eea70da4936908694d
--- /dev/null
+++ b/include/agent/linux/get_disks_info.h
@@ -0,0 +1,9 @@
+struct disk {
+    std::string model;
+    long long size;
+};
+
+typedef struct disk disk_t;
+
+void get_scsi_disks(std::list<disk_t>&);
+void get_disks_info(std::list<disk_t>&);
diff --git a/include/agent/linux/get_distro.h b/include/agent/linux/get_distro.h
index ae5556a308e2ecf37fe6e97dc026228da6bdf3a5..e9730beb1d5f67c40d2c26f7adb83dcbf6d2d19b 100644
--- a/include/agent/linux/get_distro.h
+++ b/include/agent/linux/get_distro.h
@@ -1,7 +1,5 @@
 #pragma once
 #include <sys/utsname.h>
-#include <fstream>
-#include <cstring>
+#include "agent/linux/open_file.h"
 
-int open_file(std::string name, std::ifstream& fstream);
 std::string get_distro();
diff --git a/include/agent/linux/get_memory_size.h b/include/agent/linux/get_memory_size.h
new file mode 100644
index 0000000000000000000000000000000000000000..1dc19d0110fd6ed7e6bfe541a1fc59ef5cc3c6a8
--- /dev/null
+++ b/include/agent/linux/get_memory_size.h
@@ -0,0 +1,7 @@
+#pragma once
+#include <fstream>
+#include <string>
+#include "agent/linux/open_file.h"
+#include <algorithm>
+
+int get_memory_size();
diff --git a/include/agent/linux/get_processor_model.h b/include/agent/linux/get_processor_model.h
new file mode 100644
index 0000000000000000000000000000000000000000..e3008313d95a938b53a86c0b37711efacd8a2adf
--- /dev/null
+++ b/include/agent/linux/get_processor_model.h
@@ -0,0 +1,6 @@
+#pragma once
+#include <fstream>
+#include <string>
+#include "agent/linux/open_file.h"
+
+std::string get_processor_model();
diff --git a/include/agent/linux/inventory.h b/include/agent/linux/inventory.h
index 3d96c0cfd1db85ccc955d72430d8fbba73648015..0f6bfa813eef82a276404c4e99fb4e60909e722e 100644
--- a/include/agent/linux/inventory.h
+++ b/include/agent/linux/inventory.h
@@ -3,15 +3,14 @@
 #include <time.h>
 #include <iostream>
 #include "agent/linux/get_date.h"
+#include "agent/linux/get_disks_info.h"
+#include "agent/linux/get_distro.h"
 #include "agent/linux/get_macaddr.h"
 #include "agent/linux/get_machine_type.h"
+#include "agent/linux/get_memory_size.h"
+#include "agent/linux/get_processor_model.h"
 #include "agent/linux/get_time.h"
 #include "agent/linux/get_user_count.h"
 #include "json/json.h"
 
-int open_file(std::string name, std::ifstream& fstream);
-
-std::string get_distro();
-std::string get_processor_model();
-
 Json::Value get_inventory();
diff --git a/include/agent/linux/open_file.h b/include/agent/linux/open_file.h
new file mode 100644
index 0000000000000000000000000000000000000000..486377505034a8b1fe6bfc0120007314fa7731f8
--- /dev/null
+++ b/include/agent/linux/open_file.h
@@ -0,0 +1,5 @@
+#pragma once
+#include <fstream>
+#include <string>
+
+int open_file(std::string name, std::ifstream& fstream);
diff --git a/src/linux/get_disks_info.cpp b/src/linux/get_disks_info.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dffb40f056c8d991af0c724707ac4fe1bddbefd4
--- /dev/null
+++ b/src/linux/get_disks_info.cpp
@@ -0,0 +1,117 @@
+/* Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of simmc-agent
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <libudev.h>
+#include <fstream>
+#include <string>
+#include <iostream>
+#include <list>
+#include "agent/linux/get_disks_info.h"
+
+
+void get_scsi_disks(std::list<disk_t>& disks) {  // NOLINT(runtime/references)
+
+    struct udev *udev;
+    struct udev_enumerate *enumerate;
+    struct udev_list_entry *devices, *dev_list_entry, *links_list_entry;
+    struct udev_device *dev;
+
+    udev = udev_new();
+    if (!udev) {
+        throw "Could not creat udev\n";
+    }
+
+    /* SCSI disk devices MAJOR = {8, 65-71, 128-135}
+    see https://www.kernel.org/doc/Documentation/devices.txt */
+    const char* scsi_majors[] = {"8", "65", "66", "67", "68", "69", "70", "71",
+                                 "128", "129", "130", "131", "132", "133",
+                                 "134", "135"};
+    int i;
+
+    for (i=0; i < 16; i++) {
+
+        /* create a list of the disk devices in the 'block' subsystem and with
+        MAJOR == one of the possible scsi major numbers. */
+        enumerate = udev_enumerate_new(udev);
+        udev_enumerate_add_match_property(enumerate, "MAJOR", scsi_majors[i]);
+        udev_enumerate_add_match_subsystem(enumerate, "block");
+        udev_enumerate_scan_devices(enumerate);
+        devices = udev_enumerate_get_list_entry(enumerate);
+
+        udev_list_entry_foreach(dev_list_entry, devices) {
+            /* potential new item */
+            disk_t curr = {.model = "", .size = -1};
+
+            /* get the filename of the /sys entry for the device
+            and create udev_device object representing it */
+            const char *path;
+            path = udev_list_entry_get_name(dev_list_entry);
+            dev = udev_device_new_from_syspath(udev, path);
+
+            /* MINOR = (16 * drive_number) + partition_number
+            partition_number is 0 for the whole drive, which is the one we want
+            therefore, if mod 16 != 0, skip device */
+            const char* minor = udev_device_get_property_value(dev, "MINOR");
+            if ((atoi(minor) % 16) != 0) {
+                udev_device_unref(dev);
+                continue;
+            }
+
+
+            const char* serial = udev_device_get_property_value(dev,
+                                                       "ID_SERIAL");
+            const char* size = udev_device_get_sysattr_value(dev, "size");
+
+            if (serial) {
+                curr.model.assign(std::string(serial));
+            }
+
+            /* size in Bytes = size * 512
+            size in GB = (size * 2^9)/2^30 = size/2^21 */
+            if (size) {
+                curr.size = atoll(size) >> 21;
+            }
+
+            /* do not push some anomalous device whose model and size we
+            couldn't obtain */
+            if (size && serial) {
+                disks.push_front(curr);
+            }
+
+            udev_device_unref(dev);
+        }
+
+        /* free the enumerator object */
+        udev_enumerate_unref(enumerate);
+
+    }
+
+    udev_unref(udev);
+}
+
+
+void get_disks_info(std::list<disk_t>& disks) {  // NOLINT(runtime/references)
+    get_scsi_disks(disks);
+
+    if (disks.empty()) {
+        throw std::string("No disk info found");
+    }
+}
diff --git a/src/linux/get_distro.cpp b/src/linux/get_distro.cpp
index 88a4fc8e4d519ec7df8887e2967ff4c087296c6b..a7c47703b567843b25d4fc332e667f5b3e2696cf 100644
--- a/src/linux/get_distro.cpp
+++ b/src/linux/get_distro.cpp
@@ -20,22 +20,9 @@
  */
 
 #include "agent/linux/get_distro.h"
-
-int open_file(std::string name, std::ifstream& fstream) {
-        fstream.open(name);
-        if (fstream.is_open())
-            return 1;
-        else
-            return 0;
-}
+#include "agent/linux/open_file.h"
 
 std::string get_distro() {
-    /* in Linux: distro name + version + release
-       the year is 2016 and we have 2 "unified" ways to identify distros
-       and a couple regex to find the distro name files
-       update: I used to complain about Linux, then I tried coding for
-       Windows... */
-
     /* currently recorded distros are
        * Ubuntu
        * Debian
@@ -147,5 +134,6 @@ std::string get_distro() {
 
         throw std::string("Release file empty.");
     }
+
     throw std::string("No release file found.");
 }
diff --git a/src/linux/get_memory_size.cpp b/src/linux/get_memory_size.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..df66e963cf8494f87d5c9259e7073c9e58f3d0a1
--- /dev/null
+++ b/src/linux/get_memory_size.cpp
@@ -0,0 +1,62 @@
+/* Copyright (C) 2004-2016 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of simmc-agent
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include "agent/linux/get_memory_size.h"
+
+int get_memory_size() {
+
+    std::ifstream meminfo_file;
+    std::string line;
+    std::string memsize;
+
+    if (open_file("/proc/meminfo", meminfo_file)) {
+
+        const std::string key = "MemTotal:";
+        std::size_t found;
+
+        while (getline(meminfo_file, line)) {
+
+            found = line.find(key);
+
+            if (found != std::string::npos) {
+                // remove key and 'kB' at the end
+                std::string value = line.substr(found + key.length(),
+                                                line.length() -
+                                                (found+key.length()+3));
+                // remove whitespaces
+                remove_copy(value.begin(), value.end(),
+                            std::back_inserter(memsize), ' ');
+                // convert to integer before returning
+                return std::stoi(memsize);
+            }
+        }
+        // If EOF and no info returned
+        std::string err = "MemTotal not found in /proc/meminfo.";
+        throw err;
+
+    } else {
+
+        std::string err = "Failed to open /proc/meminfo.";
+        throw err;
+
+    }
+
+}
diff --git a/src/linux/get_processor_model.cpp b/src/linux/get_processor_model.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..65a1ce8758d5b2a03735e013968c090fd3446ce3
--- /dev/null
+++ b/src/linux/get_processor_model.cpp
@@ -0,0 +1,44 @@
+/* Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of simmc-agent
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include "agent/linux/get_processor_model.h"
+
+std::string get_processor_model() {
+
+    std::ifstream cpuinfo_file;
+    std::string line;
+    if (open_file("/proc/cpuinfo", cpuinfo_file)) {
+        const std::string key = "model name";
+        std::size_t found;
+
+        while (getline(cpuinfo_file, line)) {
+            found = line.find(key);
+            if (found != std::string::npos) {
+                // remove ':' and space at the beginning
+                found = line.find(":");
+                return (line.substr(found+2));
+            }
+        }
+        throw std::string("Coudn't find model name in /proc/cpuinfo");
+    }
+
+    throw std::string("Coudn't open /proc/cpuinfo");
+}
diff --git a/src/linux/inventory.cpp b/src/linux/inventory.cpp
index ff41037b0034f5b82d2c1ab089d90d15548d8a7e..95162517dee5f5680a2a1a9d8b3f74c1416028b8 100644
--- a/src/linux/inventory.cpp
+++ b/src/linux/inventory.cpp
@@ -19,13 +19,11 @@
  * USA.
  */
 
+#include <list>
 #include "agent/linux/inventory.h"
 
-std::string get_processor_model() {
-    return "unknown";
-}
-
 Json::Value get_inventory() {
+
     Json::Value inv;
 
     // os info
@@ -46,17 +44,62 @@ Json::Value get_inventory() {
     inv["data"]["os_kernel"] = sysinfo.release;
     inv["data"]["mirror_timestamp"] = sysinfo.version;
 
+    try {
+        inv["data"]["processor"] = get_processor_model();
+    }
+    catch ( std::string err ) {
+        inv["data"]["processor"] = Json::nullValue;
+        inv["error"]["processor"] = err;
+    }
+
+    try {
+        inv["data"]["memory"] = get_memory_size();
+    }
+    catch ( std::string err ) {
+        inv["data"]["memory"] = Json::nullValue;
+        inv["error"]["memory"] = err;
+    }
+
+    try {
+        std::list<disk_t> disks;
+        get_disks_info(disks);
+        disk_t curr = disks.front();
+        inv["data"]["disk1_model"] = curr.model;
+        inv["data"]["disk1_size"] = curr.size;
+        disks.pop_front();
+
+        if (disks.empty()) {
+            inv["data"]["disk2_model"] = Json::nullValue;
+            inv["data"]["disk2_size"] = Json::nullValue;
+        } else {
+            curr = disks.front();
+            inv["data"]["disk2_model"] = curr.model;
+            inv["data"]["disk2_size"] = curr.size;
+            disks.pop_front();
+        }
+
+        Json::UInt64 disks_size = disks.size();
+        inv["data"]["extra_hds"] = disks_size;
+
+    }
+    catch ( std::string err ) {
+        inv["data"]["disk1_model"] = Json::nullValue;
+        inv["data"]["disk1_size"] = Json::nullValue;
+        inv["data"]["disk2_model"] = Json::nullValue;
+        inv["data"]["disk2_size"] = Json::nullValue;
+        inv["data"]["extra_hds"] = Json::nullValue;
+
+        inv["error"]["disk1_model"] = err;
+        inv["error"]["disk1_size"] = err;
+        inv["error"]["disk2_model"] = err;
+        inv["error"]["disk2_size"] = err;
+        inv["error"]["extra_hds"] = err;
+    }
+
     // hw info
     /*
-    inv["processor"] =
-    inv["memory"] =
-    inv["disk1_model"] =
-    inv["disk1_size"] =
     inv["disk1_used"] =
-    inv["disk2_model"] =
-    inv["disk2_size"] =
     inv["disk2_used"] =
-    inv["extra_hds"] =
     */
 
     // other
diff --git a/src/linux/open_file.cpp b/src/linux/open_file.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..10bcd1de77d261255c3edb0c7163943bb914dc13
--- /dev/null
+++ b/src/linux/open_file.cpp
@@ -0,0 +1,31 @@
+/* Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of simmc-agent
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include "agent/linux/open_file.h"
+
+int open_file(std::string name, std::ifstream& fstream) {
+        fstream.open(name);
+        if (fstream.is_open())
+            return 1;
+        else
+            return 0;
+}
+