diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-06-06 07:28:00 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-06-06 07:28:00 +0000 |
commit | cd7219e5899e47133cee5388b10969c1dc547fe4 (patch) | |
tree | 11425c153feb0687eec876d751641e4b536ee6e6 | |
parent | 44ce37c41307a8bdbb9583bf2703b2d74d708cff (diff) | |
parent | 2b2979e93eb8b5a46e72142c2a90d9b302c27600 (diff) | |
download | cuttlefish_common-pie-cts-release.tar.gz |
Snap for 4824048 from 2b2979e93eb8b5a46e72142c2a90d9b302c27600 to pi-releaseandroid-wear-9.0.0_r9android-wear-9.0.0_r8android-wear-9.0.0_r7android-wear-9.0.0_r6android-wear-9.0.0_r5android-wear-9.0.0_r4android-wear-9.0.0_r34android-wear-9.0.0_r33android-wear-9.0.0_r32android-wear-9.0.0_r31android-wear-9.0.0_r30android-wear-9.0.0_r3android-wear-9.0.0_r29android-wear-9.0.0_r28android-wear-9.0.0_r27android-wear-9.0.0_r26android-wear-9.0.0_r25android-wear-9.0.0_r24android-wear-9.0.0_r23android-wear-9.0.0_r22android-wear-9.0.0_r21android-wear-9.0.0_r20android-wear-9.0.0_r2android-wear-9.0.0_r19android-wear-9.0.0_r18android-wear-9.0.0_r17android-wear-9.0.0_r16android-wear-9.0.0_r15android-wear-9.0.0_r14android-wear-9.0.0_r13android-wear-9.0.0_r12android-wear-9.0.0_r11android-wear-9.0.0_r10android-wear-9.0.0_r1android-vts-9.0_r9android-vts-9.0_r8android-vts-9.0_r7android-vts-9.0_r6android-vts-9.0_r5android-vts-9.0_r4android-vts-9.0_r19android-vts-9.0_r18android-vts-9.0_r17android-vts-9.0_r16android-vts-9.0_r15android-vts-9.0_r14android-vts-9.0_r13android-vts-9.0_r12android-vts-9.0_r11android-vts-9.0_r10android-security-9.0.0_r76android-security-9.0.0_r75android-security-9.0.0_r74android-security-9.0.0_r73android-security-9.0.0_r72android-security-9.0.0_r71android-security-9.0.0_r70android-security-9.0.0_r69android-security-9.0.0_r68android-security-9.0.0_r67android-security-9.0.0_r66android-security-9.0.0_r65android-security-9.0.0_r64android-security-9.0.0_r63android-security-9.0.0_r62android-cts-9.0_r9android-cts-9.0_r8android-cts-9.0_r7android-cts-9.0_r6android-cts-9.0_r5android-cts-9.0_r4android-cts-9.0_r3android-cts-9.0_r20android-cts-9.0_r2android-cts-9.0_r19android-cts-9.0_r18android-cts-9.0_r17android-cts-9.0_r16android-cts-9.0_r15android-cts-9.0_r14android-cts-9.0_r13android-cts-9.0_r12android-cts-9.0_r11android-cts-9.0_r10android-cts-9.0_r1android-9.0.0_r9android-9.0.0_r8android-9.0.0_r7android-9.0.0_r61android-9.0.0_r60android-9.0.0_r6android-9.0.0_r59android-9.0.0_r58android-9.0.0_r57android-9.0.0_r56android-9.0.0_r55android-9.0.0_r54android-9.0.0_r53android-9.0.0_r52android-9.0.0_r51android-9.0.0_r50android-9.0.0_r5android-9.0.0_r49android-9.0.0_r48android-9.0.0_r3android-9.0.0_r2android-9.0.0_r18android-9.0.0_r17android-9.0.0_r10android-9.0.0_r1security-pi-releasepie-vts-releasepie-security-releasepie-s2-releasepie-release-2pie-releasepie-r2-s2-releasepie-r2-s1-releasepie-r2-releasepie-cts-release
Change-Id: I4e0f32ceec3bcf60846413ab9ab3c336db6f4562
31 files changed, 1164 insertions, 862 deletions
@@ -155,6 +155,7 @@ cc_binary_host { ], static_libs: [ "libcuttlefish_host_config", + "libjsoncpp", "libgflags", ], shared_libs: [ @@ -206,6 +207,7 @@ cc_binary_host { ], 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 c496ef09..5393d4af 100644 --- a/common/commands/wifi_relay/Android.bp +++ b/common/commands/wifi_relay/Android.bp @@ -39,6 +39,7 @@ cc_binary { 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 2b217650..4d862b0d 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 4def7bfd..3eba53ff 100644 --- a/common/frontend/socket_forward_proxy/Android.bp +++ b/common/frontend/socket_forward_proxy/Android.bp @@ -36,6 +36,7 @@ cc_binary { 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 a04c6012..e361059c 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 b192c67e..cc02baac 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 e9789b86..650ccb9a 100644 --- a/host/commands/launch/Android.bp +++ b/host/commands/launch/Android.bp @@ -35,6 +35,7 @@ cc_binary_host { ], 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 c3b21517..9605049b 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 @@ std::string StringFromEnv(const char* varname, std::string defval) { } return valstr; } -} // namespace -#define VIRSH_OPTIONS_PLACEHOLDER "<virsh_options>" +std::string DefaultHostArtifactsPath(const char* file_name) { + return (StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) + "/") + + file_name; +} + +} // namespace 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_int32(blank_data_image_mb, 0, 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 @@ DEFINE_bool(disable_dac_security, false, "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 @@ DEFINE_string(mempath, g_default_mempath.c_str(), 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 @@ DEFINE_bool(deprecated_boot_completed, false, "Log boot completed message to" " 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 @@ const std::string kDataPolicyAlwaysCreate = "always_create"; 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 @@ class VirtualUSBManager { // 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 @@ void subprocess(const char* const* command, 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 @@ void subprocess(const char* const* command, } } +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 @@ void RemoveFile(const std::string& file) { 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::string GetHostPortArg() { 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 @@ void LaunchSocketForwardProxyIfEnabled() { 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 @@ void LaunchVNCServerIfEnabled() { 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 LaunchVNCServerIfEnabled() { 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 @@ int main(int argc, char** argv) { 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; + } + + // 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; +} - std::string entropy_source = "/dev/urandom"; +bool SetUpGlobalConfiguration() { + if (!ResolveInstanceFiles()) { + return false; + } auto& memory_layout = *vsoc::VSoCMemoryLayout::Get(); + 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; + } - 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; - } - - 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 e122e291..31f5107f 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 @@ class NetConfig { 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 @@ class NetConfig { } 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; - } - 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); + 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) << "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 @@ void InitializeRilRegion() { 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 4214482b..6e19ca11 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 7f82c6a0..9d87c648 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 d380e239..b7bfe928 100644 --- a/host/commands/record_audio/Android.bp +++ b/host/commands/record_audio/Android.bp @@ -27,6 +27,7 @@ cc_binary_host { ], 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 26558386..18466f3e 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 429fd6c4..3607e8ed 100644 --- a/host/commands/stop_cvd/Android.bp +++ b/host/commands/stop_cvd/Android.bp @@ -23,10 +23,16 @@ cc_binary_host { ], 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 2c2baf7c..08648b16 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 @@ int main(int argc, char** argv) { ::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 cf8a2c41..6508945a 100644 --- a/host/frontend/vnc_server/Android.bp +++ b/host/frontend/vnc_server/Android.bp @@ -37,6 +37,7 @@ cc_binary_host { ], 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 26162025..eab7011d 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 7141bd16..c8b7f036 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 558aa57f..3eac9f35 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 12fde972..540b9b41 100644 --- a/host/libs/Android.bp +++ b/host/libs/Android.bp @@ -20,4 +20,5 @@ subdirs = [ "ivserver", "vadb", "usbip", + "vm_manager", ] diff --git a/host/libs/config/Android.bp b/host/libs/config/Android.bp index df9f99b7..9b70a07d 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 @@ cc_library_host_static { 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 00000000..bd70a958 --- /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 00000000..50e8616a --- /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 ede4870b..00000000 --- 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 3c8e55b3..00000000 --- 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 ff7432fb..00000000 --- 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 df39bb6a..00000000 --- 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 00000000..1c23f0a8 --- /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 index a812966d..6c6f4a1c 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 @@ void ConfigureVMFeatures(xmlNode* root, // 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 @@ void ConfigureOperatingSystem(xmlNode* root, const std::string& kernel, 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 @@ void ConfigureDisk(xmlNode* devices, const std::string& name, // 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 @@ void ConfigureHWRNG(xmlNode* devices, const std::string& entsrc) { 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 @@ std::string GuestConfig::Build() const { 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"}); - - if (disable_app_armor_security_) { + 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 (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 @@ std::string GuestConfig::Build() const { 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 index 15d20591..dbe7dcfc 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 cab1bc7e..13668381 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 |