@@ -68,6 +68,7 @@ constexpr auto metrics_opt_in_file = "multipassd-send-metrics.yaml";
68
68
constexpr auto reboot_cmd = " sudo reboot" ;
69
69
constexpr auto up_timeout = 2min; // This may be tweaked as appropriate and used in places that wait for ssh to be up
70
70
constexpr auto stop_ssh_cmd = " sudo systemctl stop ssh" ;
71
+ constexpr auto max_install_sshfs_retries = 3 ;
71
72
72
73
mp::Query query_from (const mp::LaunchRequest* request, const std::string& name)
73
74
{
@@ -144,10 +145,6 @@ void prepare_user_data(YAML::Node& user_data_config, YAML::Node& vendor_config)
144
145
if (users.IsSequence ())
145
146
users.push_back (" default" );
146
147
147
- auto packages = user_data_config[" packages" ];
148
- if (packages.IsSequence ())
149
- packages.push_back (" sshfs" );
150
-
151
148
auto keys = user_data_config[" ssh_authorized_keys" ];
152
149
if (keys.IsSequence ())
153
150
keys.push_back (vendor_config[" ssh_authorized_keys" ][0 ]);
@@ -304,11 +301,8 @@ auto validate_create_arguments(const mp::LaunchRequest* request)
304
301
305
302
auto grpc_status_for_mount_error (const std::string& instance_name)
306
303
{
307
- mp::MountError mount_error;
308
- mount_error.set_error_code (mp::MountError::SSHFS_MISSING);
309
- mount_error.set_instance_name (instance_name);
310
-
311
- return grpc::Status (grpc::StatusCode::FAILED_PRECONDITION, " Mount failed" , mount_error.SerializeAsString ());
304
+ return grpc::Status (grpc::StatusCode::FAILED_PRECONDITION,
305
+ fmt::format (" Error enabling mount support in '{}'" , instance_name));
312
306
}
313
307
314
308
auto grpc_status_for (fmt::memory_buffer& errors)
@@ -757,10 +751,6 @@ try // clang-format on
757
751
vm->start ();
758
752
vm->wait_until_ssh_up (std::chrono::minutes (5 ));
759
753
760
- reply.set_create_message (" Waiting for initialization to complete" );
761
- server->Write (reply);
762
- vm->wait_for_cloud_init (std::chrono::minutes (5 ));
763
-
764
754
reply.set_vm_instance_name (name);
765
755
server->Write (reply);
766
756
@@ -1265,7 +1255,18 @@ try // clang-format on
1265
1255
}
1266
1256
catch (const mp::SSHFSMissingError&)
1267
1257
{
1268
- return grpc_status_for_mount_error (name);
1258
+ try
1259
+ {
1260
+ MountReply mount_reply;
1261
+ mount_reply.set_mount_message (" Enabling support for mounting" );
1262
+ server->Write (mount_reply);
1263
+ install_sshfs (vm, name);
1264
+ start_mount (vm, name, request->source_path (), target_path, gid_map, uid_map);
1265
+ }
1266
+ catch (const mp::SSHFSMissingError&)
1267
+ {
1268
+ return grpc_status_for_mount_error (name);
1269
+ }
1269
1270
}
1270
1271
catch (const std::exception& e)
1271
1272
{
@@ -1474,7 +1475,18 @@ try // clang-format on
1474
1475
}
1475
1476
catch (const mp::SSHFSMissingError&)
1476
1477
{
1477
- return grpc_status_for_mount_error (name);
1478
+ try
1479
+ {
1480
+ StartReply start_reply;
1481
+ start_reply.set_start_message (" Enabling support for mounting" );
1482
+ server->Write (start_reply);
1483
+ install_sshfs (vm, name);
1484
+ start_mount (vm, name, source_path, target_path, gid_map, uid_map);
1485
+ }
1486
+ catch (const mp::SSHFSMissingError&)
1487
+ {
1488
+ return grpc_status_for_mount_error (name);
1489
+ }
1478
1490
}
1479
1491
catch (const std::exception& e)
1480
1492
{
@@ -2038,3 +2050,38 @@ grpc::Status mp::Daemon::cmd_vms(const std::vector<std::string>& tgts, std::func
2038
2050
2039
2051
return grpc::Status::OK;
2040
2052
}
2053
+
2054
+ void mp::Daemon::install_sshfs (const VirtualMachine::UPtr& vm, const std::string& name)
2055
+ {
2056
+ auto & key_provider = *config->ssh_key_provider ;
2057
+
2058
+ SSHSession session{vm->ssh_hostname (), vm->ssh_port (), vm->ssh_username (), key_provider};
2059
+
2060
+ mpl::log (mpl::Level::info, category, fmt::format (" Installing sshfs in \' {}\' " , name));
2061
+
2062
+ int retries{0 };
2063
+ while (++retries <= max_install_sshfs_retries)
2064
+ {
2065
+ try
2066
+ {
2067
+ auto proc = session.exec (" sudo apt update && sudo apt install -y sshfs" );
2068
+ if (proc.exit_code (std::chrono::minutes (5 )) != 0 )
2069
+ {
2070
+ auto error_msg = proc.read_std_error ();
2071
+ mpl::log (mpl::Level::warning, category,
2072
+ fmt::format (" Failed to install 'sshfs', error message: '{}'" , mp::utils::trim_end (error_msg)));
2073
+ }
2074
+ else
2075
+ {
2076
+ break ;
2077
+ }
2078
+ }
2079
+ catch (const mp::ExitlessSSHProcessException&)
2080
+ {
2081
+ mpl::log (mpl::Level::info, category, fmt::format (" Timeout while installing 'sshfs' in '{}'" , name));
2082
+ }
2083
+ }
2084
+
2085
+ if (retries > max_install_sshfs_retries)
2086
+ throw mp::SSHFSMissingError ();
2087
+ }
0 commit comments