Snap for 4824048 from 2b2979e93eb8b5a46e72142c2a90d9b302c27600 to pi-release

Change-Id: I4e0f32ceec3bcf60846413ab9ab3c336db6f4562
diff --git a/Android.bp b/Android.bp
index 7945e35..0dc83d0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -155,6 +155,7 @@
     ],
     static_libs: [
         "libcuttlefish_host_config",
+        "libjsoncpp",
         "libgflags",
     ],
     shared_libs: [
@@ -206,6 +207,7 @@
     ],
     static_libs: [
         "libcuttlefish_host_config",
+        "libjsoncpp",
         "libgtest_host",
         "libgflags",
     ],
diff --git a/common/commands/wifi_relay/Android.bp b/common/commands/wifi_relay/Android.bp
index c496ef0..5393d4a 100644
--- a/common/commands/wifi_relay/Android.bp
+++ b/common/commands/wifi_relay/Android.bp
@@ -39,6 +39,7 @@
         host: {
             static_libs: [
                 "libcuttlefish_host_config",
+                "libjsoncpp",
             ],
         },
     },
diff --git a/common/commands/wifi_relay/wifi_relay.cpp b/common/commands/wifi_relay/wifi_relay.cpp
index 2b21765..4d862b0 100644
--- a/common/commands/wifi_relay/wifi_relay.cpp
+++ b/common/commands/wifi_relay/wifi_relay.cpp
@@ -20,7 +20,7 @@
 #include "common/commands/wifi_relay/nl_client.h"
 
 #if defined(CUTTLEFISH_HOST)
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 #endif
 
 #include <linux/netdevice.h>
diff --git a/common/frontend/socket_forward_proxy/Android.bp b/common/frontend/socket_forward_proxy/Android.bp
index 4def7bf..3eba53f 100644
--- a/common/frontend/socket_forward_proxy/Android.bp
+++ b/common/frontend/socket_forward_proxy/Android.bp
@@ -36,6 +36,7 @@
         host: {
             static_libs: [
                 "libcuttlefish_host_config",
+                "libjsoncpp",
                 "libadb_connection_maintainer",
             ],
         },
diff --git a/common/frontend/socket_forward_proxy/main.cpp b/common/frontend/socket_forward_proxy/main.cpp
index a04c601..e361059 100644
--- a/common/frontend/socket_forward_proxy/main.cpp
+++ b/common/frontend/socket_forward_proxy/main.cpp
@@ -33,7 +33,7 @@
 #include "common/vsoc/lib/socket_forward_region_view.h"
 
 #ifdef CUTTLEFISH_HOST
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 #include "host/libs/adb_connection_maintainer/adb_connection_maintainer.h"
 #endif
 
diff --git a/common/vsoc/lib/screen_region_view_test.cpp b/common/vsoc/lib/screen_region_view_test.cpp
index b192c67..cc02baa 100644
--- a/common/vsoc/lib/screen_region_view_test.cpp
+++ b/common/vsoc/lib/screen_region_view_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 #include "screen_region_view.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 #include <stdio.h>
 
 using vsoc::screen::ScreenRegionView;
diff --git a/host/commands/launch/Android.bp b/host/commands/launch/Android.bp
index e9789b8..650ccb9 100644
--- a/host/commands/launch/Android.bp
+++ b/host/commands/launch/Android.bp
@@ -35,6 +35,7 @@
     ],
     static_libs: [
         "libcuttlefish_host_config",
+        "libcuttlefish_vm_manager",
         "libivserver",
         "libvadb",
         "libusbip",
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index c3b2151..9605049 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -38,14 +38,13 @@
 #include "common/vsoc/lib/vsoc_memory.h"
 #include "common/vsoc/shm/screen_layout.h"
 #include "host/commands/launch/pre_launch_initializers.h"
-#include "host/libs/config/file_partition.h"
-#include "host/libs/config/guest_config.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 #include "host/libs/ivserver/ivserver.h"
 #include "host/libs/ivserver/options.h"
 #include "host/libs/monitor/kernel_log_server.h"
 #include "host/libs/usbip/server.h"
 #include "host/libs/vadb/virtual_adb_server.h"
+#include "host/libs/vm_manager/libvirt_manager.h"
 
 namespace {
 std::string StringFromEnv(const char* varname, std::string defval) {
@@ -55,13 +54,20 @@
   }
   return valstr;
 }
+
+std::string DefaultHostArtifactsPath(const char* file_name) {
+  return (StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) + "/") +
+         file_name;
+}
+
 }  // namespace
 
-#define VIRSH_OPTIONS_PLACEHOLDER "<virsh_options>"
-
 using vsoc::GetPerInstanceDefault;
-using vsoc::GetDefaultPerInstancePath;
 
+DEFINE_string(
+    system_image, "",
+    "Path to the system image, if empty it is assumed to be a file named "
+    "system.img in the directory specified by -system_image_dir");
 DEFINE_string(cache_image, "", "Location of the cache partition image.");
 DEFINE_int32(cpus, 2, "Virtual CPU count.");
 DEFINE_string(data_image, "", "Location of the data partition image.");
@@ -72,10 +78,11 @@
 DEFINE_string(blank_data_image_fmt, "ext4",
               "The fs format for the blank data image. Used with mkfs.");
 
-DECLARE_int32(dpi);
-DECLARE_int32(x_res);
-DECLARE_int32(y_res);
-DECLARE_int32(num_screen_buffers);
+DEFINE_int32(x_res, 720, "Width of the screen in pixels");
+DEFINE_int32(y_res, 1280, "Height of the screen in pixels");
+DEFINE_int32(dpi, 160, "Pixels per inch for the screen");
+DEFINE_int32(refresh_rate_hz, 60, "Screen refresh rate in Hertz");
+DEFINE_int32(num_screen_buffers, 3, "The number of screen buffers");
 
 DEFINE_bool(disable_app_armor_security, false,
             "Disable AppArmor security in libvirt. For debug only.");
@@ -83,17 +90,10 @@
             "Disable DAC security in libvirt. For debug only.");
 DEFINE_string(extra_kernel_command_line, "",
               "Additional flags to put on the kernel command line");
-DECLARE_int32(instance);
 DEFINE_string(initrd, "", "Location of cuttlefish initrd file.");
 DEFINE_string(kernel, "", "Location of cuttlefish kernel file.");
 DEFINE_string(kernel_command_line, "",
               "Location of a text file with the kernel command line.");
-DEFINE_string(hypervisor_uri, "qemu:///system", "Hypervisor cannonical uri.");
-DEFINE_string(launch_command,
-              "virsh " VIRSH_OPTIONS_PLACEHOLDER " create /dev/fd/0",
-              "Command to start an instance. If <virsh_options> is present it "
-              "will be replaced by options to the virsh command");
-DEFINE_bool(log_xml, false, "Log the XML machine configuration");
 DEFINE_int32(memory_mb, 2048,
              "Total amount of memory available for guest, MB.");
 std::string g_default_mempath{GetPerInstanceDefault("/var/run/shm/cvd-")};
@@ -102,11 +102,13 @@
 std::string g_default_mobile_interface{GetPerInstanceDefault("cvd-mobile-")};
 DEFINE_string(mobile_interface, g_default_mobile_interface.c_str(),
               "Network interface to use for mobile networking");
-std::string g_default_qemusocket = GetDefaultPerInstancePath("ivshmem_socket_qemu");
-DEFINE_string(qemusocket, g_default_qemusocket.c_str(), "QEmu socket path");
+DEFINE_string(mobile_tap_name, GetPerInstanceDefault("amobile"),
+              "The name of the tap interface to use for mobile");
 std::string g_default_serial_number{GetPerInstanceDefault("CUTTLEFISHCVD")};
 DEFINE_string(serial_number, g_default_serial_number.c_str(),
               "Serial number to use for the device");
+DEFINE_string(instance_dir, vsoc::GetDefaultPerInstanceDir(),
+              "A directory to put all instance specific files");
 DEFINE_string(system_image_dir,
               StringFromEnv("ANDROID_PRODUCT_OUT", StringFromEnv("HOME", ".")),
               "Location of the system partition images.");
@@ -117,27 +119,40 @@
             " Will be deprecated soon.");
 DEFINE_bool(start_vnc_server, true, "Whether to start the vnc server process.");
 DEFINE_string(vnc_server_binary,
-              StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
-                  "/bin/vnc_server",
+              DefaultHostArtifactsPath("/bin/vnc_server"),
               "Location of the vnc server binary.");
 DEFINE_int32(vnc_server_port, GetPerInstanceDefault(6444),
              "The port on which the vnc server should listen");
 DEFINE_string(socket_forward_proxy_binary,
-              StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
-                  "/bin/socket_forward_proxy",
+              DefaultHostArtifactsPath("/bin/socket_forward_proxy"),
               "Location of the socket_forward_proxy binary.");
 DEFINE_string(adb_mode, "tunnel",
               "Mode for adb connection. Can be usb for usb forwarding, or "
               "tunnel for tcp connection. If using tunnel, you may have to "
               "run 'adb kill-server' to get the device to show up.");
 DEFINE_int32(vhci_port, GetPerInstanceDefault(0), "VHCI port to use for usb");
+DEFINE_string(guest_mac_address,
+              GetPerInstanceDefault("00:43:56:44:80:"), // 00:43:56:44:80:0x
+              "MAC address of the wifi interface to be created on the guest.");
+DEFINE_string(host_mac_address,
+              "42:00:00:00:00:00",
+              "MAC address of the wifi interface running on the host.");
 DEFINE_bool(start_wifi_relay, true, "Whether to start the wifi_relay process.");
 DEFINE_string(wifi_relay_binary,
-              StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
-                  "/bin/wifi_relay",
+              DefaultHostArtifactsPath("/bin/wifi_relay"),
               "Location of the wifi_relay binary.");
+std::string g_default_wifi_interface{GetPerInstanceDefault("cvd-wifi-")};
+DEFINE_string(wifi_interface, g_default_wifi_interface.c_str(),
+              "Network interface to use for wifi");
+// TODO(b/72969289) This should be generated
+DEFINE_string(dtb, DefaultHostArtifactsPath("config/cuttlefish.dtb"),
+              "Path to the cuttlefish.dtb file");
 
-DECLARE_string(uuid);
+constexpr char kDefaultUuidPrefix[] = "699acfc4-c8c4-11e7-882b-5065f31dc1";
+DEFINE_string(uuid, vsoc::GetPerInstanceDefault(kDefaultUuidPrefix).c_str(),
+              "UUID to use for the device. Random if not specified");
+
+DECLARE_string(config_file);
 
 namespace {
 const std::string kDataPolicyUseExisting = "use_existing";
@@ -147,10 +162,6 @@
 constexpr char kAdbModeTunnel[] = "tunnel";
 constexpr char kAdbModeUsb[] = "usb";
 
-std::string GetVirshOptions() {
-  return std::string("-c ").append(FLAGS_hypervisor_uri);
-}
-
 // VirtualUSBManager manages virtual USB device presence for Cuttlefish.
 class VirtualUSBManager {
  public:
@@ -196,9 +207,8 @@
 // Cuttlefish and host-side daemons.
 class IVServerManager {
  public:
-  IVServerManager()
-      : server_(ivserver::IVServerOptions(FLAGS_mempath,
-                                          FLAGS_qemusocket,
+  IVServerManager(const std::string& mempath, const std::string& qemu_socket)
+      : server_(ivserver::IVServerOptions(mempath, qemu_socket,
                                           vsoc::GetDomain())) {}
 
   ~IVServerManager() = default;
@@ -256,8 +266,16 @@
                 bool wait_for_child = true) {
   pid_t pid = fork();
   if (!pid) {
-    int rval = execve(command[0], const_cast<char* const*>(command),
-                      const_cast<char* const*>(envp));
+    int rval;
+    // If envp is NULL, the current process's environment is used as the
+    // environment of the child process. To force an empty emvironment for the
+    // child process pass the address of a pointer to NULL
+    if (envp == NULL) {
+      rval = execv(command[0], const_cast<char* const*>(command));
+    } else {
+      rval = execve(command[0], const_cast<char* const*>(command),
+                    const_cast<char* const*>(envp));
+    }
     // No need for an if: if exec worked it wouldn't have returned
     LOG(ERROR) << "exec of " << command[0] << " failed (" << strerror(errno)
                << ")";
@@ -276,6 +294,11 @@
   }
 }
 
+bool FileExists(const char* path) {
+  struct stat unused;
+  return stat(path, &unused) != -1 || errno != ENOENT;
+}
+
 void CreateBlankImage(
     const std::string& image, int image_mb, const std::string& image_fmt) {
   LOG(INFO) << "Creating " << image;
@@ -299,6 +322,84 @@
   subprocess(rm_command, NULL);
 }
 
+bool ApplyDataImagePolicy(const char* data_image) {
+  bool data_exists = FileExists(data_image);
+  bool remove{};
+  bool create{};
+
+  if (FLAGS_data_policy == kDataPolicyUseExisting) {
+    if (!data_exists) {
+      LOG(FATAL) << "Specified data image file does not exists: " << data_image;
+      return false;
+    }
+    if (FLAGS_blank_data_image_mb > 0) {
+      LOG(FATAL) << "You should NOT use -blank_data_image_mb with -data_policy="
+                 << kDataPolicyUseExisting;
+      return false;
+    }
+    create = false;
+    remove = false;
+  } else if (FLAGS_data_policy == kDataPolicyAlwaysCreate) {
+    remove = data_exists;
+    create = true;
+  } else if (FLAGS_data_policy == kDataPolicyCreateIfMissing) {
+    create = !data_exists;
+    remove = false;
+  } else {
+    LOG(FATAL) << "Invalid data_policy: " << FLAGS_data_policy;
+  }
+
+  if (remove) {
+    RemoveFile(data_image);
+  }
+
+  if (create) {
+    if (FLAGS_blank_data_image_mb <= 0) {
+      LOG(FATAL) << "-blank_data_image_mb is required to create data image";
+    }
+    CreateBlankImage(
+        data_image, FLAGS_blank_data_image_mb, FLAGS_blank_data_image_fmt);
+  } else {
+    LOG(INFO) << data_image << " exists. Not creating it.";
+  }
+
+  return true;
+}
+
+bool EnsureDirExists(const char* dir) {
+  if (!FileExists(dir)) {
+    LOG(INFO) << "Setting up " << dir;
+    if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
+      if (errno == EACCES) {
+        // TODO(79170615) Don't use sudo once libvirt is replaced
+        LOG(WARNING) << "Not enough permission to create " << dir
+                     << " retrying with sudo";
+        const char* mkdir_command[]{"/usr/bin/sudo", "/bin/mkdir", "-m",
+                                    "0775",          dir,          NULL};
+        subprocess(mkdir_command, NULL);
+
+        // When created with sudo the owner and group is root.
+        std::string user_group = getenv("USER");
+        user_group += ":libvirt-qemu";
+        const char* chown_cmd[] = {"/usr/bin/sudo", "/bin/chown",
+                                   user_group.c_str(), dir, NULL};
+        subprocess(chown_cmd, NULL);
+      } else {
+        LOG(FATAL) << "Unable to create " << dir << ". Error: " << errno;
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+std::string GetConfigFile() {
+  return vsoc::CuttlefishConfig::Get()->PerInstancePath(
+      "cuttlefish_config.json");
+}
+
+std::string GetConfigFileArg() { return "-config_file=" + GetConfigFile(); }
+
 std::string GetGuestPortArg() {
   constexpr int kEmulatorPort = 5555;
   return std::string{"--guest_ports="} + std::to_string(kEmulatorPort);
@@ -310,14 +411,6 @@
       std::to_string(vsoc::GetPerInstanceDefault(kFirstHostPort));
 }
 
-std::string GetDomainArg() {
-  return std::string{"--domain="} + vsoc::GetDomain();
-}
-
-std::string GetInstanceArg() {
-  return std::string{"--instance="} + std::to_string(FLAGS_instance);
-}
-
 void ValidateAdbModeFlag() {
   CHECK(FLAGS_adb_mode == kAdbModeUsb ||
         FLAGS_adb_mode == kAdbModeTunnel) << "invalid --adb_mode";
@@ -335,15 +428,13 @@
   if (AdbTunnelEnabled()) {
     auto guest_port_arg = GetGuestPortArg();
     auto host_port_arg = GetHostPortArg();
-    auto domain_arg = GetDomainArg();
-    auto instance_arg = GetInstanceArg();
+    auto config_arg = GetConfigFileArg();
 
     const char* const socket_proxy[] = {
       FLAGS_socket_forward_proxy_binary.c_str(),
       guest_port_arg.c_str(),
       host_port_arg.c_str(),
-      domain_arg.c_str(),
-      instance_arg.c_str(),
+      config_arg.c_str(),
       NULL
     };
     subprocess(socket_proxy, nullptr, false);
@@ -354,13 +445,11 @@
   if (FLAGS_start_vnc_server) {
     // Launch the vnc server, don't wait for it to complete
     auto port_options = "-port=" + std::to_string(FLAGS_vnc_server_port);
-    auto domain_arg = GetDomainArg();
-    auto instance_arg = GetInstanceArg();
+    auto config_arg = GetConfigFileArg();
     const char* vnc_command[] = {
       FLAGS_vnc_server_binary.c_str(),
       port_options.c_str(),
-      domain_arg.c_str(),
-      instance_arg.c_str(),
+      config_arg.c_str(),
       NULL
     };
     subprocess(vnc_command, NULL, false);
@@ -370,45 +459,22 @@
 void LaunchWifiRelayIfEnabled() {
   if (FLAGS_start_wifi_relay) {
     // Launch the wifi relay, don't wait for it to complete
-    auto domain_arg = GetDomainArg();
-    auto instance_arg = GetInstanceArg();
-
+    auto config_arg = GetConfigFileArg();
     const char* relay_command[] = {
         "/usr/bin/sudo",
+        "-E",
         FLAGS_wifi_relay_binary.c_str(),
-        domain_arg.c_str(),
-        instance_arg.c_str(),
+        config_arg.c_str(),
         NULL
     };
 
     subprocess(relay_command, NULL /* envp */, false /* wait_for_child */);
   }
 }
-
-}  // anonymous namespace
-
-int main(int argc, char** argv) {
-  ::android::base::InitLogging(argv, android::base::StderrLogger);
-  google::ParseCommandLineFlags(&argc, &argv, true);
-  ValidateAdbModeFlag();
-
-  LOG_IF(FATAL, FLAGS_system_image_dir.empty())
-      << "--system_image_dir must be specified.";
-
-  std::string per_instance_dir = vsoc::GetDefaultPerInstanceDir();
-  struct stat unused;
-  if ((stat(per_instance_dir.c_str(), &unused) == -1) && (errno == ENOENT)) {
-    LOG(INFO) << "Setting up " << per_instance_dir;
-    const char* mkdir_command[]{
-        "/usr/bin/sudo",          "/bin/mkdir", "-m", "0775",
-        per_instance_dir.c_str(), NULL};
-    subprocess(mkdir_command, NULL);
-    std::string owner_group{getenv("USER")};
-    owner_group += ":libvirt-qemu";
-    const char* chown_command[]{"/usr/bin/sudo", "/bin/chown",
-                                owner_group.c_str(), per_instance_dir.c_str(),
-                                NULL};
-    subprocess(chown_command, NULL);
+bool ResolveInstanceFiles() {
+  if (FLAGS_system_image_dir.empty()) {
+    LOG(FATAL) << "--system_image_dir must be specified.";
+    return false;
   }
 
   // If user did not specify location of either of these files, expect them to
@@ -416,165 +482,186 @@
   if (FLAGS_kernel.empty()) {
     FLAGS_kernel = FLAGS_system_image_dir + "/kernel";
   }
-
   if (FLAGS_kernel_command_line.empty()) {
     FLAGS_kernel_command_line = FLAGS_system_image_dir + "/cmdline";
   }
-
+  if (FLAGS_system_image.empty()) {
+    FLAGS_system_image = FLAGS_system_image_dir + "/system.img";
+  }
   if (FLAGS_initrd.empty()) {
     FLAGS_initrd = FLAGS_system_image_dir + "/ramdisk.img";
   }
-
   if (FLAGS_cache_image.empty()) {
     FLAGS_cache_image = FLAGS_system_image_dir + "/cache.img";
   }
-
-  if (FLAGS_data_policy == kDataPolicyCreateIfMissing) {
-    FLAGS_data_image = FLAGS_system_image_dir + "/userdata_blank.img";
-    if (FLAGS_blank_data_image_mb <= 0) {
-      LOG(FATAL) << "You should use -blank_data_image_mb with -data_policy="
-                 << kDataPolicyCreateIfMissing;
-    }
-    // Create a blank data image if the image doesn't exist yet
-    if ((stat(FLAGS_data_image.c_str(), &unused) == -1) && (errno == ENOENT)) {
-      CreateBlankImage(
-          FLAGS_data_image, FLAGS_blank_data_image_mb, FLAGS_blank_data_image_fmt);
-    } else {
-      LOG(INFO) << FLAGS_data_image << " exists. Not creating it.";
-    }
-  } else if (FLAGS_data_policy == kDataPolicyAlwaysCreate) {
-    FLAGS_data_image = FLAGS_system_image_dir + "/userdata_blank.img";
-    if (FLAGS_blank_data_image_mb <= 0) {
-      LOG(FATAL) << "You should use -blank_data_image_mb with -data_policy="
-                 << kDataPolicyAlwaysCreate;
-    }
-    RemoveFile(FLAGS_data_image);
-    CreateBlankImage(
-        FLAGS_data_image, FLAGS_blank_data_image_mb, FLAGS_blank_data_image_fmt);
-  } else if (FLAGS_data_policy == kDataPolicyUseExisting) {
-    // Do nothing. Use FLAGS_data_image.
-    if (FLAGS_blank_data_image_mb > 0) {
-      LOG(FATAL) << "You should NOT use -blank_data_image_mb with -data_policy="
-                 << kDataPolicyUseExisting;
-    }
-  } else {
-    LOG(FATAL) << "Invalid data_policy: " << FLAGS_data_policy;
-  }
-
   if (FLAGS_data_image.empty()) {
     FLAGS_data_image = FLAGS_system_image_dir + "/userdata.img";
   }
-
   if (FLAGS_vendor_image.empty()) {
     FLAGS_vendor_image = FLAGS_system_image_dir + "/vendor.img";
   }
 
-  // Each of these calls is free to fail and terminate launch if file does not
-  // exist or could not be created.
-  auto system_partition = config::FilePartition::ReuseExistingFile(
-      FLAGS_system_image_dir + "/system.img");
-  auto data_partition =
-      config::FilePartition::ReuseExistingFile(FLAGS_data_image);
-  auto cache_partition =
-      config::FilePartition::ReuseExistingFile(FLAGS_cache_image);
-  auto vendor_partition =
-      config::FilePartition::ReuseExistingFile(FLAGS_vendor_image);
-
-  std::ostringstream cmdline;
-  std::ifstream t(FLAGS_kernel_command_line);
-  if (!t) {
-    LOG(FATAL) << "Unable to open " << FLAGS_kernel_command_line;
-  }
-  cmdline << t.rdbuf();
-  t.close();
-  cmdline << " androidboot.serialno=" << FLAGS_serial_number;
-  cmdline << " androidboot.lcd_density=" << FLAGS_dpi;
-  if (FLAGS_extra_kernel_command_line.size()) {
-    cmdline << " " << FLAGS_extra_kernel_command_line;
+  // Create data if necessary
+  if (!ApplyDataImagePolicy(FLAGS_data_image.c_str())) {
+    return false;
   }
 
-  std::string entropy_source = "/dev/urandom";
+  // Check that the files exist
+  for (const auto& file :
+       {FLAGS_system_image, FLAGS_vendor_image, FLAGS_cache_image, FLAGS_kernel,
+        FLAGS_initrd, FLAGS_data_image, FLAGS_kernel_command_line}) {
+    if (!FileExists(file.c_str())) {
+      LOG(FATAL) << "File not found: " << file;
+      return false;
+    }
+  }
+  return true;
+}
+
+bool SetUpGlobalConfiguration() {
+  if (!ResolveInstanceFiles()) {
+    return false;
+  }
   auto& memory_layout = *vsoc::VSoCMemoryLayout::Get();
-
-  config::GuestConfig cfg;
-  cfg.SetID(FLAGS_instance)
-      .SetVCPUs(FLAGS_cpus)
-      .SetMemoryMB(FLAGS_memory_mb)
-      .SetKernelName(FLAGS_kernel)
-      .SetInitRDName(FLAGS_initrd)
-      .SetKernelArgs(cmdline.str())
-      .SetIVShMemSocketPath(FLAGS_qemusocket)
-      .SetIVShMemVectorCount(memory_layout.GetRegions().size())
-      .SetSystemPartitionPath(system_partition->GetName())
-      .SetCachePartitionPath(cache_partition->GetName())
-      .SetDataPartitionPath(data_partition->GetName())
-      .SetVendorPartitionPath(vendor_partition->GetName())
-      .SetMobileBridgeName(FLAGS_mobile_interface)
-      .SetEntropySource(entropy_source)
-      .SetDisableDACSecurity(FLAGS_disable_dac_security)
-      .SetDisableAppArmorSecurity(FLAGS_disable_app_armor_security)
-      .SetUUID(FLAGS_uuid);
-  if(AdbUsbEnabled()) {
-    cfg.SetUSBV1SocketName(
-        GetDefaultPerInstancePath(cfg.GetInstanceName() + "-usb"));
-  }
-  cfg.SetKernelLogSocketName(
-      GetDefaultPerInstancePath(cfg.GetInstanceName() + "-kernel-log"));
-
-  std::string xml = cfg.Build();
-  if (FLAGS_log_xml) {
-    LOG(INFO) << "Using XML:\n" << xml;
+  auto config = vsoc::CuttlefishConfig::Get();
+  // Set this first so that calls to PerInstancePath below are correct
+  config->set_instance_dir(FLAGS_instance_dir);
+  if (!EnsureDirExists(FLAGS_instance_dir.c_str())) {
+    return false;
   }
 
-  VirtualUSBManager vadb(cfg.GetUSBV1SocketName(), FLAGS_vhci_port,
-                         GetPerInstanceDefault("android_usbip"));
-  vadb.Start();
+  config->set_serial_number(FLAGS_serial_number);
 
+  config->set_cpus(FLAGS_cpus);
+  config->set_memory_mb(FLAGS_memory_mb);
+
+  config->set_dpi(FLAGS_dpi);
+  config->set_x_res(FLAGS_x_res);
+  config->set_y_res(FLAGS_y_res);
+  config->set_refresh_rate_hz(FLAGS_refresh_rate_hz);
+
+  config->set_kernel_image_path(FLAGS_kernel);
+  std::ostringstream extra_cmdline;
+  extra_cmdline << " androidboot.serialno=" << FLAGS_serial_number;
+  extra_cmdline << " androidboot.lcd_density=" << FLAGS_dpi;
+  if (FLAGS_extra_kernel_command_line.size()) {
+    extra_cmdline << " " << FLAGS_extra_kernel_command_line;
+  }
+  config->ReadKernelArgs(FLAGS_kernel_command_line.c_str(),
+                         extra_cmdline.str());
+
+  config->set_ramdisk_image_path(FLAGS_initrd);
+  config->set_system_image_path(FLAGS_system_image);
+  config->set_cache_image_path(FLAGS_cache_image);
+  config->set_data_image_path(FLAGS_data_image);
+  config->set_vendor_image_path(FLAGS_vendor_image);
+  config->set_dtb_path(FLAGS_dtb);
+
+  config->set_mempath(FLAGS_mempath);
+  config->set_ivshmem_qemu_socket_path(
+      config->PerInstancePath("ivshmem_socket_qemu"));
+  config->set_ivshmem_client_socket_path(
+      config->PerInstancePath("ivshmem_socket_client"));
+  config->set_ivshmem_vector_count(memory_layout.GetRegions().size());
+
+  config->set_usb_v1_socket_name(config->PerInstancePath("usb-v1"));
+  config->set_vhci_port(FLAGS_vhci_port);
+  config->set_usb_ip_socket_name(config->PerInstancePath("usb-ip"));
+
+  config->set_kernel_log_socket_name(config->PerInstancePath("kernel-log"));
+  config->set_console_path(config->PerInstancePath("console"));
+  config->set_logcat_path(config->PerInstancePath("logcat"));
+
+  config->set_mobile_bridge_name(FLAGS_mobile_interface);
+  config->set_mobile_tap_name(FLAGS_mobile_tap_name);
+
+  config->set_wifi_guest_mac_addr(FLAGS_guest_mac_address);
+  config->set_wifi_host_mac_addr(FLAGS_host_mac_address);
+
+  config->set_entropy_source("/dev/urandom");
+  config->set_uuid(FLAGS_uuid);
+
+  config->set_disable_dac_security(FLAGS_disable_dac_security);
+  config->set_disable_app_armor_security(FLAGS_disable_app_armor_security);
+
+  if(!AdbUsbEnabled()) {
+    config->disable_usb_adb();
+  }
+
+  return true;
+}
+
+}  // anonymous namespace
+
+namespace launch_cvd {
+void ParseCommandLineFlags(int argc, char** argv) {
+  // The config_file is created by the launcher, so the launcher is the only
+  // host process that doesn't use the flag.
+  // Set the default to empty.
+  google::SetCommandLineOptionWithMode("config_file", "",
+                                       gflags::SET_FLAGS_DEFAULT);
+  google::ParseCommandLineFlags(&argc, &argv, true);
+  // Set the flag value to empty (in case the caller passed a value for it).
+  FLAGS_config_file = "";
+
+  ValidateAdbModeFlag();
+}
+}  // namespace launch_cvd
+
+int main(int argc, char** argv) {
+  ::android::base::InitLogging(argv, android::base::StderrLogger);
+  launch_cvd::ParseCommandLineFlags(argc, argv);
+
+  // Do this early so that the config object is ready for anything that needs it
+  if (!SetUpGlobalConfiguration()) {
+    return -1;
+  }
+
+  auto& memory_layout = *vsoc::VSoCMemoryLayout::Get();
   // TODO(b/79170615) These values need to go to the config object/file and the
   // region resizing be done by the ivserver process (or maybe the config
   // library to ensure all processes have the correct value?)
-  size_t screen_size =
+  size_t screen_region_size =
       memory_layout
           .GetRegionByName(vsoc::layout::screen::ScreenLayout::region_name)
           ->region_size();
   auto actual_width = ((FLAGS_x_res * 4) + 15) & ~15;  // aligned to 16
-  screen_size += FLAGS_num_screen_buffers *
+  screen_region_size += FLAGS_num_screen_buffers *
                  (actual_width * FLAGS_y_res + 16 /* padding */);
-  screen_size += (FLAGS_num_screen_buffers - 1) * 4096; /* Guard pages */
+  screen_region_size += (FLAGS_num_screen_buffers - 1) * 4096; /* Guard pages */
   memory_layout.ResizeRegion(vsoc::layout::screen::ScreenLayout::region_name,
-                             screen_size);
+                             screen_region_size);
   // TODO(b/79170615) Resize gralloc region too.
 
-  IVServerManager ivshmem;
+
+  auto config = vsoc::CuttlefishConfig::Get();
+  // Save the config object before starting any host process
+  if (!config->SaveToFile(GetConfigFile())) {
+    return -1;
+  }
+
+  // Start the usb manager
+  VirtualUSBManager vadb(config->usb_v1_socket_name(), config->vhci_port(),
+                         config->usb_ip_socket_name());
+  vadb.Start();
+
+  // Start IVServer
+  IVServerManager ivshmem(config->mempath(), config->ivshmem_qemu_socket_path());
   ivshmem.Start();
-  KernelLogMonitor kmon(cfg.GetKernelLogSocketName(),
-                        GetDefaultPerInstancePath("kernel.log"),
+
+  KernelLogMonitor kmon(config->kernel_log_socket_name(),
+                        config->PerInstancePath("kernel.log"),
                         FLAGS_deprecated_boot_completed);
   kmon.Start();
 
-  sleep(1);
-
-  // Initialize the regions that require it before the VM starts.
+  // Initialize the regions that require so before the VM starts.
   PreLaunchInitializers::Initialize();
 
-  std::string launch_command = FLAGS_launch_command;
-  auto pos = launch_command.find(VIRSH_OPTIONS_PLACEHOLDER);
-  if (pos != std::string::npos) {
-    launch_command.replace(
-        pos, sizeof(VIRSH_OPTIONS_PLACEHOLDER) - 1, GetVirshOptions());
-  }
-
-  FILE* launch = popen(launch_command.c_str(), "w");
-  if (!launch) {
-    LOG(FATAL) << "Unable to execute " << launch_command;
-  }
-  int rval = fputs(xml.c_str(), launch);
-  if (rval == EOF) {
-    LOG(FATAL) << "Launch command exited while accepting XML";
-  }
-  int exit_code = pclose(launch);
-  if (exit_code) {
-    LOG(FATAL) << "Launch command exited with status " << exit_code;
+  // Start the guest VM
+  vm_manager::LibvirtManager libvirt;
+  if (!libvirt.Start()) {
+    LOG(FATAL) << "Unable to start libvirt";
+    return -1;
   }
 
   LaunchSocketForwardProxyIfEnabled();
diff --git a/host/commands/launch/ril_region_handler.cc b/host/commands/launch/ril_region_handler.cc
index e122e29..31f5107 100644
--- a/host/commands/launch/ril_region_handler.cc
+++ b/host/commands/launch/ril_region_handler.cc
@@ -22,21 +22,13 @@
 #include <memory>
 #include <string>
 
-#include <gflags/gflags.h>
-#include <glog/logging.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
 #include "common/vsoc/lib/ril_region_view.h"
 #include "host/commands/launch/pre_launch_initializers.h"
-#include "host/libs/config/host_config.h"
-
-DECLARE_string(hypervisor_uri);
-DECLARE_string(mobile_interface);
+#include "host/libs/config/cuttlefish_config.h"
 
 namespace {
 
-int number_of_ones(int val) {
+int number_of_ones(unsigned long val) {
   int ret = 0;
   while (val) {
     ret += val % 2;
@@ -54,7 +46,7 @@
   std::string ril_broadcast;
 
   bool ObtainConfig(const std::string& interface) {
-    bool ret = ParseLibvirtXml(interface) && GetBroadcastAddr(interface);
+    bool ret = ParseIntefaceAttributes(interface);
     LOG(INFO) << "Network config:";
     LOG(INFO) << "ipaddr = " << ril_ipaddr;
     LOG(INFO) << "gateway = " << ril_gateway;
@@ -65,102 +57,74 @@
   }
 
  private:
-  bool GetBroadcastAddr(const std::string& interface) {
-    struct ifaddrs *ifap{}, *ifa{};
-    struct sockaddr_in *sa{};
-    char *addr{};
-    getifaddrs (&ifap);
-    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
-      if (ifa->ifa_addr && ifa->ifa_addr->sa_family==AF_INET) {
-        if (strcmp(ifa->ifa_name, interface.c_str())) continue;
-        sa = reinterpret_cast<sockaddr_in*>(ifa->ifa_ifu.ifu_broadaddr);
-        addr = inet_ntoa(sa->sin_addr);
-        this->ril_broadcast = strtok(addr, "\n");
+  bool ParseIntefaceAttributes(struct ifaddrs* ifa) {
+    // if (ifa->ifa_addr->sa_family != AF_INET) {
+    //   LOG(ERROR) << "The " << ifa->ifa_name << " interface is not IPv4";
+    //   return false;
+    // }
+    struct sockaddr_in* sa;
+    char* addr_str;
+
+    // Gateway
+    sa = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
+    addr_str = inet_ntoa(sa->sin_addr);
+    this->ril_gateway = strtok(addr_str, "\n");
+    auto gateway_s_addr = ntohl(sa->sin_addr.s_addr);
+
+    // Broadcast
+    sa = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
+    addr_str = inet_ntoa(sa->sin_addr);
+    this->ril_broadcast = strtok(addr_str, "\n");
+    auto broadcast_s_addr = ntohl(sa->sin_addr.s_addr);
+
+    // Netmask
+    sa = reinterpret_cast<sockaddr_in*>(ifa->ifa_netmask);
+    this->ril_prefixlen = number_of_ones(sa->sin_addr.s_addr);
+    auto netmask_s_addr = ntohl(sa->sin_addr.s_addr);
+
+    // Address (Find an address in the network different than the network, the
+    // gateway and the broadcast)
+    auto network = gateway_s_addr & netmask_s_addr;
+    auto s_addr = network + 1;
+    // s_addr & ~netmask_s_addr is zero when s_addr wraps around the network
+    while (s_addr & ~netmask_s_addr) {
+      if (s_addr != gateway_s_addr && s_addr != broadcast_s_addr) {
+        break;
       }
+      ++s_addr;
     }
-
-    freeifaddrs(ifap);
-    return (this->ril_broadcast.size() > 0);
-  }
-
-  bool ParseLibvirtXml(const std::string& interface) {
-    std::string net_dump_command =
-        "virsh -c " + FLAGS_hypervisor_uri + " net-dumpxml " + interface;
-    std::shared_ptr<FILE> net_xml_file(popen(net_dump_command.c_str(), "r"),
-                                       pclose);
-    if (!net_xml_file) {
-      LOG(ERROR) << "Unable to popen virsh...";
+    if (s_addr == network) {
+      LOG(ERROR) << "No available address found in interface " << ifa->ifa_name;
       return false;
     }
-    std::shared_ptr<xmlDoc> doc(
-        xmlReadFd(fileno(net_xml_file.get()), NULL, NULL, 0), xmlFreeDoc);
-    if (!doc) {
-      LOG(ERROR) << "Unable to parse network xml";
-      return false;
-    }
-
-    xmlNode* element = xmlDocGetRootElement(doc.get());
-    element = element->xmlChildrenNode;
-    while (element) {
-      if (strcmp(reinterpret_cast<const char*>(element->name), "ip") == 0) {
-        return ProcessIpNode(element);
-      }
-      element = element->next;
-    }
-    LOG(ERROR) << "ip node not found in network xml spec";
-    return false;
-  }
-
-  bool ParseIpAttributes(xmlNode* ip_node) {
-    // The gateway is the host ip address
-    this->ril_gateway = reinterpret_cast<const char*>(
-        xmlGetProp(ip_node, reinterpret_cast<const xmlChar*>("address")));
-
-    // The prefix length need to be obtained from the network mask
-    auto* netmask = reinterpret_cast<const char*>(
-        xmlGetProp(ip_node, reinterpret_cast<const xmlChar*>("netmask")));
-    int byte1, byte2, byte3, byte4;
-    sscanf(netmask, "%d.%d.%d.%d", &byte1, &byte2, &byte3, &byte4);
-    this->ril_prefixlen = 0;
-    this->ril_prefixlen += number_of_ones(byte1);
-    this->ril_prefixlen += number_of_ones(byte2);
-    this->ril_prefixlen += number_of_ones(byte3);
-    this->ril_prefixlen += number_of_ones(byte4);
+    struct in_addr addr;
+    addr.s_addr = htonl(s_addr);
+    addr_str = inet_ntoa(addr);
+    this->ril_ipaddr = strtok(addr_str, "\n");
     return true;
   }
 
-  bool ProcessDhcpNode(xmlNode* dhcp_node) {
-    xmlNode* child = dhcp_node->xmlChildrenNode;
-    while (child) {
-      if (strcmp(reinterpret_cast<const char*>(child->name), "range") == 0) {
-        this->ril_ipaddr = reinterpret_cast<const char*>(
-            xmlGetProp(child, reinterpret_cast<const xmlChar*>("start")));
-        return true;
+  bool ParseIntefaceAttributes(const std::string& interface) {
+    struct ifaddrs *ifa_list{}, *ifa{};
+    bool ret = false;
+    getifaddrs(&ifa_list);
+    for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
+      if (strcmp(ifa->ifa_name, interface.c_str()) == 0 &&
+          ifa->ifa_addr->sa_family == AF_INET) {
+        ret = ParseIntefaceAttributes(ifa);
+        break;
       }
-      child = child->next;
     }
-    LOG(ERROR) << "range node not found in network xml spec";
-    return false;
-  }
-
-  bool ProcessIpNode(xmlNode* ip_node) {
-    ParseIpAttributes(ip_node);
-    xmlNode* child = ip_node->xmlChildrenNode;
-    while (child) {
-      if (strcmp(reinterpret_cast<const char*>(child->name), "dhcp") == 0) {
-        return ProcessDhcpNode(child);
-      }
-      child = child->next;
-    }
-    LOG(ERROR) << "dhcp node not found in network xml spec";
-    return false;
+    freeifaddrs(ifa_list);
+    return ret;
   }
 };
 }  // namespace
 
 void InitializeRilRegion() {
   NetConfig netconfig;
-  if (!netconfig.ObtainConfig(FLAGS_mobile_interface)) {
+  auto config = vsoc::CuttlefishConfig::Get();
+  if (!netconfig.ObtainConfig(config->mobile_bridge_name())) {
     LOG(ERROR) << "Unable to obtain the network configuration";
     return;
   }
@@ -175,16 +139,12 @@
 
   auto dest = region->data();
 
-  snprintf(
-      dest->ipaddr, sizeof(dest->ipaddr), "%s", netconfig.ril_ipaddr.c_str());
-  snprintf(dest->gateway,
-           sizeof(dest->gateway),
-           "%s",
+  snprintf(dest->ipaddr, sizeof(dest->ipaddr), "%s",
+           netconfig.ril_ipaddr.c_str());
+  snprintf(dest->gateway, sizeof(dest->gateway), "%s",
            netconfig.ril_gateway.c_str());
   snprintf(dest->dns, sizeof(dest->dns), "%s", netconfig.ril_dns.c_str());
-  snprintf(dest->broadcast,
-           sizeof(dest->broadcast),
-           "%s",
+  snprintf(dest->broadcast, sizeof(dest->broadcast), "%s",
            netconfig.ril_broadcast.c_str());
   dest->prefixlen = netconfig.ril_prefixlen;
 }
diff --git a/host/commands/launch/screen_region_handler.cc b/host/commands/launch/screen_region_handler.cc
index 4214482..6e19ca1 100644
--- a/host/commands/launch/screen_region_handler.cc
+++ b/host/commands/launch/screen_region_handler.cc
@@ -14,29 +14,23 @@
  * limitations under the License.
  */
 
-#include <gflags/gflags.h>
 #include <glog/logging.h>
 
 #include "common/vsoc/lib/screen_region_view.h"
 #include "host/commands/launch/pre_launch_initializers.h"
-#include "host/libs/config/host_config.h"
-
-DEFINE_int32(x_res, 720, "Width of the screen in pixels");
-DEFINE_int32(y_res, 1280, "Height of the screen in pixels");
-DEFINE_int32(dpi, 160, "Pixels per inch for the screen");
-DEFINE_int32(refresh_rate_hz, 60, "Screen refresh rate in Hertz");
-DEFINE_int32(num_screen_buffers, 3, "The number of screen buffers");
+#include "host/libs/config/cuttlefish_config.h"
 
 void InitializeScreenRegion() {
   auto region =
       vsoc::screen::ScreenRegionView::GetInstance(vsoc::GetDomain().c_str());
+  auto config = vsoc::CuttlefishConfig::Get();
   if (!region) {
-    LOG(ERROR) << "Screen region was not found";
+    LOG(FATAL) << "Screen region was not found";
     return;
   }
   auto dest = region->data();
-  dest->x_res = FLAGS_x_res;
-  dest->y_res = FLAGS_y_res;
-  dest->dpi = FLAGS_dpi;
-  dest->refresh_rate_hz = FLAGS_refresh_rate_hz;
+  dest->x_res = config->x_res();
+  dest->y_res = config->y_res();
+  dest->dpi = config->dpi();
+  dest->refresh_rate_hz = config->refresh_rate_hz();
 }
diff --git a/host/commands/launch/wifi_region_handler.cc b/host/commands/launch/wifi_region_handler.cc
index 7f82c6a..9d87c64 100644
--- a/host/commands/launch/wifi_region_handler.cc
+++ b/host/commands/launch/wifi_region_handler.cc
@@ -14,60 +14,38 @@
  * limitations under the License.
  */
 
-#include <cassert>
 #include <string>
 
-#include <gflags/gflags.h>
 #include <glog/logging.h>
 
 #include "common/vsoc/lib/wifi_exchange_view.h"
 #include "host/commands/launch/pre_launch_initializers.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 
 using vsoc::wifi::WifiExchangeView;
 
-namespace {
-
-std::string GetPerInstanceDefaultMacAddress(const char* base_mac) {
-  WifiExchangeView::MacAddress addr;
-  if (!WifiExchangeView::ParseMACAddress(base_mac, &addr)) {
-    LOG(FATAL) << "Unable to parse MAC address: " << base_mac;
-    return "";
-  }
-  // Modify the last byte of the mac address to make it different for every cvd
-  addr.back() = static_cast<uint8_t>(vsoc::GetPerInstanceDefault(addr.back()));
-  return WifiExchangeView::MacAddressToString(addr);
-}
-
-}  // namespace
-
-DEFINE_string(guest_mac_address,
-              GetPerInstanceDefaultMacAddress("00:43:56:44:80:01"),
-              "MAC address of the wifi interface to be created on the guest.");
-
-DEFINE_string(host_mac_address,
-              "42:00:00:00:00:00",
-              "MAC address of the wifi interface running on the host.");
-
 void InitializeWifiRegion() {
   auto region = WifiExchangeView::GetInstance(vsoc::GetDomain().c_str());
+  auto config = vsoc::CuttlefishConfig::Get();
   if (!region) {
     LOG(FATAL) << "Wifi region not found";
     return;
   }
   WifiExchangeView::MacAddress guest_mac, host_mac;
-  if (!WifiExchangeView::ParseMACAddress(FLAGS_guest_mac_address, &guest_mac)) {
+  if (!WifiExchangeView::ParseMACAddress(config->wifi_guest_mac_addr(),
+                                         &guest_mac)) {
     LOG(FATAL) << "Unable to parse guest mac address: "
-               << FLAGS_guest_mac_address;
+               << config->wifi_guest_mac_addr();
     return;
   }
-  LOG(INFO) << "Setting guest mac to " << FLAGS_guest_mac_address;
+  LOG(INFO) << "Setting guest mac to " << config->wifi_guest_mac_addr();
   region->SetGuestMACAddress(guest_mac);
-  if (!WifiExchangeView::ParseMACAddress(FLAGS_host_mac_address, &host_mac)) {
+  if (!WifiExchangeView::ParseMACAddress(config->wifi_host_mac_addr(),
+                                         &host_mac)) {
     LOG(FATAL) << "Unable to parse guest mac address: "
-               << FLAGS_guest_mac_address;
+               << config->wifi_guest_mac_addr();
     return;
   }
-  LOG(INFO) << "Setting host mac to " << FLAGS_host_mac_address;
+  LOG(INFO) << "Setting host mac to " << config->wifi_host_mac_addr();
   region->SetHostMACAddress(host_mac);
 }
diff --git a/host/commands/record_audio/Android.bp b/host/commands/record_audio/Android.bp
index d380e23..b7bfe92 100644
--- a/host/commands/record_audio/Android.bp
+++ b/host/commands/record_audio/Android.bp
@@ -27,6 +27,7 @@
     ],
     static_libs: [
         "libcuttlefish_host_config",
+        "libjsoncpp",
         "libgflags",
     ],
     defaults: ["cuttlefish_host_only"],
diff --git a/host/commands/record_audio/main.cc b/host/commands/record_audio/main.cc
index 2655838..18466f3 100644
--- a/host/commands/record_audio/main.cc
+++ b/host/commands/record_audio/main.cc
@@ -17,7 +17,7 @@
 #include "common/vsoc/lib/audio_data_region_view.h"
 #include "common/vsoc/lib/circqueue_impl.h"
 #include "common/vsoc/lib/vsoc_audio_message.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 
 #include "WaveWriter.h"
 
diff --git a/host/commands/stop_cvd/Android.bp b/host/commands/stop_cvd/Android.bp
index 429fd6c..3607e8e 100644
--- a/host/commands/stop_cvd/Android.bp
+++ b/host/commands/stop_cvd/Android.bp
@@ -23,10 +23,16 @@
     ],
     shared_libs: [
         "libbase",
+        "libcuttlefish_fs",
+        "cuttlefish_auto_resources",
+        "libicuuc",
     ],
     static_libs: [
         "libcuttlefish_host_config",
+        "libcuttlefish_vm_manager",
+        "libjsoncpp",
         "libgflags",
+        "libxml2",
     ],
     defaults: ["cuttlefish_host_only"],
 }
diff --git a/host/commands/stop_cvd/main.cc b/host/commands/stop_cvd/main.cc
index 2c2baf7..08648b1 100644
--- a/host/commands/stop_cvd/main.cc
+++ b/host/commands/stop_cvd/main.cc
@@ -35,26 +35,15 @@
 #include <gflags/gflags.h>
 #include <glog/logging.h>
 
-#include "host/libs/config/host_config.h"
-
-using vsoc::GetDefaultPerInstancePath;
-using vsoc::GetPerInstanceDefault;
-
-DECLARE_int32(instance);
-// TODO(b/78512938): These parameters should go away when the launcher work is
-// completed and the process monitor handles the shutdown.
-DEFINE_string(hypervisor_uri, "qemu:///system", "Hypervisor cannonical uri.");
-std::string g_default_mempath{GetPerInstanceDefault("/var/run/shm/cvd-")};
-DEFINE_string(mempath,
-              g_default_mempath.c_str(),
-              "Target location for the shmem file.");
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/vm_manager/libvirt_manager.h"
 
 namespace {
 void RunCommand(const char* command) {
-  LOG(INFO) << "Running: " << command;
   int rval = std::system(command);
   if (rval) {
-    LOG(ERROR) << "Unable to execute command: " << command;
+    LOG(ERROR) << "Unable to execute command: " << command
+               << ". Exit code: " << rval;
   }
 }
 }  // anonymous namespace
@@ -63,25 +52,28 @@
   ::android::base::InitLogging(argv, android::base::StderrLogger);
   google::ParseCommandLineFlags(&argc, &argv, true);
 
+  int exit_code = 0;
+
   // TODO(b/78512938): Should ask the monitor to do the shutdown instead
-  std::ostringstream cvd_strm;
-  cvd_strm << "cvd-" << std::setfill('0') << std::setw(2) << FLAGS_instance;
-  auto cvd = cvd_strm.str();
-  std::string destroy_cmd = "virsh ";
-  destroy_cmd += "-c ";
-  destroy_cmd += FLAGS_hypervisor_uri;
-  destroy_cmd += " destroy ";
-  destroy_cmd += cvd;
-  RunCommand(destroy_cmd.c_str());
+  vm_manager::LibvirtManager libvirt_manager;
+  if (!libvirt_manager.Stop()) {
+    LOG(ERROR)
+        << "Error when stopping guest virtual machine. Is it still running?";
+    exit_code = 1;
+  }
+
+  auto config = vsoc::CuttlefishConfig::Get();
 
   // TODO(b/78512938): Shouldn't need sudo to shut down
-  std::string run_files = vsoc::GetDefaultPerInstanceDir() + "/*";
+  std::string run_files = config->PerInstancePath("*");
   std::string fuser_cmd = "sudo fuser -k ";
   fuser_cmd += run_files;
   fuser_cmd += " ";
-  fuser_cmd += FLAGS_mempath;
+  fuser_cmd += config->mempath();
   RunCommand(fuser_cmd.c_str());
   std::string delete_cmd = "rm -f ";
   delete_cmd += run_files;
   RunCommand(delete_cmd.c_str());
+
+  return exit_code;
 }
diff --git a/host/frontend/vnc_server/Android.bp b/host/frontend/vnc_server/Android.bp
index cf8a2c4..6508945 100644
--- a/host/frontend/vnc_server/Android.bp
+++ b/host/frontend/vnc_server/Android.bp
@@ -37,6 +37,7 @@
     ],
     static_libs: [
         "libcuttlefish_host_config",
+        "libjsoncpp",
         "libjpeg",
         "libgflags",
     ],
diff --git a/host/frontend/vnc_server/main.cpp b/host/frontend/vnc_server/main.cpp
index 2616202..eab7011 100644
--- a/host/frontend/vnc_server/main.cpp
+++ b/host/frontend/vnc_server/main.cpp
@@ -22,7 +22,7 @@
 #include "common/libs/glog/logging.h"
 #include "host/frontend/vnc_server/vnc_server.h"
 #include "host/frontend/vnc_server/vnc_utils.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 
 DEFINE_bool(agressive, false, "Whether to use agressive server");
 DEFINE_int32(port, 6444, "Port where to listen for connections");
diff --git a/host/frontend/vnc_server/simulated_hw_composer.cpp b/host/frontend/vnc_server/simulated_hw_composer.cpp
index 7141bd1..c8b7f03 100644
--- a/host/frontend/vnc_server/simulated_hw_composer.cpp
+++ b/host/frontend/vnc_server/simulated_hw_composer.cpp
@@ -17,7 +17,7 @@
 #include "host/frontend/vnc_server/simulated_hw_composer.h"
 
 #include "host/frontend/vnc_server/vnc_utils.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 #include "common/vsoc/lib/screen_region_view.h"
 
 using cvd::vnc::SimulatedHWComposer;
diff --git a/host/frontend/vnc_server/vnc_utils.h b/host/frontend/vnc_server/vnc_utils.h
index 558aa57..3eac9f3 100644
--- a/host/frontend/vnc_server/vnc_utils.h
+++ b/host/frontend/vnc_server/vnc_utils.h
@@ -23,7 +23,7 @@
 
 #include "common/libs/tcp_socket/tcp_socket.h"
 #include "common/vsoc/lib/screen_region_view.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 
 namespace cvd {
 namespace vnc {
diff --git a/host/libs/Android.bp b/host/libs/Android.bp
index 12fde97..540b9b4 100644
--- a/host/libs/Android.bp
+++ b/host/libs/Android.bp
@@ -20,4 +20,5 @@
     "ivserver",
     "vadb",
     "usbip",
+    "vm_manager",
 ]
diff --git a/host/libs/config/Android.bp b/host/libs/config/Android.bp
index df9f99b..9b70a07 100644
--- a/host/libs/config/Android.bp
+++ b/host/libs/config/Android.bp
@@ -16,9 +16,7 @@
 cc_library_host_static {
     name: "libcuttlefish_host_config",
     srcs: [
-        "file_partition.cpp",
-        "guest_config.cpp",
-        "host_config.cpp",
+        "cuttlefish_config.cpp"
     ],
     header_libs: [
         "cuttlefish_glog",
@@ -31,6 +29,7 @@
     static_libs: [
         "libxml2",
         "libgflags",
+        "libjsoncpp",
     ],
     defaults: ["cuttlefish_host_only"],
 }
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
new file mode 100644
index 0000000..bd70a95
--- /dev/null
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "host/libs/config/cuttlefish_config.h"
+
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+#include <fstream>
+#include <iomanip>
+#include <sstream>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+#include <json/json.h>
+
+DEFINE_string(config_file,
+              vsoc::GetDefaultPerInstanceDir() + "/cuttlefish_config.json",
+              "A file from where to load the config values. This flag is "
+              "ignored by the launcher");
+
+namespace {
+
+constexpr char kDefaultUuidPrefix[] = "699acfc4-c8c4-11e7-882b-5065f31dc1";
+
+int InstanceFromEnvironment() {
+  static constexpr char kInstanceEnvironmentVariable[] = "CUTTLEFISH_INSTANCE";
+  static constexpr char kVsocUserPrefix[] = "vsoc-";
+  static constexpr int kDefaultInstance = 1;
+
+  // CUTTLEFISH_INSTANCE environment variable
+  const char* instance_str = std::getenv(kInstanceEnvironmentVariable);
+  if (!instance_str) {
+    // Try to get it from the user instead
+    instance_str = std::getenv("USER");
+    if (!instance_str || std::strncmp(instance_str, kVsocUserPrefix,
+                                      sizeof(kVsocUserPrefix) - 1)) {
+      // No user or we don't recognize this user
+      return kDefaultInstance;
+    }
+    instance_str += sizeof(kVsocUserPrefix) - 1;
+    // Set the environment variable so that child processes see it
+    setenv(kInstanceEnvironmentVariable, instance_str, 0);
+  }
+
+  int instance = std::atoi(instance_str);
+  if (instance <= 0) {
+    instance = kDefaultInstance;
+  }
+
+  return instance;
+}
+const char* kSerialNumber = "serial_number";
+const char* kInstanceDir = "instance_dir";
+
+const char* kCpus = "cpus";
+const char* kMemoryMb = "memory_mb";
+const char* kDpi = "dpi";
+const char* kXRes = "x_res";
+const char* kYRes = "y_res";
+const char* kRefreshRateHz = "refresh_rate_hz";
+
+const char* kKernelImagePath = "kernel_image_path";
+const char* kKernelArgs = "kernel_args";
+const char* kRamdiskImagePath = "ramdisk_image_path";
+
+const char* kSystemImagePath = "system_image_path";
+const char* kCacheImagePath = "cache_image_path";
+const char* kDataImagePath = "data_image_path";
+const char* kVendorImagePath = "vendor_image_path";
+const char* kUsbV1SocketName = "usb_v1_socket_name";
+const char* kVhciPort = "vhci_port";
+const char* kUsbIpSocketName = "usb_ip_socket_name";
+const char* kKernelLogSocketName = "kernel_log_socket_name";
+const char* kConsolePath = "console_path";
+const char* kLogcatPath = "logcat_path";
+const char* kDtbPath = "dtb_path";
+
+const char* kMempath = "mempath";
+const char* kIvshmemQemuSocketPath = "ivshmem_qemu_socket_path";
+const char* kIvshmemClientSocketPath = "ivshmem_client_socket_path";
+const char* kIvshmemVectorCount = "ivshmem_vector_count";
+
+const char* kMobileBridgeName = "mobile_bridge_name";
+const char* kMobileTapName = "mobile_tap_name";
+const char* kWifiGuestMacAddr = "wifi_guest_mac_addr";
+const char* kWifiHostMacAddr = "wifi_host_mac_addr";
+const char* kEntropySource = "entropy_source";
+
+const char* kUuid = "uuid";
+const char* kDisableDacSecurity = "disable_dac_security";
+const char* kDisableAppArmorSecurity = "disable_app_armor_security";
+}  // namespace
+
+namespace vsoc {
+
+std::string CuttlefishConfig::instance_dir() const {
+  return (*dictionary_)[kInstanceDir].asString();
+}
+void CuttlefishConfig::set_instance_dir(const std::string& instance_dir) {
+  (*dictionary_)[kInstanceDir] = instance_dir;
+}
+
+std::string CuttlefishConfig::serial_number() const {
+  return (*dictionary_)[kSerialNumber].asString();
+}
+void CuttlefishConfig::set_serial_number(const std::string& serial_number) {
+  (*dictionary_)[kSerialNumber] = serial_number;
+}
+
+int CuttlefishConfig::cpus() const { return (*dictionary_)[kCpus].asInt(); }
+void CuttlefishConfig::set_cpus(int cpus) { (*dictionary_)[kCpus] = cpus; }
+
+int CuttlefishConfig::memory_mb() const {
+  return (*dictionary_)[kMemoryMb].asInt();
+}
+void CuttlefishConfig::set_memory_mb(int memory_mb) {
+  (*dictionary_)[kMemoryMb] = memory_mb;
+}
+
+int CuttlefishConfig::dpi() const { return (*dictionary_)[kDpi].asInt(); }
+void CuttlefishConfig::set_dpi(int dpi) { (*dictionary_)[kDpi] = dpi; }
+
+int CuttlefishConfig::x_res() const { return (*dictionary_)[kXRes].asInt(); }
+void CuttlefishConfig::set_x_res(int x_res) { (*dictionary_)[kXRes] = x_res; }
+
+int CuttlefishConfig::y_res() const { return (*dictionary_)[kYRes].asInt(); }
+void CuttlefishConfig::set_y_res(int y_res) { (*dictionary_)[kYRes] = y_res; }
+
+int CuttlefishConfig::refresh_rate_hz() const {
+  return (*dictionary_)[kRefreshRateHz].asInt();
+}
+void CuttlefishConfig::set_refresh_rate_hz(int refresh_rate_hz) {
+  (*dictionary_)[kRefreshRateHz] = refresh_rate_hz;
+}
+
+std::string CuttlefishConfig::kernel_image_path() const {
+  return (*dictionary_)[kKernelImagePath].asString();
+}
+void CuttlefishConfig::set_kernel_image_path(
+    const std::string& kernel_image_path) {
+  (*dictionary_)[kKernelImagePath] = kernel_image_path;
+}
+
+std::string CuttlefishConfig::kernel_args() const {
+  return (*dictionary_)[kKernelArgs].asString();
+}
+void CuttlefishConfig::set_kernel_args(const std::string& kernel_args) {
+  (*dictionary_)[kKernelArgs] = kernel_args;
+}
+
+std::string CuttlefishConfig::ramdisk_image_path() const {
+  return (*dictionary_)[kRamdiskImagePath].asString();
+}
+void CuttlefishConfig::set_ramdisk_image_path(
+    const std::string& ramdisk_image_path) {
+  (*dictionary_)[kRamdiskImagePath] = ramdisk_image_path;
+}
+
+std::string CuttlefishConfig::system_image_path() const {
+  return (*dictionary_)[kSystemImagePath].asString();
+}
+void CuttlefishConfig::set_system_image_path(
+    const std::string& system_image_path) {
+  (*dictionary_)[kSystemImagePath] = system_image_path;
+}
+
+std::string CuttlefishConfig::cache_image_path() const {
+  return (*dictionary_)[kCacheImagePath].asString();
+}
+void CuttlefishConfig::set_cache_image_path(
+    const std::string& cache_image_path) {
+  (*dictionary_)[kCacheImagePath] = cache_image_path;
+}
+
+std::string CuttlefishConfig::data_image_path() const {
+  return (*dictionary_)[kDataImagePath].asString();
+}
+void CuttlefishConfig::set_data_image_path(const std::string& data_image_path) {
+  (*dictionary_)[kDataImagePath] = data_image_path;
+}
+
+std::string CuttlefishConfig::vendor_image_path() const {
+  return (*dictionary_)[kVendorImagePath].asString();
+}
+void CuttlefishConfig::set_vendor_image_path(
+    const std::string& vendor_image_path) {
+  (*dictionary_)[kVendorImagePath] = vendor_image_path;
+}
+
+std::string CuttlefishConfig::dtb_path() const {
+  return (*dictionary_)[kDtbPath].asString();
+}
+void CuttlefishConfig::set_dtb_path(const std::string& dtb_path) {
+  (*dictionary_)[kDtbPath] = dtb_path;
+}
+
+std::string CuttlefishConfig::mempath() const {
+  return (*dictionary_)[kMempath].asString();
+}
+void CuttlefishConfig::set_mempath(const std::string& mempath) {
+  (*dictionary_)[kMempath] = mempath;
+}
+
+std::string CuttlefishConfig::ivshmem_qemu_socket_path() const {
+  return (*dictionary_)[kIvshmemQemuSocketPath].asString();
+}
+void CuttlefishConfig::set_ivshmem_qemu_socket_path(
+    const std::string& ivshmem_qemu_socket_path) {
+  (*dictionary_)[kIvshmemQemuSocketPath] = ivshmem_qemu_socket_path;
+}
+
+std::string CuttlefishConfig::ivshmem_client_socket_path() const {
+  return (*dictionary_)[kIvshmemClientSocketPath].asString();
+}
+void CuttlefishConfig::set_ivshmem_client_socket_path(
+    const std::string& ivshmem_client_socket_path) {
+  (*dictionary_)[kIvshmemClientSocketPath] = ivshmem_client_socket_path;
+}
+
+int CuttlefishConfig::ivshmem_vector_count() const {
+  return (*dictionary_)[kIvshmemVectorCount].asInt();
+}
+void CuttlefishConfig::set_ivshmem_vector_count(int ivshmem_vector_count) {
+  (*dictionary_)[kIvshmemVectorCount] = ivshmem_vector_count;
+}
+
+std::string CuttlefishConfig::usb_v1_socket_name() const {
+  return (*dictionary_)[kUsbV1SocketName].asString();
+}
+void CuttlefishConfig::set_usb_v1_socket_name(
+    const std::string& usb_v1_socket_name) {
+  (*dictionary_)[kUsbV1SocketName] = usb_v1_socket_name;
+}
+
+int CuttlefishConfig::vhci_port() const {
+  return (*dictionary_)[kVhciPort].asInt();
+}
+void CuttlefishConfig::set_vhci_port(int vhci_port) {
+  (*dictionary_)[kVhciPort] = vhci_port;
+}
+
+std::string CuttlefishConfig::usb_ip_socket_name() const {
+  return (*dictionary_)[kUsbIpSocketName].asString();
+}
+void CuttlefishConfig::set_usb_ip_socket_name(
+    const std::string& usb_ip_socket_name) {
+  (*dictionary_)[kUsbIpSocketName] = usb_ip_socket_name;
+}
+
+std::string CuttlefishConfig::kernel_log_socket_name() const {
+  return (*dictionary_)[kKernelLogSocketName].asString();
+}
+void CuttlefishConfig::set_kernel_log_socket_name(
+    const std::string& kernel_log_socket_name) {
+  (*dictionary_)[kKernelLogSocketName] = kernel_log_socket_name;
+}
+
+std::string CuttlefishConfig::console_path() const {
+  return (*dictionary_)[kConsolePath].asString();
+}
+void CuttlefishConfig::set_console_path(const std::string& console_path) {
+  (*dictionary_)[kConsolePath] = console_path;
+}
+
+std::string CuttlefishConfig::logcat_path() const {
+  return (*dictionary_)[kLogcatPath].asString();
+}
+void CuttlefishConfig::set_logcat_path(const std::string& logcat_path) {
+  (*dictionary_)[kLogcatPath] = logcat_path;
+}
+
+std::string CuttlefishConfig::mobile_bridge_name() const {
+  return (*dictionary_)[kMobileBridgeName].asString();
+}
+void CuttlefishConfig::set_mobile_bridge_name(
+    const std::string& mobile_bridge_name) {
+  (*dictionary_)[kMobileBridgeName] = mobile_bridge_name;
+}
+
+std::string CuttlefishConfig::wifi_guest_mac_addr() const {
+  return (*dictionary_)[kWifiGuestMacAddr].asString();
+}
+void CuttlefishConfig::set_wifi_guest_mac_addr(
+    const std::string& wifi_guest_mac_addr) {
+  (*dictionary_)[kWifiGuestMacAddr] = wifi_guest_mac_addr;
+}
+
+std::string CuttlefishConfig::wifi_host_mac_addr() const {
+  return (*dictionary_)[kWifiHostMacAddr].asString();
+}
+void CuttlefishConfig::set_wifi_host_mac_addr(
+    const std::string& wifi_host_mac_addr) {
+  (*dictionary_)[kWifiHostMacAddr] = wifi_host_mac_addr;
+}
+
+std::string CuttlefishConfig::mobile_tap_name() const {
+  return (*dictionary_)[kMobileTapName].asString();
+}
+void CuttlefishConfig::set_mobile_tap_name(const std::string& mobile_tap_name) {
+  (*dictionary_)[kMobileTapName] = mobile_tap_name;
+}
+
+std::string CuttlefishConfig::entropy_source() const {
+  return (*dictionary_)[kEntropySource].asString();
+}
+void CuttlefishConfig::set_entropy_source(const std::string& entropy_source) {
+  (*dictionary_)[kEntropySource] = entropy_source;
+}
+
+std::string CuttlefishConfig::uuid() const {
+  return (*dictionary_)[kUuid].asString();
+}
+void CuttlefishConfig::set_uuid(const std::string& uuid) {
+  (*dictionary_)[kUuid] = uuid;
+}
+
+bool CuttlefishConfig::disable_dac_security() const {
+  return (*dictionary_)[kDisableDacSecurity].asBool();
+}
+void CuttlefishConfig::set_disable_dac_security(bool disable_dac_security) {
+  (*dictionary_)[kDisableDacSecurity] = disable_dac_security;
+}
+
+bool CuttlefishConfig::disable_app_armor_security() const {
+  return (*dictionary_)[kDisableAppArmorSecurity].asBool();
+}
+void CuttlefishConfig::set_disable_app_armor_security(
+    bool disable_app_armor_security) {
+  (*dictionary_)[kDisableAppArmorSecurity] = disable_app_armor_security;
+}
+
+/*static*/ CuttlefishConfig* CuttlefishConfig::Get() {
+  static CuttlefishConfig config;
+  return &config;
+}
+
+CuttlefishConfig::CuttlefishConfig() : dictionary_(new Json::Value()) {
+  if (!FLAGS_config_file.empty()) {
+    LoadFromFile(FLAGS_config_file.c_str());
+  }
+}
+
+void CuttlefishConfig::LoadFromFile(const char* file) {
+  char real_file_path[PATH_MAX];
+  if (realpath(file, real_file_path) == nullptr) {
+    LOG(FATAL) << "Could not get real path for file " << file << ": "
+               << strerror(errno);
+  }
+
+  Json::Reader reader;
+  std::ifstream ifs(real_file_path);
+  if (!reader.parse(ifs, *dictionary_)) {
+    LOG(FATAL) << "Could not read config file " << file << ": "
+               << reader.getFormattedErrorMessages();
+  }
+}
+bool CuttlefishConfig::SaveToFile(const std::string& file) const {
+  std::ofstream ofs(file);
+  if (!ofs.is_open()) {
+    LOG(ERROR) << "Unable to write to file " << file;
+    return false;
+  }
+  ofs << *dictionary_;
+  return !ofs.fail();
+}
+
+std::string CuttlefishConfig::PerInstancePath(const char* file_name) const {
+  return (instance_dir() + "/") + file_name;
+}
+
+std::string CuttlefishConfig::instance_name() const {
+  return GetPerInstanceDefault("cvd-");
+}
+
+bool CuttlefishConfig::ReadKernelArgs(const std::string& cmdline_file,
+                                      const std::string& extra_args) {
+  std::ostringstream kernel_args;
+  std::ifstream cmd_stream(cmdline_file);
+  if (!cmd_stream) {
+    LOG(WARNING) << "Unable to open " << cmdline_file;
+    return false;
+  } else {
+    kernel_args << cmd_stream.rdbuf();
+    cmd_stream.close();
+  }
+  if (!extra_args.empty()) {
+    kernel_args << " " << extra_args;
+  }
+  set_kernel_args(kernel_args.str());
+  return true;
+}
+
+int GetInstance() {
+  static int instance_id = InstanceFromEnvironment();
+  return instance_id;
+}
+
+std::string GetDomain() {
+  return CuttlefishConfig::Get()->ivshmem_client_socket_path();
+}
+
+std::string GetPerInstanceDefault(const char* prefix) {
+  std::ostringstream stream;
+  stream << prefix << std::setfill('0') << std::setw(2) << GetInstance();
+  return stream.str();
+}
+int GetPerInstanceDefault(int base) { return base + GetInstance() - 1; }
+
+std::string GetDefaultPerInstanceDir() {
+  // TODO(79170615): Change to a directory in home once libvirt is no longer
+  // default.
+  std::ostringstream stream;
+  stream << "/var/run/libvirt-" << kDefaultUuidPrefix << std::setfill('0')
+         << std::setw(2) << GetInstance();
+  return stream.str();
+}
+
+}  // namespace vsoc
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
new file mode 100644
index 0000000..50e8616
--- /dev/null
+++ b/host/libs/config/cuttlefish_config.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <memory>
+#include <string>
+
+namespace Json {
+class Value;
+}
+
+namespace vsoc {
+
+// Holds the configuration of the cuttlefish instances.
+class CuttlefishConfig {
+ public:
+  static CuttlefishConfig* Get();
+  ~CuttlefishConfig() = default;
+
+  // Saves the configuration object in a file, it can then be read in other
+  // processes by passing the --config_file option.
+  bool SaveToFile(const std::string& file) const ;
+
+  // Returns the path to a file with the given name in the instance directory..
+  std::string PerInstancePath(const char* file_name) const;
+
+  std::string instance_name() const;
+
+  void disable_usb_adb() {
+    // This seems to be the way usb is being disbled in the launcher
+    set_usb_v1_socket_name("");
+  }
+
+  // Reads the kernel command line from a file and appends extra arguments.
+  bool ReadKernelArgs(const std::string& cmdline_file,
+                      const std::string& extra_args);
+
+  std::string instance_dir() const;
+  void set_instance_dir(const std::string& instance_dir);
+
+  std::string serial_number() const;
+  void set_serial_number(const std::string& serial_number);
+
+  int cpus() const;
+  void set_cpus(int cpus);
+
+  int memory_mb() const;
+  void set_memory_mb(int memory_mb);
+
+  int dpi() const;
+  void set_dpi(int dpi);
+
+  int x_res() const;
+  void set_x_res(int x_res);
+
+  int y_res() const;
+  void set_y_res(int y_res);
+
+  int refresh_rate_hz() const;
+  void set_refresh_rate_hz(int refresh_rate_hz);
+
+  std::string kernel_image_path() const;
+  void set_kernel_image_path(const std::string& kernel_image_path);
+
+  std::string kernel_args() const;
+  void set_kernel_args(const std::string& kernel_args);
+
+  std::string ramdisk_image_path() const;
+  void set_ramdisk_image_path(const std::string& ramdisk_image_path);
+
+  std::string system_image_path() const;
+  void set_system_image_path(const std::string& system_image_path);
+
+  std::string cache_image_path() const;
+  void set_cache_image_path(const std::string& cache_image_path);
+
+  std::string data_image_path() const;
+  void set_data_image_path(const std::string& data_image_path);
+
+  std::string vendor_image_path() const;
+  void set_vendor_image_path(const std::string& vendor_image_path);
+
+  std::string dtb_path() const;
+  void set_dtb_path(const std::string& dtb_path);
+
+  std::string mempath() const;
+  void set_mempath(const std::string& mempath);
+
+  std::string ivshmem_qemu_socket_path() const;
+  void set_ivshmem_qemu_socket_path(
+      const std::string& ivshmem_qemu_socket_path);
+
+  std::string ivshmem_client_socket_path() const;
+  void set_ivshmem_client_socket_path(
+      const std::string& ivshmem_client_socket_path);
+
+  int ivshmem_vector_count() const;
+  void set_ivshmem_vector_count(int ivshmem_vector_count);
+
+  // The name of the socket that will be used to forward access to USB gadget.
+  // This is for V1 of the USB bus.
+  std::string usb_v1_socket_name() const;
+  void set_usb_v1_socket_name(const std::string& usb_v1_socket_name);
+
+  int vhci_port() const;
+  void set_vhci_port(int vhci_port);
+
+  std::string usb_ip_socket_name() const;
+  void set_usb_ip_socket_name(const std::string& usb_ip_socket_name);
+
+  std::string kernel_log_socket_name() const;
+  void set_kernel_log_socket_name(const std::string& kernel_log_socket_name);
+
+  std::string console_path() const;
+  void set_console_path(const std::string& console_path);
+
+  std::string logcat_path() const;
+  void set_logcat_path(const std::string& logcat_path);
+
+  std::string mobile_bridge_name() const;
+  void set_mobile_bridge_name(const std::string& mobile_bridge_name);
+
+  std::string mobile_tap_name() const;
+  void set_mobile_tap_name(const std::string& mobile_tap_name);
+
+  std::string wifi_guest_mac_addr() const;
+  void set_wifi_guest_mac_addr(const std::string& wifi_guest_mac_addr);
+
+  std::string wifi_host_mac_addr() const;
+  void set_wifi_host_mac_addr(const std::string& wifi_host_mac_addr);
+
+  std::string entropy_source() const;
+  void set_entropy_source(const std::string& entropy_source);
+
+  std::string uuid() const;
+  void set_uuid(const std::string& uuid);
+
+  bool disable_dac_security() const;
+  void set_disable_dac_security(bool disable_dac_security);
+
+  bool disable_app_armor_security() const;
+  void set_disable_app_armor_security(bool disable_app_armor_security);
+
+ private:
+  std::unique_ptr<Json::Value> dictionary_;
+
+  void LoadFromFile(const char* file);
+
+  CuttlefishConfig();
+  CuttlefishConfig(const CuttlefishConfig&) = delete;
+  CuttlefishConfig& operator=(const CuttlefishConfig&) = delete;
+};
+
+// Returns the instance number as obtained from the CUTTLEFISH_INSTANCE
+// environment variable or the username.
+int GetInstance();
+
+// Returns the path to the ivserver's client socket.
+std::string GetDomain();
+
+// These functions modify a given base value to make it different accross
+// different instances by appending the instance id in case of strings or adding
+// it in case of integers.
+std::string GetPerInstanceDefault(const char* prefix);
+int GetPerInstanceDefault(int base);
+
+std::string GetDefaultPerInstanceDir();
+
+}  // namespace vsoc
diff --git a/host/libs/config/file_partition.cpp b/host/libs/config/file_partition.cpp
deleted file mode 100644
index ede4870..0000000
--- a/host/libs/config/file_partition.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <errno.h>
-#include <limits.h>
-
-#include <sstream>
-
-#include <glog/logging.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/config/file_partition.h"
-
-namespace config {
-namespace {
-constexpr char kTempFileSuffix[] = ".img";
-
-void Initialize(const std::string& path) {
-  std::string command = "/sbin/mkfs.ext4 -F '" + path + "' &>/dev/null";
-  CHECK(system(command.c_str()) == 0)
-      << "Could not initialize filesystem on partition image " << path << ": "
-      << strerror(errno);
-}
-}  // namespace
-
-FilePartition::~FilePartition() {
-  if (should_delete_) {
-    LOG(INFO) << "Deleting partition image file " << name_;
-    errno = 0;
-    unlink(name_.c_str());
-    if (errno != 0) {
-      LOG(WARNING) << "Could not delete partition image file: "
-                   << strerror(errno);
-    }
-  }
-}
-
-std::unique_ptr<FilePartition> FilePartition::ReuseExistingFile(
-    const std::string& path) {
-  return std::unique_ptr<FilePartition>(new FilePartition(path, false));
-}
-
-std::unique_ptr<FilePartition> FilePartition::CreateNewFile(
-    const std::string& path, int size_mb) {
-  {
-    cvd::SharedFD fd(cvd::SharedFD::Open(path.c_str(), O_CREAT | O_RDWR, 0600));
-    CHECK(fd->IsOpen()) << "Could not open file: " << path << ": "
-                        << fd->StrError();
-    CHECK(fd->Truncate(size_mb << 20) == 0)
-        << "Could not truncate file " << path << ": " << fd->StrError();
-  }
-
-  Initialize(path);
-  return std::unique_ptr<FilePartition>(new FilePartition(path, false));
-}
-
-// Create temporary FilePartition object using supplied prefix.
-// Newly created file will be deleted after this instance is destroyed.
-std::unique_ptr<FilePartition> FilePartition::CreateTemporaryFile(
-    const std::string& prefix, int size_mb) {
-  std::stringstream ss;
-  ss << prefix << "-XXXXXX" << kTempFileSuffix;
-  char path[PATH_MAX];
-  strncpy(&path[0], ss.str().c_str(), sizeof(path));
-
-  {
-    int raw_fd = mkostemps(&path[0], strlen(kTempFileSuffix), O_RDWR | O_CREAT);
-    CHECK(raw_fd > 0) << "Could not create temporary file: " << strerror(errno);
-    CHECK(ftruncate(raw_fd, size_mb << 20) == 0)
-        << "Could not truncate file " << path << ": " << strerror(errno);
-    close(raw_fd);
-  }
-
-  Initialize(path);
-  return std::unique_ptr<FilePartition>(new FilePartition(path, true));
-}
-
-}  // namespace config
diff --git a/host/libs/config/file_partition.h b/host/libs/config/file_partition.h
deleted file mode 100644
index 3c8e55b..0000000
--- a/host/libs/config/file_partition.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <memory>
-#include <string>
-
-namespace config {
-// FilePartition class manages partition image files.
-// Partition image files can be reused or created on demand. Temporary images
-// are deleted when corresponding instances of FilePartition object are
-// destroyed.
-class FilePartition {
- public:
-  ~FilePartition();
-
-  // Create FilePartition object from existing file.
-  // Specified file will not be disposed of after this instance is destroyed.
-  static std::unique_ptr<FilePartition> ReuseExistingFile(
-      const std::string& path);
-
-  // Create FilePartition object at specified location and initialize content.
-  // Specified file will not be disposed of after this instance is destroyed.
-  static std::unique_ptr<FilePartition> CreateNewFile(const std::string& path,
-                                                      int size_mb);
-
-  // Create temporary FilePartition object using supplied prefix.
-  // Newly created file will be deleted after this instance is destroyed.
-  static std::unique_ptr<FilePartition> CreateTemporaryFile(
-      const std::string& prefix, int size_mb);
-
-  const std::string& GetName() const { return name_; }
-
- private:
-  std::string name_;
-  bool should_delete_ = false;
-
-  FilePartition(const std::string& name, bool should_delete)
-      : name_(name), should_delete_(should_delete) {}
-
-  FilePartition(const FilePartition&) = delete;
-  FilePartition& operator=(const FilePartition&) = delete;
-};
-
-}  // namespace config
diff --git a/host/libs/config/guest_config.h b/host/libs/config/guest_config.h
deleted file mode 100644
index ff7432f..0000000
--- a/host/libs/config/guest_config.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <memory>
-#include <string>
-
-namespace config {
-// GuestConfig builds XML document describing target VM.
-// Documents built by GuestConfig can be directly used by libvirt to instantiate
-// new virtual machine.
-class GuestConfig {
- public:
-  GuestConfig() = default;
-  ~GuestConfig() = default;
-
-  // Set instance ID.
-  GuestConfig& SetID(int id) {
-    id_ = id;
-    return *this;
-  }
-
-  // Set number of virtual CPUs.
-  GuestConfig& SetVCPUs(int vcpus) {
-    vcpus_ = vcpus;
-    return *this;
-  }
-
-  // Set total memory amount it MB.
-  GuestConfig& SetMemoryMB(int mem_mb) {
-    memory_mb_ = mem_mb;
-    return *this;
-  }
-
-  // Set kernel path.
-  GuestConfig& SetKernelName(const std::string& kernel) {
-    kernel_name_ = kernel;
-    return *this;
-  }
-
-  // Set kernel cmdline arguments.
-  GuestConfig& SetKernelArgs(const std::string& args) {
-    kernel_args_ = args;
-    return *this;
-  }
-
-  // Set initrd path.
-  GuestConfig& SetInitRDName(const std::string& initrd) {
-    initrd_name_ = initrd;
-    return *this;
-  }
-
-  // Set Android system partition image path.
-  GuestConfig& SetSystemPartitionPath(const std::string& path) {
-    system_partition_path_ = path;
-    return *this;
-  }
-
-  // Set Android data partition image path.
-  GuestConfig& SetCachePartitionPath(const std::string& path) {
-    cache_partition_path_ = path;
-    return *this;
-  }
-
-  // Set Android data partition image path.
-  GuestConfig& SetDataPartitionPath(const std::string& path) {
-    data_partition_path_ = path;
-    return *this;
-  }
-
-  // Set Android vendor partition image path.
-  GuestConfig& SetVendorPartitionPath(const std::string& path) {
-    vendor_partition_path_ = path;
-    return *this;
-  }
-
-  // Set ivshmem server socket path.
-  GuestConfig& SetIVShMemSocketPath(const std::string& path) {
-    ivshmem_socket_path_ = path;
-    return *this;
-  }
-
-  // Set number of vectors supplied by ivserver.
-  GuestConfig& SetIVShMemVectorCount(int count) {
-    ivshmem_vector_count_ = count;
-    return *this;
-  }
-
-  // Set name of the mobile bridge, eg. br0
-  GuestConfig& SetMobileBridgeName(const std::string& name) {
-    mobile_bridge_name_ = name;
-    return *this;
-  }
-
-  // Set source of entropy, eg. /dev/urandom.
-  GuestConfig& SetEntropySource(const std::string& source) {
-    entropy_source_ = source;
-    return *this;
-  }
-
-  // Flags to disable the AppArmor security features of libvirt
-  GuestConfig& SetDisableAppArmorSecurity(bool value) {
-    disable_app_armor_security_ = value;
-    return *this;
-  }
-
-  // Flags to disable the DAC security features of libvirt
-  GuestConfig& SetDisableDACSecurity(bool value) {
-    disable_dac_security_ = value;
-    return *this;
-  }
-
-  // The UUID that libvirt uses to identify the instance
-  GuestConfig& SetUUID(const std::string& uuid) {
-    uuid_ = uuid;
-    return *this;
-  }
-
-  // GetInstanceName returns name of this newly created instance.
-  std::string GetInstanceName() const;
-
-  // GetUSBSocketName returns name of the USB socket that will be used to
-  // forward access to USB gadget. This is for V1 of the USB bus.
-  std::string GetUSBV1SocketName() const { return usb_v1_socket_name_; }
-
-  GuestConfig& SetUSBV1SocketName(const std::string& source) {
-    usb_v1_socket_name_ = source;
-    return *this;
-  }
-
-  std::string GetKernelLogSocketName() const { return kernel_log_socket_name_; }
-
-  GuestConfig& SetKernelLogSocketName(const std::string& source) {
-    kernel_log_socket_name_ = source;
-    return *this;
-  }
-
-  // Build document as formatted XML string.
-  std::string Build() const;
-
- private:
-  int id_;
-  int vcpus_;
-  int memory_mb_;
-
-  std::string kernel_name_;
-  std::string kernel_args_;
-  std::string initrd_name_;
-
-  std::string system_partition_path_;
-  std::string cache_partition_path_;
-  std::string data_partition_path_;
-  std::string vendor_partition_path_;
-  std::string usb_v1_socket_name_;
-  std::string kernel_log_socket_name_;
-
-  std::string ivshmem_socket_path_;
-  int ivshmem_vector_count_;
-
-  std::string mobile_bridge_name_;
-  std::string entropy_source_;
-
-  std::string uuid_;
-  bool disable_dac_security_;
-  bool disable_app_armor_security_;
-
-  GuestConfig(const GuestConfig&) = delete;
-  GuestConfig& operator=(const GuestConfig&) = delete;
-};
-
-}  // namespace config
diff --git a/host/libs/config/host_config.cpp b/host/libs/config/host_config.cpp
deleted file mode 100644
index df39bb6..0000000
--- a/host/libs/config/host_config.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "host/libs/config/host_config.h"
-
-#include <cstdlib>
-#include <cstring>
-#include <string>
-#include <iomanip>
-#include <sstream>
-
-#include <gflags/gflags.h>
-
-constexpr char kDefaultUuidPrefix[] = "699acfc4-c8c4-11e7-882b-5065f31dc1";
-
-DEFINE_string(domain, vsoc::GetDefaultShmClientSocketPath(),
-              "Path to the ivshmem client socket");
-DEFINE_int32(instance, vsoc::GetDefaultInstance(),
-             "Instance number. Must be unique.");
-DEFINE_string(uuid, vsoc::GetPerInstanceDefault(kDefaultUuidPrefix).c_str(),
-              "UUID to use for the device. Random if not specified");
-
-int vsoc::GetDefaultInstance() {
-  static constexpr char kVsocUserPrefix[] = "vsoc-";
-  const char* user = std::getenv("USER");
-  if (user && !std::strncmp(user, kVsocUserPrefix,
-                            sizeof(kVsocUserPrefix) - 1)) {
-    int temp = std::atoi(user + sizeof(kVsocUserPrefix) - 1);
-    if (temp > 0) {
-      return temp;
-    }
-  }
-  return 1;
-}
-
-std::string vsoc::GetPerInstanceDefault(const char* prefix) {
-  std::ostringstream stream;
-  stream << prefix << std::setfill('0') << std::setw(2)
-         << GetDefaultInstance();
-  return stream.str();
-}
-
-int vsoc::GetPerInstanceDefault(int base) {
-  return base + GetDefaultInstance() - 1;
-}
-
-std::string vsoc::GetDefaultPerInstanceDir() {
-  std::ostringstream stream;
-  stream << "/var/run/libvirt-" << kDefaultUuidPrefix;
-  return vsoc::GetPerInstanceDefault(stream.str().c_str());
-}
-
-std::string vsoc::GetDefaultPerInstancePath(const std::string& basename) {
-  std::ostringstream stream;
-  stream << GetDefaultPerInstanceDir() << "/" << basename;
-  return stream.str();
-}
-
-std::string vsoc::GetDefaultShmClientSocketPath() {
-  return vsoc::GetDefaultPerInstancePath("ivshmem_socket_client");
-}
-
-std::string vsoc::GetDomain() {
-  return FLAGS_domain;
-}
diff --git a/host/libs/vm_manager/Android.bp b/host/libs/vm_manager/Android.bp
new file mode 100644
index 0000000..1c23f0a
--- /dev/null
+++ b/host/libs/vm_manager/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_host_static {
+    name: "libcuttlefish_vm_manager",
+    srcs: [
+        "libvirt_manager.cpp",
+    ],
+    header_libs: [
+        "cuttlefish_glog",
+    ],
+    shared_libs: [
+        "libcuttlefish_fs",
+        "cuttlefish_auto_resources",
+        "libbase",
+        "libicuuc",
+    ],
+    static_libs: [
+        "libxml2",
+        "libgflags",
+        "libcuttlefish_host_config",
+        "libjsoncpp",
+    ],
+    defaults: ["cuttlefish_host_only"],
+}
\ No newline at end of file
diff --git a/host/libs/config/guest_config.cpp b/host/libs/vm_manager/libvirt_manager.cpp
similarity index 75%
rename from host/libs/config/guest_config.cpp
rename to host/libs/vm_manager/libvirt_manager.cpp
index a812966..6c6f4a1 100644
--- a/host/libs/config/guest_config.cpp
+++ b/host/libs/vm_manager/libvirt_manager.cpp
@@ -14,41 +14,26 @@
  * limitations under the License.
  */
 
-#include "host/libs/config/guest_config.h"
+#include "host/libs/vm_manager/libvirt_manager.h"
+
+#include <stdio.h>
+#include <cstdlib>
 #include <iomanip>
 #include <sstream>
 
 #include <gflags/gflags.h>
 #include <glog/logging.h>
 #include <libxml/tree.h>
-#include "host/libs/config/host_config.h"
 
-namespace {
-std::string StringFromEnv(const char* varname, std::string defval) {
-  const char* const valstr = getenv(varname);
-  if (!valstr) {
-    return defval;
-  }
-  return valstr;
-}
-}  // namespace
+DEFINE_string(hypervisor_uri, "qemu:///system", "Hypervisor cannonical uri.");
+DEFINE_bool(log_xml, false, "Log the XML machine configuration");
 
-
-std::string g_default_libvirt_domain{vsoc::GetPerInstanceDefault("cvd-")};
-//TODO(b/72969289) This should be generated
-DEFINE_string(dtb,
-              StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
-                  "/config/cuttlefish.dtb",
-              "Location of the cuttlefish.dtb file.");
-DEFINE_string(libvirt_domain, g_default_libvirt_domain.c_str(),
-              "Domain name to use with libvirt");
-
-// This class represents libvirt guest configuration.
 // A lot of useful information about the document created here can be found on
 // these websites:
 // - https://libvirt.org/formatdomain.html
 // - https://wiki.libvirt.org/page/Virtio
-namespace config {
+namespace vm_manager {
+
 namespace {
 // This trivial no-op helper function serves purpose of making libxml2 happy.
 // Apparently, *most* (not all!) string literals in libxml2 have to be of
@@ -120,7 +105,7 @@
 // This section configures target os (<os>).
 void ConfigureOperatingSystem(xmlNode* root, const std::string& kernel,
                               const std::string& initrd,
-                              const std::string& args) {
+                              const std::string& args, const std::string& dtb) {
   auto os = xmlNewChild(root, nullptr, xc("os"), nullptr);
 
   auto type = xmlNewChild(os, nullptr, xc("type"), xc("hvm"));
@@ -130,7 +115,7 @@
   xmlNewChild(os, nullptr, xc("kernel"), xc(kernel.c_str()));
   xmlNewChild(os, nullptr, xc("initrd"), xc(initrd.c_str()));
   xmlNewChild(os, nullptr, xc("cmdline"), xc(args.c_str()));
-  xmlNewChild(os, nullptr, xc("dtb"), xc(FLAGS_dtb.c_str()));
+  xmlNewChild(os, nullptr, xc("dtb"), xc(dtb.c_str()));
 }
 
 // Configure QEmu specific arguments.
@@ -210,7 +195,9 @@
 // This section adds <channel> elements to <devices> node.
 void ConfigureVirtioChannel(xmlNode* devices, int port, const std::string& name,
                             DeviceSourceType type, const std::string& path) {
-  if (path.empty()) { return; }
+  if (path.empty()) {
+    return;
+  }
   auto vch = xmlNewChild(devices, nullptr, xc("channel"), nullptr);
   ConfigureDeviceSource(vch, type, path);
 
@@ -262,14 +249,19 @@
   xmlNewProp(bend, xc("model"), xc("random"));
 }
 
-}  // namespace
-
-std::string GuestConfig::GetInstanceName() const {
-  return FLAGS_libvirt_domain;
+std::string GetLibvirtCommand() {
+  std::string cmd = "virsh";
+  if (!FLAGS_hypervisor_uri.empty()) {
+    cmd += " -c " + FLAGS_hypervisor_uri;
+  }
+  return cmd;
 }
 
-std::string GuestConfig::Build() const {
-  std::string instance_name = GetInstanceName();
+}  // namespace
+
+std::string LibvirtManager::BuildXmlConfig() const {
+  auto config = vsoc::CuttlefishConfig::Get();
+  std::string instance_name = config->instance_name();
 
   std::unique_ptr<xmlDoc, void (*)(xmlDocPtr)> xml{xmlNewDoc(xc("1.0")),
                                                    xmlFreeDoc};
@@ -277,23 +269,27 @@
   xmlDocSetRootElement(xml.get(), root);
   xmlNewProp(root, xc("type"), xc("kvm"));
 
-  ConfigureVM(root, instance_name, vcpus_, memory_mb_, uuid_);
+  ConfigureVM(root, instance_name, config->cpus(), config->memory_mb(),
+              config->uuid());
   ConfigureVMFeatures(root, {"acpi", "apic", "hap"});
-  ConfigureOperatingSystem(root, kernel_name_, initrd_name_, kernel_args_);
+  ConfigureOperatingSystem(root, config->kernel_image_path(),
+                           config->ramdisk_image_path(), config->kernel_args(),
+                           config->dtb_path());
   ConfigureQEmuSpecificOptions(
-      root,
-      {"-chardev", concat("socket,path=", ivshmem_socket_path_, ",id=ivsocket"),
-       "-device",
-       concat("ivshmem-doorbell,chardev=ivsocket,vectors=",
-              ivshmem_vector_count_),
-       "-cpu", "host"});
+      root, {"-chardev",
+             concat("socket,path=", config->ivshmem_qemu_socket_path(),
+                    ",id=ivsocket"),
+             "-device",
+             concat("ivshmem-doorbell,chardev=ivsocket,vectors=",
+                    config->ivshmem_vector_count()),
+             "-cpu", "host"});
 
-  if (disable_app_armor_security_) {
+  if (config->disable_app_armor_security()) {
     auto seclabel = xmlNewChild(root, nullptr, xc("seclabel"), nullptr);
     xmlNewProp(seclabel, xc("type"), xc("none"));
     xmlNewProp(seclabel, xc("model"), xc("apparmor"));
   }
-  if (disable_dac_security_) {
+  if (config->disable_dac_security()) {
     auto seclabel = xmlNewChild(root, nullptr, xc("seclabel"), nullptr);
     xmlNewProp(seclabel, xc("type"), xc("none"));
     xmlNewProp(seclabel, xc("model"), xc("dac"));
@@ -302,30 +298,65 @@
   auto devices = xmlNewChild(root, nullptr, xc("devices"), nullptr);
 
   ConfigureSerialPort(devices, 0, DeviceSourceType::kUnixSocketClient,
-                      GetKernelLogSocketName());
+                      config->kernel_log_socket_name());
   ConfigureSerialPort(devices, 1, DeviceSourceType::kUnixSocketServer,
-                      vsoc::GetDefaultPerInstancePath("console"));
+                      config->console_path());
   ConfigureVirtioChannel(devices, 1, "cf-logcat", DeviceSourceType::kFile,
-                         vsoc::GetDefaultPerInstancePath("logcat"));
+                         config->logcat_path());
   ConfigureVirtioChannel(devices, 2, "cf-gadget-usb-v1",
                          DeviceSourceType::kUnixSocketClient,
-                         GetUSBV1SocketName());
+                         config->usb_v1_socket_name());
 
-  ConfigureDisk(devices, "vda", system_partition_path_);
-  ConfigureDisk(devices, "vdb", data_partition_path_);
-  ConfigureDisk(devices, "vdc", cache_partition_path_);
-  ConfigureDisk(devices, "vdd", vendor_partition_path_);
+  ConfigureDisk(devices, "vda", config->system_image_path());
+  ConfigureDisk(devices, "vdb", config->data_image_path());
+  ConfigureDisk(devices, "vdc", config->cache_image_path());
+  ConfigureDisk(devices, "vdd", config->vendor_image_path());
 
-  ConfigureNIC(devices, concat("amobile", id_), mobile_bridge_name_, id_, 1);
-  ConfigureHWRNG(devices, entropy_source_);
+  ConfigureNIC(devices, config->mobile_tap_name(), config->mobile_bridge_name(),
+               vsoc::GetInstance(), 1);
+  ConfigureHWRNG(devices, config->entropy_source());
 
   xmlChar* tgt;
   int tgt_len;
 
   xmlDocDumpFormatMemoryEnc(xml.get(), &tgt, &tgt_len, "utf-8", true);
-  std::string out(reinterpret_cast<const char*>(tgt), tgt_len);
+  std::string out((const char*)(tgt), tgt_len);
   xmlFree(tgt);
   return out;
 }
 
-}  // namespace config
+bool LibvirtManager::Start() const {
+  std::string start_command = GetLibvirtCommand();
+  start_command += " create /dev/fd/0";
+
+  std::string xml = BuildXmlConfig();
+  if (FLAGS_log_xml) {
+    LOG(INFO) << "Using XML:\n" << xml;
+  }
+
+  FILE* launch = popen(start_command.c_str(), "w");
+  if (!launch) {
+    LOG(FATAL) << "Unable to execute " << start_command;
+    return false;
+  }
+  int rval = fputs(xml.c_str(), launch);
+  if (rval == EOF) {
+    LOG(FATAL) << "Launch command exited while accepting XML";
+    return false;
+  }
+  int exit_code = pclose(launch);
+  if (exit_code != 0) {
+    LOG(FATAL) << "Launch command exited with status " << exit_code;
+    return false;
+  }
+  return true;
+}
+
+bool LibvirtManager::Stop() const {
+  auto config = vsoc::CuttlefishConfig::Get();
+  auto stop_command = GetLibvirtCommand();
+  stop_command += " destroy " + config->instance_name();
+  return std::system(stop_command.c_str()) == 0;
+}
+
+}  // namespace vm_manager
diff --git a/host/libs/config/host_config.h b/host/libs/vm_manager/libvirt_manager.h
similarity index 62%
rename from host/libs/config/host_config.h
rename to host/libs/vm_manager/libvirt_manager.h
index 15d2059..dbe7dcf 100644
--- a/host/libs/config/host_config.h
+++ b/host/libs/vm_manager/libvirt_manager.h
@@ -1,5 +1,3 @@
-#pragma once
-
 /*
  * Copyright (C) 2017 The Android Open Source Project
  *
@@ -15,17 +13,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/* Host-specific values associated with RegionControl. */
+#pragma once
 
 #include <string>
 
-namespace vsoc {
-int GetDefaultInstance();
-std::string GetPerInstanceDefault(const char* prefix);
-int GetPerInstanceDefault(int base);
-std::string GetDefaultPerInstanceDir();
-std::string GetDefaultPerInstancePath(const std::string& basename);
-std::string GetDefaultShmClientSocketPath();
-std::string GetDomain();
-}  // namespace vsoc
+#include "host/libs/config/cuttlefish_config.h"
+
+namespace vm_manager {
+
+class LibvirtManager {
+ public:
+  LibvirtManager() = default;
+  ~LibvirtManager() = default;
+
+  bool Start() const;
+  bool Stop() const;
+
+ protected:
+  std::string BuildXmlConfig() const;
+};
+
+}  // namespace vm_manager
diff --git a/host/vsoc/lib/host_region_e2e_test.cpp b/host/vsoc/lib/host_region_e2e_test.cpp
index cab1bc7..1366838 100644
--- a/host/vsoc/lib/host_region_e2e_test.cpp
+++ b/host/vsoc/lib/host_region_e2e_test.cpp
@@ -20,7 +20,7 @@
 
 #include <gtest/gtest.h>
 #include "common/vsoc/lib/e2e_test_region_view.h"
-#include "host/libs/config/host_config.h"
+#include "host/libs/config/cuttlefish_config.h"
 
 // Here is a summary of the two regions interrupt and write test:
 // 1. Write our strings to the first region