Virtual Disk Mount API在Linux挂载虚拟磁盘文件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hilavergil/article/details/80273003

在查看虚拟磁盘文件系统的时候,需要将虚拟磁盘挂载到主机上,VMware提供了相应的接口——Virtual Disk Mount API

这部分遇到了几个坑,记录一下,也算是对做相同或相似工作的人提个醒,遇到了这些问题能够绕过去。

首先安装VDDK,参照如下链接:

https://code.vmware.com/doc/preview?id=1497#/doc/vddkInstall.4.3.html

其次,VDDK安装完成后就可以开始编码了,如果在后续的编译或执行过程中遇到了问题,请参照下面这位小哥的博客:

https://blog.csdn.net/zhouxukun123/article/category/7140664

使用Virtual Disk Mount API可以将一个本地的虚拟磁盘文件挂载到本地,也可以将一个ESXi上虚拟机的虚拟磁盘文件挂载到本地。挂载的过程大致分为如下几个步骤(以本地vmdk文件的挂载为例):

1.初始化

vixError = VixDiskLib_InitEx(VERSION_MAJOR, VERSION_MINOR, &LogFunc, &WarnFunc, &PanicFunc, libdir, NULL);

VERSION_MAJOR、VERSION_MINOR分别对应你下载的VDDK的主次版本号

vixError = VixMntapi_Init(VIXMNTAPI_MAJOR_VERSION, VIXMNTAPI_MINOR_VERSION, &LogFunc, &WarnFunc, &PanicFunc, libdir, NULL);

这个函数中前两个参数的宏定义在vixMntapi.h中,分别为1和0

2.建立连接,获取VixDiskLibConnection

如果是本地vmdk文件:

vixError = VixDiskLib_Connect(NULL, &connection);

如果是远程虚拟机:

vixError = VixDiskLib_Connect(&cnxParam, &connection);

3.打开磁盘,获取VixDiskSetHandle

vixError = VixMntapi_OpenDisks(connection,diskNames, diskHandlesCount, openFlag, &diskSetHandle);

其中diskNames的类型为const char *diskNames[],是需要打开的各个vmdk文件的绝对路径的数组。diskHandlesCount在Linux下为1。成功之后可以用VixMntapi_GetDiskSetInfo查看虚拟磁盘的挂载路径

4.获取虚拟磁盘分区的句柄

vixError = VixMntapi_GetVolumeHandles(diskSetHandle, &numVolumes, &volumeHandles);

执行成功则返回分区个数numVolumes和分区句柄的数组volumeHandles

5.挂载分区

vixError = VixMntapi_MountVolume(volumeHandles[i], FALSE);

6.获取分区挂载位置

vixError = VixMntapi_GetVolumeInfo(volumeHandles[i], &newVolume.volInfo);

7.卸载分区

VixMntapi_DismountVolume(volumeHandles[i],TRUE);

8.关闭虚拟磁盘

vixError=VixMntapi_CloseDiskSet(diskSetHandle);

9.清理工作

vixError = VixDiskLib_Disconnect(connection);
VixMntapi_Exit();

大致就是这样的步骤,遇到的几个问题在下面罗列一下:

圈1.初始化

注意初始化时候的版本号,vix Mnt api的版本号一定为1和0。

圈2.打开虚拟磁盘

函数

VixMntapi_OpenDisks(VixDiskLibConnection connection,
                    const char *diskNames[],
                    size_t numberOfDisks,
                    uint32 openFlags,

                    VixDiskSetHandle *handle);

其参数说明如下:

/**
 * Opens the set of disks for mounting.
 * @param connection [in] VixDiskLibConnection to use for opening the disks.
 *          VixDiskLib_Open with the specified flags will be called on each
 *          disk to open.
 * @param diskNames [in] Array of names of disks to open.
 * @param numberOfDisks [in] Number of disk handles in the array.
 *                           Must be 1 for Linux.
 * @param flags [in] Flags to open the disk.
 * @param handle [out] Disk set handle filled in.
 * @return VIX_OK if success, suitable VIX error code otherwise.

 */

一是要注意numberOfDisks在Linux下为1;

二是建议flags置0、置0、置0!!!这个地方坑我很惨,如果以只读模式打开会造成分区无法挂载的问题。实际上挂载后会修改xxx.vmdk(虚拟磁盘的配置文件)的CID字段和ddb.longContentID字段,对应的xxx-flat.vmdk(虚拟磁盘的二进制数据)文件也会被修改,如果开启了块修改追踪,对应的xxx-ctk.vmdk也会被修改。

圈3.挂载分区

函数

VixMntapi_MountVolume(VixVolumeHandle volumeHandle,

                      Bool readOnly);

在Linux下不支持只读模式的分区挂载,第二个参数置为FALSE。

最后贴上完整的代码:

//#pragma comment(lib, "vixDiskLib.lib")
//#pragma comment(lib, "vixMntapi.lib")
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#include <process.h>
#else

#include <dlfcn.h>
#include <sys/time.h>

#endif
//#include "ChangedBlock.h"
#include "util.h"
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <stdexcept>
#include <cstring>
#include <unistd.h>
#include "vixDiskLib.h"
#include "vixMntapi.h"

using namespace std;


#define VERSION_MAJOR 6
#define VERSION_MINOR 0
#define ERROR_MNTAPI_VOLUME_ALREADY_MOUNTED	24305

static void LogFunc(const char *fmt, va_list args);

static void WarnFunc(const char *fmt, va_list args);

static void PanicFunc(const char *fmt, va_list args);

typedef struct {
    VixVolumeHandle volumeHandle;
    VixVolumeInfo* volInfo;
} MountedVolume;


int main() {

    VixError vixError;
    char libdir[] = {"/xxx/vmware-vix-disklib-distrib"};

    char host[] = {"xxx.vm.com"};
    char userName[] = {"xxx"};
    char password[] = {"xxx"};
    char vmPath[] = {"vmPath=datacenter/vm/xxx"};
    char thumbPrint[] = {"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};

    VixDiskLibConnectParams cnxParam = {0};
    cnxParam.credType = VIXDISKLIB_CRED_UID;
    cnxParam.serverName = host;
    cnxParam.creds.uid.userName = userName;
    cnxParam.creds.uid.password = password;
    cnxParam.port = 443;
    cnxParam.vmxSpec = vmPath;
    cnxParam.thumbPrint = thumbPrint;



    //////TEST MNT API//////

    VixDiskLibConnection connection = NULL;
    const int diskHandlesCount=1;
    uint32 openFlags = VIXDISKLIB_FLAG_OPEN_READ_ONLY;
    VixDiskSetHandle diskSetHandle = NULL;
    const char *diskNames[diskHandlesCount];
    diskNames[0]="/mnt/home/zcy/xxx/xxx.vmdk";
    VixDiskSetInfo *diskSetInfo = NULL;
    VixVolumeHandle *volumeHandles = NULL;
    size_t numVolumes = 0;


    //VixDiskLib_InitEx
    vixError = VixDiskLib_InitEx(VERSION_MAJOR, VERSION_MINOR, &LogFunc, &WarnFunc, &PanicFunc, libdir, NULL);
    printf("VixDiskLib_InitEx   %d\n", vixError);
    if (vixError != VIX_OK) {
        printf("VixDiskLib_InitEx failed\n");
        exit(0);
    }
    printf("VixDiskLib_InitEx success\n");

    //VixMntapi_Init
    vixError = VixMntapi_Init(VIXMNTAPI_MAJOR_VERSION, VIXMNTAPI_MINOR_VERSION, &LogFunc, &WarnFunc, &PanicFunc, libdir, NULL);
    printf("VixMntapi_Init   %d\n", vixError);
    if (vixError != VIX_OK) {
        printf("VixMntapi_Init failed\n");
        exit(0);
    }
    printf("VixMntapi_Init success\n");

    ///////////////////////连接选项////////////////////////
    //if remote connection
//    vixError = VixDiskLib_Connect(&cnxParam, &connection);
    //if local connection
    vixError = VixDiskLib_Connect(NULL, &connection);
    ////////////////////////////////////////////////////////
    if(vixError!=VIX_OK){
        printf("VixDiskLib_Connect failed\n");
        goto SAFE_EXIT;
    }
    printf("VixDiskLib_Connect success\n");

    //open vmdks, obtain diskSetHandle
    //openFlag must be zero
    vixError = VixMntapi_OpenDisks(connection,diskNames, diskHandlesCount, 0, &diskSetHandle);
    if(vixError!=VIX_OK){
        printf("VixMntapi_OpenDisks failed\n");
        goto SAFE_EXIT;
    }
    printf("\n####WATCH ME####\n");
    printf("diskSetHandle is %p\n",diskSetHandle);
    printf("\n################\n");
    printf("VixMntapi_OpenDisks success\n");

    //get diskset info
    vixError = VixMntapi_GetDiskSetInfo(diskSetHandle, &diskSetInfo);
    if(vixError!=VIX_OK){
        printf("VixMntapi_GetDiskSetInfo failed\n");
        goto SAFE_EXIT;
    }
    printf("VixMntapi_GetDiskSetInfo success\n");
    printf("DiskSet Info - flags %u (passed - %u), mountPoint %s.\n",
            diskSetInfo->openFlags, openFlags,
            diskSetInfo->mountPath);

    //get volume handle
    vixError = VixMntapi_GetVolumeHandles(diskSetHandle, &numVolumes, &volumeHandles);
    printf("\n####WATCH ME####\n");
    printf("numVolumes is %d\n",numVolumes);
    printf("\n################\n");
    if(vixError!=VIX_OK){
        printf("VixMntapi_GetVolumeHandles failed\n");
        goto SAFE_EXIT;
    }
    printf("VixMntapi_GetVolumeHandles success\n");
    for (int i = 0; i < numVolumes; ++i) {
        printf("\n####WATCH ME####\n");
        printf("volumeHandles[%d] is %p\n",i,volumeHandles[i]);
        printf("\n################\n");
    }

    //mount volume
    for (int i = 0; i < numVolumes; i++) {
        printf("\n\nMounting volume using VixMntapi_MountVolume...\n");
        vixError = VixMntapi_MountVolume(volumeHandles[i], FALSE);
        if(vixError==VIX_OK){
            printf("mount volume %d success\n",i);
            continue;
        }
        else{
            if (vixError == ERROR_MNTAPI_VOLUME_ALREADY_MOUNTED)
                printf("volume %d already mounted\n",i);
            else
                goto SAFE_EXIT;
        }
    }

    //get volume info
    for(int i=0;i<numVolumes;i++){
        printf("\n\nGetting volume info using VixMntapi_GetVolumeInfo...\n");
        MountedVolume newVolume = {0, 0};
        vixError = VixMntapi_GetVolumeInfo(volumeHandles[i], &newVolume.volInfo);
        if(vixError!=VIX_OK){
            printf("VixMntapi_GetVolumeInfo failed\n");
            goto SAFE_EXIT;
        }
        printf("VixMntapi_GetVolumeInfo success\n");
        printf("\nMounted Volume %d, Type %d, isMounted %d, symLink %s, numGuestMountPoints %d (%s)\n\n",
               i, newVolume.volInfo->type, newVolume.volInfo->isMounted,
               newVolume.volInfo->symbolicLink == NULL ? "<null>" : newVolume.volInfo->symbolicLink,
               newVolume.volInfo->numGuestMountPoints,
               (newVolume.volInfo->numGuestMountPoints == 1) ? (newVolume.volInfo->inGuestMountPoints[0]) : "<null>" );
    }

    ///////////////
    SAFE_EXIT:
    printf("Cleanup Stuff:\n");
    if(diskSetInfo!=NULL){
        VixMntapi_FreeDiskSetInfo(diskSetInfo);
        printf("VixMntapi_FreeDiskSetInfo\n");
    }
    printf("dismount volumes?(y/n)");
    char dismountOption='y';
    scanf("%c",&dismountOption);
    if(dismountOption=='y'||dismountOption=='Y'){
        if (numVolumes!=0){
            for (int (i) = 0; (i) < numVolumes; ++(i)) {
                printf("dismount volume %d\n",i);
                VixMntapi_DismountVolume(volumeHandles[i],TRUE);
            }
        }
        if(diskSetHandle){
            vixError=VixMntapi_CloseDiskSet(diskSetHandle);
            printf("VixMntapi_CloseDiskSet\n");
        }
    }

    if (connection != NULL) {
        vixError = VixDiskLib_Disconnect(connection);
        printf("VixDiskLib_Disconnect\n");
    }
    VixMntapi_Exit();
    printf("VixMntapi_Exit\n");
    return 0;
}




/*
 *--------------------------------------------------------------------------
 *
 * LogFunc --
 *
 *      Callback for VixDiskLib Log messages.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------------------
 */
static void
LogFunc(const char *fmt, va_list args) {
    printf("Log: ");
    vprintf(fmt, args);
}

/*
 *--------------------------------------------------------------------------
 *
 * WarnFunc --
 *
 *      Callback for VixDiskLib Warning messages.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------------------
 */
static void
WarnFunc(const char *fmt, va_list args) {
    printf("Warning: ");
    vprintf(fmt, args);
}

/*
 *--------------------------------------------------------------------------
 *
 * PanicFunc --
 *
 *      Callback for VixDiskLib Panic messages.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------------------
 */
static void
PanicFunc(const char *fmt, va_list args) {
    printf("Panic: ");
    vprintf(fmt, args);
    exit(10);
}

猜你喜欢

转载自blog.csdn.net/Hilavergil/article/details/80273003