VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/CloudGateway.cpp

Last change on this file was 98261, checked in by vboxsync, 16 months ago

Main/CloudGateway.cpp: rc -> vrc/hrc bugref:10223

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
RevLine 
[85359]1/* $Id: CloudGateway.cpp 98261 2023-01-24 01:30:57Z vboxsync $ */
2/** @file
3 * Implementation of local and cloud gateway management.
4 */
5
6/*
[98103]7 * Copyright (C) 2019-2023 Oracle and/or its affiliates.
[85359]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[85359]26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_CONSOLE
29
30/* Make sure all the stdint.h macros are included - must come first! */
31#ifndef __STDC_LIMIT_MACROS
32# define __STDC_LIMIT_MACROS
33#endif
34#ifndef __STDC_CONSTANT_MACROS
35# define __STDC_CONSTANT_MACROS
36#endif
37
38#include "LoggingNew.h"
39#include "ApplianceImpl.h"
40#include "CloudNetworkImpl.h"
41#include "CloudGateway.h"
42
43#include <iprt/http.h>
44#include <iprt/inifile.h>
45#include <iprt/net.h>
46#include <iprt/path.h>
47#include <iprt/vfs.h>
48#include <iprt/uri.h>
[93312]49#ifdef DEBUG
50#include <iprt/file.h>
51#include <VBox/com/utils.h>
52#endif
[85359]53
[93312]54#ifdef VBOX_WITH_LIBSSH
55/* Prevent inclusion of Winsock2.h */
56#define _WINSOCK2API_
57#include <libssh/libssh.h>
58#endif /* VBOX_WITH_LIBSSH */
59
60
[85359]61static HRESULT setMacAddress(const Utf8Str& str, RTMAC& mac)
62{
[98261]63 int vrc = RTNetStrToMacAddr(str.c_str(), &mac);
64 if (RT_FAILURE(vrc))
[85359]65 {
66 LogRel(("CLOUD-NET: Invalid MAC address '%s'\n", str.c_str()));
67 return E_INVALIDARG;
68 }
69 return S_OK;
70}
71
[93312]72
[85359]73HRESULT GatewayInfo::setCloudMacAddress(const Utf8Str& mac)
74{
75 return setMacAddress(mac, mCloudMacAddress);
76}
77
[93312]78
[85359]79HRESULT GatewayInfo::setLocalMacAddress(const Utf8Str& mac)
80{
81 return setMacAddress(mac, mLocalMacAddress);
82}
83
84
85class CloudError
86{
87public:
88 CloudError(HRESULT hrc, const Utf8Str& strText) : mHrc(hrc), mText(strText) {};
89 HRESULT getRc() { return mHrc; };
90 Utf8Str getText() { return mText; };
91
92private:
93 HRESULT mHrc;
94 Utf8Str mText;
95};
96
[93312]97
[85359]98static void handleErrors(HRESULT hrc, const char *pszFormat, ...)
99{
100 if (FAILED(hrc))
101 {
102 va_list va;
103 va_start(va, pszFormat);
104 Utf8Str strError(pszFormat, va);
105 va_end(va);
[98261]106 LogRel(("CLOUD-NET: %s (hrc=%x)\n", strError.c_str(), hrc));
[85359]107 throw CloudError(hrc, strError);
108 }
109
110}
111
[93312]112
[85359]113class CloudClient
114{
115public:
116 CloudClient(ComPtr<IVirtualBox> virtualBox, const Bstr& strProvider, const Bstr& strProfile);
117 ~CloudClient() {};
118
[93312]119 void startCloudGateway(const ComPtr<ICloudNetwork> &network, GatewayInfo& gateway);
120 void stopCloudGateway(const GatewayInfo& gateway);
[85359]121
122private:
123 ComPtr<ICloudProviderManager> mManager;
124 ComPtr<ICloudProvider> mProvider;
125 ComPtr<ICloudProfile> mProfile;
126 ComPtr<ICloudClient> mClient;
127};
128
[93312]129
[85359]130CloudClient::CloudClient(ComPtr<IVirtualBox> virtualBox, const Bstr& strProvider, const Bstr& strProfile)
131{
132 HRESULT hrc = virtualBox->COMGETTER(CloudProviderManager)(mManager.asOutParam());
133 handleErrors(hrc, "Failed to obtain cloud provider manager object");
134 hrc = mManager->GetProviderByShortName(strProvider.raw(), mProvider.asOutParam());
135 handleErrors(hrc, "Failed to obtain cloud provider '%ls'", strProvider.raw());
136 hrc = mProvider->GetProfileByName(strProfile.raw(), mProfile.asOutParam());
137 handleErrors(hrc, "Failed to obtain cloud profile '%ls'", strProfile.raw());
138 hrc = mProfile->CreateCloudClient(mClient.asOutParam());
139 handleErrors(hrc, "Failed to create cloud client");
140}
141
[93312]142
143void CloudClient::startCloudGateway(const ComPtr<ICloudNetwork> &network, GatewayInfo& gateway)
[85359]144{
145 ComPtr<IProgress> progress;
146 ComPtr<ICloudNetworkGatewayInfo> gatewayInfo;
[93312]147 HRESULT hrc = mClient->StartCloudNetworkGateway(network, Bstr(gateway.mPublicSshKey).raw(),
[85359]148 gatewayInfo.asOutParam(), progress.asOutParam());
149 handleErrors(hrc, "Failed to launch compute instance");
150 hrc = progress->WaitForCompletion(-1);
151 handleErrors(hrc, "Failed to launch compute instance (wait)");
152
153 Bstr instanceId;
154 hrc = gatewayInfo->COMGETTER(InstanceId)(instanceId.asOutParam());
155 handleErrors(hrc, "Failed to get launched compute instance id");
[93312]156 gateway.mGatewayInstanceId = instanceId;
[85359]157
158 Bstr publicIP;
159 hrc = gatewayInfo->COMGETTER(PublicIP)(publicIP.asOutParam());
160 handleErrors(hrc, "Failed to get cloud gateway public IP address");
[93312]161 gateway.mCloudPublicIp = publicIP;
[85359]162
163 Bstr secondaryPublicIP;
164 hrc = gatewayInfo->COMGETTER(SecondaryPublicIP)(secondaryPublicIP.asOutParam());
165 handleErrors(hrc, "Failed to get cloud gateway secondary public IP address");
[93312]166 gateway.mCloudSecondaryPublicIp = secondaryPublicIP;
[85359]167
168 Bstr macAddress;
169 hrc = gatewayInfo->COMGETTER(MacAddress)(macAddress.asOutParam());
170 handleErrors(hrc, "Failed to get cloud gateway public IP address");
[93312]171 gateway.setCloudMacAddress(macAddress);
[85359]172}
173
[93312]174
175void CloudClient::stopCloudGateway(const GatewayInfo& gateway)
[85359]176{
177 ComPtr<IProgress> progress;
[93312]178 HRESULT hrc = mClient->TerminateInstance(Bstr(gateway.mGatewayInstanceId).raw(), progress.asOutParam());
[85359]179 handleErrors(hrc, "Failed to terminate compute instance");
180#if 0
181 /* Someday we may want to wait until the cloud gateway has terminated. */
182 hrc = progress->WaitForCompletion(-1);
183 handleErrors(hrc, "Failed to terminate compute instance (wait)");
184#endif
185}
186
187
[93312]188HRESULT startCloudGateway(ComPtr<IVirtualBox> virtualBox, ComPtr<ICloudNetwork> network, GatewayInfo& gateway)
[85359]189{
190 HRESULT hrc = S_OK;
191
192 try {
[93312]193 hrc = network->COMGETTER(Provider)(gateway.mCloudProvider.asOutParam());
194 hrc = network->COMGETTER(Profile)(gateway.mCloudProfile.asOutParam());
195 CloudClient client(virtualBox, gateway.mCloudProvider, gateway.mCloudProfile);
196 client.startCloudGateway(network, gateway);
[85359]197 }
198 catch (CloudError e)
199 {
200 hrc = e.getRc();
201 }
202
203 return hrc;
204}
205
206
[93312]207HRESULT stopCloudGateway(ComPtr<IVirtualBox> virtualBox, GatewayInfo& gateway)
[85359]208{
[93312]209 if (gateway.mGatewayInstanceId.isEmpty())
210 return S_OK;
[85359]211
[93312]212 LogRel(("CLOUD-NET: Terminating cloud gateway instance '%s'...\n", gateway.mGatewayInstanceId.c_str()));
[85359]213
[93312]214 HRESULT hrc = S_OK;
215 try {
216 CloudClient client(virtualBox, gateway.mCloudProvider, gateway.mCloudProfile);
217 client.stopCloudGateway(gateway);
218#if 0
219# ifdef DEBUG
220 char szKeyPath[RTPATH_MAX];
[85359]221
[98261]222 int vrc = GetVBoxUserHomeDirectory(szKeyPath, sizeof(szKeyPath), false /* fCreateDir */);
223 if (RT_SUCCESS(vrc))
[85359]224 {
[98261]225 vrc = RTPathAppend(szKeyPath, sizeof(szKeyPath), "gateway-key.pem");
226 AssertRCReturn(vrc, vrc);
227 vrc = RTFileDelete(szKeyPath);
228 if (RT_FAILURE(vrc))
229 LogRel(("WARNING! Failed to delete private key %s with vrc=%d\n", szKeyPath, vrc));
[85359]230 }
[93312]231 else
[98261]232 LogRel(("WARNING! Failed to get VirtualBox user home directory with '%Rrc'\n", vrc));
[93312]233# endif /* DEBUG */
234#endif
235 }
236 catch (CloudError e)
237 {
238 hrc = e.getRc();
[98261]239 LogRel(("CLOUD-NET: Failed to terminate cloud gateway instance (hrc=%x).\n", hrc));
[93312]240 }
241 gateway.mGatewayInstanceId.setNull();
[85359]242 return hrc;
243}
244
245
[93312]246HRESULT generateKeys(GatewayInfo& gateway)
[85359]247{
[93312]248#ifndef VBOX_WITH_LIBSSH
249 RT_NOREF(gateway);
250 return E_NOTIMPL;
251#else /* VBOX_WITH_LIBSSH */
252 ssh_key single_use_key;
[98261]253 int iRcSsh = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &single_use_key);
254 if (iRcSsh != SSH_OK)
[93312]255 {
[98261]256 LogRel(("Failed to generate a key pair. iRcSsh = %d\n", iRcSsh));
[93312]257 return E_FAIL;
258 }
[85359]259
[93312]260 char *pstrKey = NULL;
[98261]261 iRcSsh = ssh_pki_export_privkey_base64(single_use_key, NULL, NULL, NULL, &pstrKey);
262 if (iRcSsh != SSH_OK)
[85359]263 {
[98261]264 LogRel(("Failed to export private key. iRcSsh = %d\n", iRcSsh));
[93312]265 return E_FAIL;
[85359]266 }
[93312]267 gateway.mPrivateSshKey = pstrKey;
268#if 0
269# ifdef DEBUG
270 char szConfigPath[RTPATH_MAX];
[85359]271
[98261]272 vrc = GetVBoxUserHomeDirectory(szConfigPath, sizeof(szConfigPath), false /* fCreateDir */);
273 if (RT_SUCCESS(vrc))
[85359]274 {
[98261]275 vrc = RTPathAppend(szConfigPath, sizeof(szConfigPath), "gateway-key.pem");
276 AssertRCReturn(vrc, E_FAIL);
277 iRcSsh = ssh_pki_export_privkey_file(single_use_key, NULL, NULL, NULL, szConfigPath);
278 if (iRcSsh != SSH_OK)
[85359]279 {
[98261]280 LogRel(("Failed to export private key to %s with iRcSsh=%d\n", szConfigPath, iRcSsh));
[93312]281 return E_FAIL;
[85359]282 }
[93312]283# ifndef RT_OS_WINDOWS
[98261]284 vrc = RTPathSetMode(szConfigPath, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR); /* Satisfy ssh client */
285 AssertRCReturn(vrc, E_FAIL);
[93312]286# endif
[85359]287 }
[93312]288 else
[85359]289 {
[98261]290 LogRel(("Failed to get VirtualBox user home directory with '%Rrc'\n", vrc));
[93312]291 return E_FAIL;
[85359]292 }
[93312]293# endif /* DEBUG */
[85359]294#endif
[93312]295 ssh_string_free_char(pstrKey);
296 pstrKey = NULL;
[98261]297 iRcSsh = ssh_pki_export_pubkey_base64(single_use_key, &pstrKey);
298 if (iRcSsh != SSH_OK)
[85359]299 {
[98261]300 LogRel(("Failed to export public key. iRcSsh = %d\n", iRcSsh));
[93312]301 return E_FAIL;
[85359]302 }
[93312]303 gateway.mPublicSshKey = Utf8StrFmt("ssh-rsa %s single-use-key", pstrKey);
304 ssh_string_free_char(pstrKey);
305 ssh_key_free(single_use_key);
[85359]306
[93312]307 return S_OK;
308#endif /* VBOX_WITH_LIBSSH */
[85359]309}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use