Changeset 78602 in vbox for trunk/src/VBox
- Timestamp:
- May 20, 2019 4:26:10 PM (6 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/ovfreader.h
r76562 r78602 664 664 { 665 665 public: 666 OVFReader(); 666 667 OVFReader(const void *pvBuf, size_t cbSize, const RTCString &path); 667 668 OVFReader(const RTCString &path); -
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r78430 r78602 51 51 #include "ApplianceImplPrivate.h" 52 52 #include "CertificateImpl.h" 53 #include "ovfreader.h" 53 54 54 55 #include <VBox/param.h> … … 1195 1196 { 1196 1197 Utf8Str strBasename(pTask->locInfo.strPath); 1197 RTCList<RTCString, RTCString *> parts = strBasename.split("/" );1198 RTCList<RTCString, RTCString *> parts = strBasename.split("/" ); 1198 1199 if (parts.size() != 2)//profile + instance id 1199 1200 { … … 1250 1251 Bstr(profileName).raw(), 1251 1252 Bstr(profileName).raw()); 1252 // set name 1253 Utf8Str strSetting = "cloud VM (";1254 strSetting.append(parts.at(1)).append(")");1253 1254 Utf8StrFmt strSetting("VM with id %s imported from the cloud provider %s", 1255 parts.at(1).c_str(), strProviderName.c_str()); 1255 1256 // set description 1256 strSetting = "VM with id ";1257 strSetting.append(parts.at(1)).append(" imported from the cloud provider ").append(strProviderName);1258 1259 // description1260 1257 instanceDescription->AddDescription(VirtualSystemDescriptionType_Description, 1261 1258 Bstr(strSetting).raw(), … … 1285 1282 LogFlowFunc(("Appliance %p\n", this)); 1286 1283 1284 int vrc = VINF_SUCCESS; 1285 HRESULT hrc = S_OK; 1286 Utf8Str strLastActualErrorDesc("No errors"); 1287 1287 1288 /* Change the appliance state so we can safely leave the lock while doing 1288 1289 * time-consuming operations; also the below method calls do all kinds of 1289 1290 * locking which conflicts with the appliance object lock. */ 1290 1291 AutoWriteLock writeLock(this COMMA_LOCKVAL_SRC_POS); 1292 1291 1293 /* Check if the appliance is currently busy. */ 1292 1294 if (!i_isApplianceIdle()) … … 1294 1296 /* Set the internal state to importing. */ 1295 1297 m->state = Data::ApplianceImporting; 1296 1297 HRESULT hrc = S_OK; 1298 writeLock.release(); 1298 1299 1299 1300 /* Clear the list of imported machines, if any */ 1300 1301 m->llGuidsMachinesCreated.clear(); 1301 1302 /*1303 * Actual code for the cloud import1304 *1305 */1306 1302 1307 1303 ComPtr<ICloudProviderManager> cpm; … … 1318 1314 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud provider object wasn't found", __FUNCTION__)); 1319 1315 1316 /* Get the actual VSD, only one VSD object can be there for now so just call the function front() */ 1320 1317 ComPtr<IVirtualSystemDescription> vsd = m->virtualSystemDescriptions.front(); 1321 1318 1319 Utf8Str vsdData; 1322 1320 com::SafeArray<VirtualSystemDescriptionType_T> retTypes; 1323 1321 com::SafeArray<BSTR> aRefs; … … 1326 1324 com::SafeArray<BSTR> aExtraConfigValues; 1327 1325 1328 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_CloudProfileName, 1329 ComSafeArrayAsOutParam(retTypes), 1330 ComSafeArrayAsOutParam(aRefs), 1331 ComSafeArrayAsOutParam(aOvfValues), 1332 ComSafeArrayAsOutParam(aVBoxValues), 1333 ComSafeArrayAsOutParam(aExtraConfigValues)); 1334 if (FAILED(hrc)) 1335 return hrc; 1326 /* 1327 * local #define for better reading the code 1328 * uses only the previously locally declared variable names 1329 * set hrc as the result of operation 1330 */ 1331 #define GET_VSD_DESCRIPTION_BY_TYPE(aParamType) \ 1332 retTypes.setNull(); \ 1333 aRefs.setNull(); \ 1334 aOvfValues.setNull(); \ 1335 aVBoxValues.setNull(); \ 1336 aExtraConfigValues.setNull(); \ 1337 vsd->GetDescriptionByType(aParamType, \ 1338 ComSafeArrayAsOutParam(retTypes), \ 1339 ComSafeArrayAsOutParam(aRefs), \ 1340 ComSafeArrayAsOutParam(aOvfValues), \ 1341 ComSafeArrayAsOutParam(aVBoxValues), \ 1342 ComSafeArrayAsOutParam(aExtraConfigValues)); \ 1343 1344 1345 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_CloudProfileName) 1346 if (aVBoxValues.size() == 0) 1347 return setErrorVrc(VERR_NOT_FOUND, tr("%s: Cloud user profile name wasn't found", __FUNCTION__)); 1336 1348 1337 1349 Utf8Str profileName(aVBoxValues[0]); 1338 1350 if (profileName.isEmpty()) 1339 return setErrorVrc(V BOX_E_OBJECT_NOT_FOUND, tr("%s: Cloud user profile name wasn't found", __FUNCTION__));1351 return setErrorVrc(VERR_INVALID_STATE, tr("%s: Cloud user profile name is empty", __FUNCTION__)); 1340 1352 1341 1353 hrc = cloudProvider->GetProfileByName(aVBoxValues[0], cloudProfile.asOutParam()); … … 1348 1360 return setErrorVrc(VERR_COM_OBJECT_NOT_FOUND, tr("%s: Cloud client object wasn't found", __FUNCTION__)); 1349 1361 1362 ComPtr<IProgress> pProgress; 1363 hrc = pTask->pProgress.queryInterfaceTo(pProgress.asOutParam()); 1364 if (FAILED(hrc)) 1365 return hrc; 1366 1367 Utf8Str strOsType; 1368 ComPtr<IGuestOSType> pGuestOSType; 1369 { 1370 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_OS)//aVBoxValues is set in this #define 1371 if (aVBoxValues.size() != 0) 1372 strOsType = aVBoxValues[0]; 1373 else 1374 return setErrorVrc(VERR_NOT_FOUND, "%s: OS type wasn't found", __FUNCTION__); 1375 LogRel(("%s: OS type is %s\n", __FUNCTION__, strOsType.c_str())); 1376 1377 /* Check the OS type and get the structure with the some default settings for this OS type */ 1378 uint32_t const idxOSType = Global::getOSTypeIndexFromId(strOsType.c_str()); 1379 VBOXOSTYPE guestOsType = idxOSType < Global::cOSTypes ? Global::sOSTypes[idxOSType].osType : VBOXOSTYPE_Unknown; 1380 if (guestOsType == VBOXOSTYPE_Unknown) 1381 return setErrorVrc(VERR_NOT_SUPPORTED, "%s: OS type is unknown", __FUNCTION__); 1382 1383 /* We can get some default settings from GuestOSType when it's needed */ 1384 mVirtualBox->GetGuestOSType(Bstr(strOsType).raw(), pGuestOSType.asOutParam()); 1385 } 1386 1387 /* Should be defined here because it's used later, at least when ComposeMachineFilename() is called */ 1388 Utf8Str strVMName("VM_exported_from_cloud"); 1389 1350 1390 if (m->virtualSystemDescriptions.size() == 1) 1351 1391 { … … 1353 1393 { 1354 1394 ComPtr<IVirtualBox> VBox(mVirtualBox); 1355 retTypes.setNull(); 1356 aRefs.setNull(); 1357 aOvfValues.setNull(); 1358 aVBoxValues.setNull(); 1359 aExtraConfigValues.setNull(); 1360 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_CloudInstanceId, 1361 ComSafeArrayAsOutParam(retTypes), 1362 ComSafeArrayAsOutParam(aRefs), 1363 ComSafeArrayAsOutParam(aOvfValues), 1364 ComSafeArrayAsOutParam(aVBoxValues), 1365 ComSafeArrayAsOutParam(aExtraConfigValues)); 1366 if (FAILED(hrc)) 1395 1396 { 1397 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_Name)//aVBoxValues is set in this #define 1398 if (aVBoxValues.size() != 0)//paranoia but anyway... 1399 strVMName = aVBoxValues[0]; 1400 LogRel(("%s: VM name is %s\n", __FUNCTION__, strVMName.c_str())); 1401 } 1402 1403 // i_searchUniqueVMName(strVMName);//internally calls setError() in the case of absent the registered VM with such name 1404 1405 ComPtr<IMachine> machine; 1406 hrc = mVirtualBox->FindMachine(Bstr(strVMName.c_str()).raw(), machine.asOutParam()); 1407 if (SUCCEEDED(hrc)) 1408 { 1409 //what to do? create a new name from the old one with some suffix? 1410 com::Guid newId; 1411 newId.create(); 1412 strVMName.append("__").append(newId.toString()); 1413 vsd->RemoveDescriptionByType(VirtualSystemDescriptionType_Name); 1414 vsd->AddDescription(VirtualSystemDescriptionType_Name, 1415 Bstr(strVMName).raw(), 1416 Bstr(strVMName).raw()); 1417 //No check again because it would be weird if a VM with such unique name exists 1418 } 1419 1420 Utf8Str strInsId; 1421 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_CloudInstanceId)//aVBoxValues is set in this #define 1422 if (aVBoxValues.size() == 0) 1423 { 1424 hrc = setErrorVrc(VERR_NOT_FOUND, "%s: Cloud Instance Id wasn't found", __FUNCTION__); 1367 1425 break; 1368 1369 ComPtr<IProgress> pProgress; 1370 pTask->pProgress.queryInterfaceTo(pProgress.asOutParam()); 1426 } 1427 strInsId = aVBoxValues[0]; 1371 1428 1372 1429 LogRel(("%s: calling CloudClient::ImportInstance\n", __FUNCTION__)); 1430 1431 /* Here it's strongly supposed that cloud import produces ONE object on the disk. 1432 Because it much easier to manage one object in any case. 1433 In the case when cloud import creates several object on the disk all of them 1434 must be combined together into one object by cloud client. 1435 The most simple way is to create a TAR archive. */ 1373 1436 hrc = cloudClient->ImportInstance(m->virtualSystemDescriptions.front(), 1374 1437 aVBoxValues[0], 1375 1438 VBox, 1376 1439 pProgress); 1377 Bstr instId(aVBoxValues[0]); 1378 Utf8Str strInsId(instId);1440 1441 hrc = S_OK; 1379 1442 if (FAILED(hrc)) 1380 1443 { 1381 hrc = setError(hrc, "%s: Import cloud instance \'%s\' failed\n", __FUNCTION__, strInsId.c_str()); 1444 strLastActualErrorDesc = Utf8StrFmt("%s: Cloud import (cloud phase) failed. " 1445 "Used cloud instance is \'%s\'\n", __FUNCTION__, strInsId.c_str()); 1446 1447 LogRel((strLastActualErrorDesc.c_str())); 1448 hrc = setError(hrc, strLastActualErrorDesc.c_str()); 1382 1449 break; 1383 1450 } 1384 1451 1385 Utf8Str vsdData; 1386 1387 retTypes.setNull(); 1388 aRefs.setNull(); 1389 aOvfValues.setNull(); 1390 aVBoxValues.setNull(); 1391 aExtraConfigValues.setNull(); 1392 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_CPU, 1393 ComSafeArrayAsOutParam(retTypes), 1394 ComSafeArrayAsOutParam(aRefs), 1395 ComSafeArrayAsOutParam(aOvfValues), 1396 ComSafeArrayAsOutParam(aVBoxValues), 1397 ComSafeArrayAsOutParam(aExtraConfigValues)); 1398 if (FAILED(hrc)) 1399 break; 1400 vsdData = aVBoxValues[0]; 1401 if (vsdData.isEmpty()) 1402 LogRel(("%s: Number of CPUs wasn't found\n", __FUNCTION__)); 1452 } while (0); 1453 } 1454 else 1455 { 1456 vrc = VERR_NOT_SUPPORTED; 1457 hrc = setErrorVrc(vrc, tr("Import from Cloud isn't supported for more than one VM instance.")); 1458 1459 /* Reset the state so others can call methods again */ 1460 m->state = Data::ApplianceIdle; 1461 return hrc; 1462 } 1463 1464 if (FAILED(hrc)) 1465 { 1466 HRESULT temp_hrc = hrc;//save the original result 1467 Utf8Str generalRollBackErrorMessage("Rollback action for Import Cloud operation failed." 1468 "Some leavings may exist on the local disk or in the Cloud."); 1469 /* 1470 * Roll-back actions. 1471 * we finish here if: 1472 * 1. The getting the object form the Cloud has been failed. 1473 * 2. Something is wrong with getting data from ComPtr<IVirtualSystemDescription> vsd. 1474 * 3. More than 1 VirtualSystemDescription is presented in the list m->virtualSystemDescriptions. 1475 * Maximum what we have there are: 1476 * 1. The downloaded object, so just check the presence and delete it if one exists 1477 * 2. Some leftovers in the Cloud. Also delete them too if it's possible. 1478 * Should they be deleted in the OCICloudClient::importInstance()? 1479 * Because deleting them here is not easy as it in the importInstance(). 1480 */ 1481 1482 { 1483 /* small explanation here, the image here points out to the whole downloaded object (not to the image only) 1484 * filled during the first cloud import stage (in the ICloudClient::importInstance()) */ 1485 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_HardDiskImage)//aVBoxValues is set in this #define 1486 if (aVBoxValues.size() == 0) 1487 hrc = setErrorVrc(VERR_NOT_FOUND, generalRollBackErrorMessage.c_str()); 1403 1488 else 1404 LogRel(("%s: Number of CPUs is %s\n", __FUNCTION__, vsdData.c_str())); 1405 1406 retTypes.setNull(); 1407 aRefs.setNull(); 1408 aOvfValues.setNull(); 1409 aVBoxValues.setNull(); 1410 aExtraConfigValues.setNull(); 1411 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_Memory, 1412 ComSafeArrayAsOutParam(retTypes), 1413 ComSafeArrayAsOutParam(aRefs), 1414 ComSafeArrayAsOutParam(aOvfValues), 1415 ComSafeArrayAsOutParam(aVBoxValues), 1416 ComSafeArrayAsOutParam(aExtraConfigValues)); 1417 if (FAILED(hrc)) 1418 break; 1419 vsdData = aVBoxValues[0]; 1420 if (vsdData.isEmpty()) 1421 LogRel(("%s: Size of RAM wasn't found\n", __FUNCTION__)); 1489 { 1490 vsdData = aVBoxValues[0]; 1491 //try to delete the downloaded object 1492 bool fExist = RTPathExists(vsdData.c_str()); 1493 if (fExist) 1494 { 1495 vrc = RTFileDelete(vsdData.c_str()); 1496 if (RT_FAILURE(vrc)) 1497 { 1498 hrc = setErrorVrc(vrc, generalRollBackErrorMessage.c_str()); 1499 LogRel(("%s: Rollback action - the object %s hasn't been deleted\n", __FUNCTION__, vsdData.c_str())); 1500 } 1501 else 1502 LogRel(("%s: Rollback action - the object %s has been deleted\n", __FUNCTION__, vsdData.c_str())); 1503 } 1504 } 1505 } 1506 1507 { 1508 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_CloudInstanceId)//aVBoxValues is set in this #define 1509 if (aVBoxValues.size() == 0) 1510 hrc = setErrorVrc(VERR_NOT_FOUND, generalRollBackErrorMessage.c_str()); 1422 1511 else 1423 LogRel(("%s: Size of RAM is %sMB\n", __FUNCTION__, vsdData.c_str())); 1424 1425 retTypes.setNull(); 1426 aRefs.setNull(); 1427 aOvfValues.setNull(); 1428 aVBoxValues.setNull(); 1429 aExtraConfigValues.setNull(); 1430 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_OS, 1431 ComSafeArrayAsOutParam(retTypes), 1432 ComSafeArrayAsOutParam(aRefs), 1433 ComSafeArrayAsOutParam(aOvfValues), 1434 ComSafeArrayAsOutParam(aVBoxValues), 1435 ComSafeArrayAsOutParam(aExtraConfigValues)); 1436 if (FAILED(hrc)) 1437 break; 1438 vsdData = aVBoxValues[0]; 1439 if (vsdData.isEmpty()) 1440 LogRel(("%s: OS type wasn't found", __FUNCTION__)); 1441 else 1442 LogRel(("%s: OS type is %s\n", __FUNCTION__, vsdData.c_str())); 1443 1444 retTypes.setNull(); 1445 aRefs.setNull(); 1446 aOvfValues.setNull(); 1447 aVBoxValues.setNull(); 1448 aExtraConfigValues.setNull(); 1449 hrc = vsd->GetDescriptionByType(VirtualSystemDescriptionType_Name, 1450 ComSafeArrayAsOutParam(retTypes), 1451 ComSafeArrayAsOutParam(aRefs), 1452 ComSafeArrayAsOutParam(aOvfValues), 1453 ComSafeArrayAsOutParam(aVBoxValues), 1454 ComSafeArrayAsOutParam(aExtraConfigValues)); 1455 if (FAILED(hrc)) 1456 break; 1457 vsdData = aVBoxValues[0]; 1458 if (vsdData.isEmpty()) 1459 LogRel(("%s: VM name wasn't found", __FUNCTION__)); 1460 else 1461 LogRel(("%s: VM name is %s\n", __FUNCTION__, vsdData.c_str())); 1462 } while (0); 1512 { 1513 vsdData = aVBoxValues[0]; 1514 //hrc = cloud.EliminateImportLeavings(aVBoxValues[0], pProgress);//future function 1515 if (FAILED(hrc)) 1516 { 1517 hrc = setErrorVrc(VERR_INVALID_STATE, generalRollBackErrorMessage.c_str()); 1518 LogRel(("%s: Rollback action - the leavings in the %s after import the " 1519 "instance %s may not have been deleted\n", 1520 __FUNCTION__, strProviderName.c_str(), vsdData.c_str())); 1521 } 1522 else 1523 LogRel(("%s: Rollback action - the leavings in the %s after import the " 1524 "instance %s have been deleted\n", 1525 __FUNCTION__, strProviderName.c_str(), vsdData.c_str())); 1526 } 1527 } 1528 1529 /* Because during the rollback phase the hrc may have the good result 1530 * Thus we restore the original error in the case when the rollback phase was successful 1531 * Otherwise we return not the original error but the last error in the rollback phase */ 1532 if (SUCCEEDED(hrc)) 1533 hrc = setError(temp_hrc, strLastActualErrorDesc.c_str());//restore the original result 1463 1534 } 1464 1535 else 1465 hrc = setErrorVrc(VERR_MISMATCH, tr("Import from Cloud isn't supported for more than one VM instance.")); 1466 1467 if (FAILED(hrc)) 1468 { 1469 //some roll-back actions 1470 } 1471 else 1472 { 1473 //continue and create new VM using data from VSD and downloaded image as base image 1474 //The downloaded image should be converted to VDI/VMDK if it has another format 1536 { 1537 1538 /* Small explanation here, the image here points out to the whole downloaded object (not to the image only) 1539 * filled during the first cloud import stage (in the ICloudClient::importInstance()) */ 1540 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_HardDiskImage)//aVBoxValues is set in this #define 1541 if (aVBoxValues.size() == 0) 1542 throw setErrorVrc(VERR_NOT_FOUND, "%s: The description of the downloaded object wasn't found", __FUNCTION__); 1543 1544 Utf8Str strAbsSrcPath(aVBoxValues[0]); 1545 1546 /* Put all VFS* declaration here because they are needed to be release by the corresponding 1547 RTVfs***Release functions in the case of exception */ 1548 RTVFSOBJ hVfsObj; 1549 RTVFSFSSTREAM hVfsFssObject; 1550 RTVFSIOSTREAM hVfsIosCurr; 1551 1552 /* Continue and create new VM using data from VSD and downloaded object. 1553 * The downloaded images should be converted to VDI/VMDK if they have another format */ 1554 try 1555 { 1556 Utf8Str strInstId("default cloud instance id"); 1557 { 1558 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_CloudInstanceId)//aVBoxValues is set in this #define 1559 if (aVBoxValues.size() != 0)//paranoia but anyway... 1560 strInstId = aVBoxValues[0]; 1561 LogRel(("%s: Importing cloud instance %s\n", __FUNCTION__, strInstId.c_str())); 1562 } 1563 1564 Utf8Str strGroup("/");//default VM group 1565 Utf8Str strTargetFormat("VMDK");//default image format 1566 1567 /* Based on the VM name, create a target machine path. */ 1568 Bstr bstrSettingsFilename; 1569 hrc = mVirtualBox->ComposeMachineFilename(Bstr(strVMName).raw(), 1570 Bstr(strGroup).raw(), 1571 NULL /* aCreateFlags */, 1572 NULL /* aBaseFolder */, 1573 bstrSettingsFilename.asOutParam()); 1574 if (FAILED(hrc)) throw hrc; 1575 1576 Utf8Str strMachineFolder(bstrSettingsFilename); 1577 strMachineFolder.stripFilename(); 1578 1579 /* Get the system properties. */ 1580 SystemProperties *pSysProps = mVirtualBox->i_getSystemProperties(); 1581 1582 ComObjPtr<MediumFormat> trgFormat; 1583 trgFormat = pSysProps->i_mediumFormatFromExtension(strTargetFormat); 1584 1585 /* Processing the downloaded object (prepare for the local import) */ 1586 RTVFSIOSTREAM hVfsIosSrc; 1587 vrc = RTVfsIoStrmOpenNormal(strAbsSrcPath.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, &hVfsIosSrc); 1588 if (RT_FAILURE(vrc)) 1589 { 1590 strLastActualErrorDesc = Utf8StrFmt("Error opening '%s' for reading (%Rrc)\n", strAbsSrcPath.c_str(), vrc); 1591 throw setErrorVrc(vrc, strLastActualErrorDesc.c_str()); 1592 } 1593 1594 vrc = RTZipTarFsStreamFromIoStream(hVfsIosSrc, 0 /*fFlags*/, &hVfsFssObject); 1595 RTVfsIoStrmRelease(hVfsIosSrc); 1596 if (RT_FAILURE(vrc)) 1597 { 1598 strLastActualErrorDesc = Utf8StrFmt("Error reading the downloaded file '%s' (%Rrc)", strAbsSrcPath.c_str(), vrc); 1599 throw setErrorVrc(vrc, strLastActualErrorDesc.c_str()); 1600 } 1601 1602 /* Create an empty ovf::OVFReader for manual filling it. 1603 * It's not a normal usage case, but we try to re-use some OVF stuff to friend 1604 * the cloud import with OVF import. 1605 * In the standard case the ovf::OVFReader is created earlier.*/ 1606 m->pReader = new ovf::OVFReader(); 1607 1608 /* Create a new virtual system and work directly on the list copy. */ 1609 m->pReader->m_llVirtualSystems.push_back(ovf::VirtualSystem()); 1610 ovf::VirtualSystem &vsys = m->pReader->m_llVirtualSystems.back(); 1611 1612 /* Try to re-use some OVF stuff here */ 1613 { 1614 vsys.strName = strVMName; 1615 uint32_t cpus = 1; 1616 { 1617 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_CPU)//aVBoxValues is set in this #define 1618 if (aVBoxValues.size() != 0) 1619 { 1620 vsdData = aVBoxValues[0]; 1621 cpus = vsdData.toUInt32(); 1622 } 1623 vsys.cCPUs = (uint16_t)cpus; 1624 LogRel(("%s: Number of CPUs is %s\n", __FUNCTION__, vsdData.c_str())); 1625 } 1626 1627 ULONG memory;//Mb 1628 pGuestOSType->COMGETTER(RecommendedRAM)(&memory); 1629 { 1630 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_Memory)//aVBoxValues is set in this #define 1631 if (aVBoxValues.size() != 0) 1632 { 1633 vsdData = aVBoxValues[0]; 1634 memory = vsdData.toUInt32(); 1635 } 1636 vsys.ullMemorySize = memory; 1637 LogRel(("%s: Size of RAM is %sMB\n", __FUNCTION__, vsdData.c_str())); 1638 } 1639 1640 { 1641 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_Description)//aVBoxValues is set in this #define 1642 if (aVBoxValues.size() != 0) 1643 { 1644 vsdData = aVBoxValues[0]; 1645 vsys.strDescription = vsdData; 1646 } 1647 LogRel(("%s: VM description \'%s\'\n", __FUNCTION__, vsdData.c_str())); 1648 } 1649 1650 { 1651 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_OS)//aVBoxValues is set in this #define 1652 if (aVBoxValues.size() != 0) 1653 strOsType = aVBoxValues[0]; 1654 vsys.strTypeVBox = strOsType; 1655 LogRel(("%s: OS type is %s\n", __FUNCTION__, strOsType.c_str())); 1656 } 1657 1658 ovf::EthernetAdapter ea; 1659 { 1660 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_NetworkAdapter)//aVBoxValues is set in this #define 1661 if (aVBoxValues.size() != 0) 1662 { 1663 ea.strAdapterType = (Utf8Str)(aVBoxValues[0]); 1664 ea.strNetworkName = "NAT";//default 1665 vsys.llEthernetAdapters.push_back(ea); 1666 LogRel(("%s: Network adapter type is %s\n", __FUNCTION__, ea.strAdapterType.c_str())); 1667 } 1668 else 1669 { 1670 NetworkAdapterType_T defaultAdapterType = NetworkAdapterType_Am79C970A; 1671 pGuestOSType->COMGETTER(AdapterType)(&defaultAdapterType); 1672 Utf8StrFmt dat("%RU32", (uint32_t)defaultAdapterType); 1673 vsd->AddDescription(VirtualSystemDescriptionType_NetworkAdapter, 1674 Bstr(dat).raw(), 1675 Bstr(Utf8Str("NAT")).raw()); 1676 } 1677 } 1678 1679 ovf::HardDiskController hdc; 1680 { 1681 //It's thought that SATA is supported by any OS types 1682 hdc.system = ovf::HardDiskController::SATA; 1683 hdc.idController = 0; 1684 1685 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_HardDiskControllerSATA)//aVBoxValues is set in this #define 1686 if (aVBoxValues.size() != 0) 1687 hdc.strControllerType = (Utf8Str)(aVBoxValues[0]); 1688 else 1689 hdc.strControllerType = "AHCI"; 1690 1691 LogRel(("%s: Hard disk controller type is %s\n", __FUNCTION__, hdc.strControllerType.c_str())); 1692 vsys.mapControllers[hdc.idController] = hdc; 1693 1694 if (aVBoxValues.size() == 0) 1695 { 1696 /* we should do it here because it'll be used later in the OVF logic (inside i_importMachines()) */ 1697 vsd->AddDescription(VirtualSystemDescriptionType_HardDiskControllerSATA, 1698 Bstr(hdc.strControllerType).raw(), 1699 Bstr(hdc.strControllerType).raw()); 1700 } 1701 } 1702 1703 { 1704 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_SoundCard)//aVBoxValues is set in this #define 1705 if (aVBoxValues.size() != 0) 1706 vsys.strSoundCardType = (Utf8Str)(aVBoxValues[0]); 1707 else 1708 { 1709 AudioControllerType_T defaultAudioController; 1710 pGuestOSType->COMGETTER(RecommendedAudioController)(&defaultAudioController); 1711 vsys.strSoundCardType = Utf8StrFmt("%RU32", (uint32_t)defaultAudioController);//"ensoniq1371";//"AC97"; 1712 vsd->AddDescription(VirtualSystemDescriptionType_SoundCard, 1713 Bstr(vsys.strSoundCardType).raw(), 1714 Bstr(vsys.strSoundCardType).raw()); 1715 } 1716 1717 LogRel(("%s: Sound card is %s\n", __FUNCTION__, vsys.strSoundCardType.c_str())); 1718 } 1719 1720 vsys.fHasFloppyDrive = false; 1721 vsys.fHasCdromDrive = false; 1722 vsys.fHasUsbController = true; 1723 } 1724 1725 unsigned currImageObjectNum = 0; 1726 hrc = S_OK; 1727 do 1728 { 1729 char *pszName = NULL; 1730 RTVFSOBJTYPE enmType; 1731 vrc = RTVfsFsStrmNext(hVfsFssObject, &pszName, &enmType, &hVfsObj); 1732 if (RT_FAILURE(vrc)) 1733 { 1734 if (vrc != VERR_EOF) 1735 { 1736 hrc = setErrorVrc(vrc, tr("%s: Error reading '%s' (%Rrc)"), __FUNCTION__, strAbsSrcPath.c_str(), vrc); 1737 throw hrc; 1738 } 1739 break; 1740 } 1741 1742 /* We only care about entries that are files. Get the I/O stream handle for them. */ 1743 if ( enmType == RTVFSOBJTYPE_IO_STREAM 1744 || enmType == RTVFSOBJTYPE_FILE) 1745 { 1746 /* Find the suffix and check if this is a possibly interesting file. */ 1747 char *pszSuffix = RTStrToLower(strrchr(pszName, '.')); 1748 1749 /* Get the I/O stream. */ 1750 hVfsIosCurr = RTVfsObjToIoStream(hVfsObj); 1751 Assert(hVfsIosCurr != NIL_RTVFSIOSTREAM); 1752 1753 /* Get the source medium format */ 1754 ComObjPtr<MediumFormat> srcFormat; 1755 srcFormat = pSysProps->i_mediumFormatFromExtension(pszSuffix + 1); 1756 1757 /* unknown image format so just extract a file without any processing */ 1758 if (srcFormat == NULL) 1759 { 1760 /* Read the file into a memory buffer */ 1761 void *pvBuffered; 1762 size_t cbBuffered; 1763 RTVFSFILE hVfsDstFile; 1764 try 1765 { 1766 vrc = RTVfsIoStrmReadAll(hVfsIosCurr, &pvBuffered, &cbBuffered); 1767 RTVfsIoStrmRelease(hVfsIosCurr); 1768 hVfsIosCurr = NIL_RTVFSIOSTREAM; 1769 if (RT_FAILURE(vrc)) 1770 throw setErrorVrc(vrc, tr("Could not read the file '%s' (%Rrc)"), strAbsSrcPath.c_str(), vrc); 1771 1772 Utf8StrFmt strAbsDstPath("%s%s%s", strMachineFolder.c_str(), RTPATH_SLASH_STR, pszName); 1773 1774 /* Simple logic - just try to get dir info, in case of absent try to create one. 1775 No deep errors analysis */ 1776 RTFSOBJINFO dirInfo; 1777 vrc = RTPathQueryInfo(strMachineFolder.c_str(), &dirInfo, RTFSOBJATTRADD_NOTHING); 1778 if (RT_FAILURE(vrc)) 1779 { 1780 if (vrc == VERR_FILE_NOT_FOUND || vrc == VERR_PATH_NOT_FOUND) 1781 { 1782 vrc = RTDirCreate(strMachineFolder.c_str(), 0755, 0); 1783 if (RT_FAILURE(vrc)) 1784 throw setErrorVrc(vrc, tr("Could not create the directory '%s' (%Rrc)"), 1785 strMachineFolder.c_str(), vrc); 1786 } 1787 else 1788 throw setErrorVrc(vrc, tr("Error during getting info about the directory '%s' (%Rrc)"), 1789 strMachineFolder.c_str(), vrc); 1790 } 1791 1792 /* Write the file on the disk */ 1793 vrc = RTVfsFileOpenNormal(strAbsDstPath.c_str(), 1794 RTFILE_O_WRITE | RTFILE_O_DENY_ALL | RTFILE_O_CREATE, 1795 &hVfsDstFile); 1796 if (RT_FAILURE(vrc)) 1797 throw setErrorVrc(vrc, tr("Could not create the file '%s' (%Rrc)"), strAbsDstPath.c_str(), vrc); 1798 1799 size_t cbWritten; 1800 RTVfsFileWrite(hVfsDstFile, pvBuffered, cbBuffered, &cbWritten); 1801 if (RT_FAILURE(vrc)) 1802 throw setErrorVrc(vrc, tr("Could not write into the file '%s' (%Rrc)"), strAbsDstPath.c_str(), vrc); 1803 } 1804 catch (HRESULT aRc) 1805 { 1806 hrc = aRc; 1807 } 1808 catch (...) 1809 { 1810 hrc = VERR_UNEXPECTED_EXCEPTION; 1811 } 1812 1813 /* Don't forget to release all resources */ 1814 RTVfsFileRelease(hVfsDstFile); 1815 RTVfsIoStrmReadAllFree(pvBuffered, cbBuffered); 1816 1817 /*re-throw the error */ 1818 if (FAILED(hrc)) 1819 throw hrc; 1820 1821 } 1822 else 1823 { 1824 /* Image format is supported by VBox so extract the file and try to convert 1825 * one to the default format (which is VMDK for now) */ 1826 Utf8Str z(bstrSettingsFilename); 1827 Utf8StrFmt strAbsDstPath("%s_%d.%s", 1828 z.stripSuffix().c_str(), 1829 currImageObjectNum, 1830 strTargetFormat.c_str()); 1831 1832 hrc = mVirtualBox->i_findHardDiskByLocation(strAbsDstPath, false, NULL); 1833 if (SUCCEEDED(hrc)) 1834 throw setError(VERR_ALREADY_EXISTS, tr("The hard disk '%s' already exists."), strAbsDstPath.c_str()); 1835 1836 /* Create an IMedium object. */ 1837 ComObjPtr<Medium> pTargetMedium; 1838 pTargetMedium.createObject(); 1839 hrc = pTargetMedium->init(mVirtualBox, 1840 strTargetFormat, 1841 strAbsDstPath, 1842 Guid::Empty /* media registry: none yet */, 1843 DeviceType_HardDisk); 1844 if (FAILED(hrc)) 1845 throw hrc; 1846 1847 pTask->pProgress->SetNextOperation(BstrFmt(tr("Importing virtual disk image '%s'",pszName)).raw(), 1848 200); 1849 ComObjPtr<Medium> nullParent; 1850 ComPtr<IProgress> pProgressImport; 1851 ComObjPtr<Progress> pProgressImportTmp; 1852 hrc = pProgressImportTmp.createObject(); 1853 if (FAILED(hrc)) 1854 throw hrc; 1855 1856 hrc = pProgressImportTmp->init(mVirtualBox, 1857 static_cast<IAppliance*>(this), 1858 Utf8StrFmt(tr("Importing medium '%s'"), 1859 pszName), 1860 TRUE); 1861 if (FAILED(hrc)) 1862 throw hrc; 1863 1864 pProgressImportTmp.queryInterfaceTo(pProgressImport.asOutParam()); 1865 1866 hrc = pTargetMedium->i_importFile(pszName, 1867 srcFormat, 1868 MediumVariant_Standard, 1869 hVfsIosCurr, 1870 nullParent, 1871 pProgressImportTmp, 1872 true /* aNotify */); 1873 RTVfsIoStrmRelease(hVfsIosCurr); 1874 hVfsIosCurr = NIL_RTVFSIOSTREAM; 1875 /* Now wait for the background import operation to complete; 1876 * this throws HRESULTs on error. */ 1877 pTask->pProgress->WaitForOtherProgressCompletion(pProgressImport, 0 /* indefinite wait */); 1878 1879 /* Try to re-use some OVF stuff here */ 1880 { 1881 /* Small trick here. 1882 * We add new item into the actual VSD after successful conversion. 1883 * There is no need to delete any previous records describing the images in the VSD 1884 * because later in the code the search of the images in the VSD will use such records 1885 * with the actual image id (d.strDiskId = pTargetMedium->i_getId().toString()) which is 1886 * used as a key for m->pReader->m_mapDisks, vsys.mapVirtualDisks. 1887 * So all 3 objects are tied via the image id. 1888 * In the OVF case we already have all such records in the VSD after reading OVF 1889 * description file (read() and interpret() functions).*/ 1890 ovf::DiskImage d; 1891 d.strDiskId = pTargetMedium->i_getId().toString(); 1892 d.strHref = pTargetMedium->i_getLocationFull(); 1893 d.strFormat = pTargetMedium->i_getFormat(); 1894 d.iSize = pTargetMedium->i_getSize(); 1895 d.ulSuggestedSizeMB = (uint32_t)(pTargetMedium->i_getSize()/_1M); 1896 1897 m->pReader->m_mapDisks[d.strDiskId] = d; 1898 1899 ComObjPtr<VirtualSystemDescription> vsdescThis = m->virtualSystemDescriptions.front(); 1900 1901 /* It's needed here to use the internal function i_addEntry() instead of the API function 1902 * addDescription() because we should pass the d.strDiskId for the proper handling this 1903 * disk later in the i_importMachineGeneric(): 1904 * - find the line like this "if (vsdeHD->strRef == diCurrent.strDiskId)". 1905 * if those code can be eliminated then addDescription() will be used. */ 1906 vsdescThis->i_addEntry(VirtualSystemDescriptionType_HardDiskImage, 1907 d.strDiskId, 1908 d.strHref, 1909 d.strHref, 1910 d.ulSuggestedSizeMB); 1911 1912 ovf::VirtualDisk vd; 1913 vd.idController = vsys.mapControllers[0].idController; 1914 vd.ulAddressOnParent = 0; 1915 vd.strDiskId = d.strDiskId; 1916 vsys.mapVirtualDisks[vd.strDiskId] = vd; 1917 1918 } 1919 1920 ++currImageObjectNum; 1921 } 1922 1923 RTVfsIoStrmRelease(hVfsIosCurr); 1924 hVfsIosCurr = NIL_RTVFSIOSTREAM; 1925 } 1926 1927 RTVfsObjRelease(hVfsObj); 1928 hVfsObj = NIL_RTVFSOBJ; 1929 1930 RTStrFree(pszName); 1931 1932 } while (SUCCEEDED(hrc)); 1933 1934 RTVfsFsStrmRelease(hVfsFssObject); 1935 hVfsFssObject = NIL_RTVFSFSSTREAM; 1936 1937 pTask->pProgress->SetNextOperation(BstrFmt(tr("Creating new VM '%s'", strVMName.c_str())).raw(), 50); 1938 /* Create the import stack to comply OVF logic. 1939 * Before we filled some other data structures which are needed by OVF logic too.*/ 1940 ImportStack stack(pTask->locInfo, m->pReader->m_mapDisks, pTask->pProgress, NIL_RTVFSFSSTREAM); 1941 i_importMachines(stack); 1942 1943 } 1944 catch (HRESULT aRc) 1945 { 1946 LogRel(("%s: Cloud import (local phase) - exception occured (%Rrc).\n", __FUNCTION__, aRc)); 1947 hrc = aRc; 1948 } 1949 catch (...) 1950 { 1951 hrc = VERR_UNRESOLVED_ERROR; 1952 LogRel(("%s: Cloud import (local phase) - Unknown exception occured.\n", __FUNCTION__)); 1953 } 1954 1955 if (FAILED(hrc)) 1956 { 1957 /* Try to free VFS stuff because some of them might not be released due to the exception */ 1958 if (hVfsIosCurr != NIL_RTVFSIOSTREAM) 1959 RTVfsIoStrmRelease(hVfsIosCurr); 1960 if (hVfsObj != NIL_RTVFSOBJ) 1961 RTVfsObjRelease(hVfsObj); 1962 if (hVfsFssObject != NIL_RTVFSFSSTREAM) 1963 RTVfsFsStrmRelease(hVfsFssObject); 1964 1965 LogRel(("%s: Cloud import (local phase): original error was \'%s\'.\n", __FUNCTION__, strLastActualErrorDesc.c_str())); 1966 1967 /* What to do here? 1968 * Delete or not the downloaded object? 1969 * For now: 1970 * - check the list of imported images, detach them and next delete. 1971 * - check the registration of created VM and delete one. 1972 * - check some other leavings if they may exist and delete them too. 1973 */ 1974 1975 /* Small explanation here. 1976 * After adding extracted files into the actual VSD the returned list will contain not only the 1977 * record about the downloaded object but also the records about the extracted files from this object. 1978 * It's needed to go through this list to find the record about the downloaded object. 1979 * But it was the first record added into the list, so aVBoxValues[0] should be correct here. 1980 */ 1981 GET_VSD_DESCRIPTION_BY_TYPE(VirtualSystemDescriptionType_HardDiskImage)//aVBoxValues is set in this #define 1982 if (aVBoxValues.size() != 0) 1983 hrc = setError(hrc, "%s: Cloud import (local phase) failed. Find the root cause in the log file. " 1984 "But the first phase was successful and the downloaded object was stored as \'%s\'\n", 1985 __FUNCTION__, Utf8Str(aVBoxValues[0]).c_str()); 1986 } 1475 1987 } 1476 1988 … … 2337 2849 else if (mode == ImportCloud) 2338 2850 { 2339 /*2340 1. Create a custom imaghe from the instance2341 2. Import the custom image into the Object Storage (OCI format - TAR file with QCOW2 image and JSON file)2342 3. Download the object from the Object Storage2343 4. Open the object, extract QCOW2 image and convert one QCOW2->VDI2344 5. Create VM with user settings and attach the converted image to VM2345 6. Lauch VM.2346 */2347 2851 progress.createObject(); 2348 2852 if (locInfo.strProvider.equals("OCI")) 2349 2853 { 2854 /* 2855 * 1. Create a custom image from the instance 2856 * - 2 operations (starting and waiting) 2857 * 2. Import the custom image into the Object Storage (OCI format - TAR file with QCOW2 image and JSON file) 2858 * - 2 operations (starting and waiting) 2859 * 3. Download the object from the Object Storage 2860 * - 2 operations (starting and waiting) 2861 * 4. Open the object, extract QCOW2 image and convert one QCOW2->VDI 2862 * - 1 operation (extracting and conversion are piped) 2863 * 5. Create VM with user settings and attach the converted image to VM 2864 * - 1 operation. 2865 * sum up = 2+2+2+1+1 = 8 op 2866 */ 2867 2868 /* 2869 * See src/VBox/ExtPacks/Puel/OCI/OCICloudClient.h. 2870 * Weight of cloud import operations (1-3 items from above): 2871 * Total = 750 = 10+40+50+50+200x2+200. 2872 * 2873 * Weight of local import operations (4-5 items from above): 2874 * Total = 250 = 200 (extract and convert) + 50 (create VM, attach disks) 2875 */ 2350 2876 progress->init(mVirtualBox, static_cast<IAppliance*>(this), 2351 2877 Bstr("Importing VM from Cloud...").raw(), 2352 2878 TRUE /* aCancelable */, 2353 6, // ULONG cOperations,2354 750, // ULONG ulTotalOperationsWeight,2879 8, // ULONG cOperations, 2880 1000, // ULONG ulTotalOperationsWeight, 2355 2881 Bstr("Importing VM from Cloud...").raw(), // aFirstOperationDescription 2356 2882 10); // ULONG ulFirstOperationWeight … … 3698 4224 3699 4225 ComObjPtr<Medium> pTargetMedium; 3700 i_importOneDiskImage(diCurrent, 3701 vsdeTargetHD->strVBoxCurrent, 3702 pTargetMedium, 3703 stack); 4226 if (stack.locInfo.storageType == VFSType_Cloud) 4227 { 4228 //we have already all disks prepared (converted and registered in the VBox) 4229 //and in the correct place (VM machine folder). 4230 //so what is needed is to get the disk uuid from VirtualDisk::strDiskId 4231 //and find the Medium object with this uuid. 4232 //next just attach the Medium object to new VM. 4233 //VirtualDisk::strDiskId is filled in the 4234 4235 Guid id(ovfVdisk.strDiskId); 4236 rc = mVirtualBox->i_findHardDiskById(id, false, &pTargetMedium); 4237 if (FAILED(rc)) 4238 throw rc; 4239 } 4240 else 4241 { 4242 i_importOneDiskImage(diCurrent, 4243 vsdeTargetHD->strVBoxCurrent, 4244 pTargetMedium, 4245 stack); 4246 } 3704 4247 3705 4248 // now use the new uuid to attach the medium to our new machine -
trunk/src/VBox/Main/xml/ovfreader.cpp
r76553 r78602 33 33 // 34 34 //////////////////////////////////////////////////////////////////////////////// 35 36 /** 37 * Default Constructor. 38 * Should be used if you don't have an OVF file, but want to fill the data 39 * m_mapDisks, m_llVirtualSystems manually 40 */ 41 OVFReader::OVFReader() 42 { 43 } 35 44 36 45 /**
Note:
See TracChangeset
for help on using the changeset viewer.