CLC通过CC调用NC
说明:这里主要通过RebootInstances为例,展示重启虚拟机流程,在看这个之前必须了解axis2c的客户端与服务端通信过程
CLC通过CC客户端与CC通信
在eucalyptus-2.0.1/cluster/目录下 cc-client-marshal.h/c为CC服务器的客户端文件,CLC通过调用这个文件中函数与CC通信,具体过程与CC和NC通信相似,在后面说明。
客户端连接到服务器
在这里我们将一个事件成为一个对象,如运行实例可以看着一个对象,重启实例可以看着一个对象。一个对象有多个值,在客户端与服务端通信时,要求每一个值都不为空,因为在客户端自己会检验是否为空,为空就会放弃这次通信,从而得不到任何响应。CC的客户端文件为cc-client-marshal,NC的客户端文件为client-marshal。
CC服务端响应CC客户端请求
axis2_skel_EucalyptusCC.c文件
CC的处理事件逻辑在eucalyptus-2.0.1/cluster/generated下的axis2_skel_EucalyptusCC.c文件,当CC服务端收到客户端的事件请求,如果收到RebootInstances,就开始响应请求,axis2_skel_EucalyptusCC.c中代码如下:
adb_RebootInstancesResponse_t* axis2_skel_EucalyptusCC_RebootInstances (const axutil_env_t *env , adb_RebootInstances_t* rebootInstances ) { return (RebootInstancesMarshal(rebootInstances, env)); }
|
转到CC的server-marshal.h文件
而RebootInstancesMarshal(rebootInstances, env))则定义在CC文件夹中的server-marshal.h文件中,代码如下
adb_RebootInstancesResponse_t* RebootInstancesMarshal (adb_RebootInstances_t* rebootInstances, const axutil_env_t *env) {
……
if (!DONOTHING) {
rc = doRebootInstances(&ccMeta, instIds, instIdsLen);
}
……
return(ret);
}
本段代码的主要部分为红色字体部分rc = doRebootInstances(&ccMeta, instIds, instIdsLen);
转到CC的handlers.h文件
通过这个调用相应目录下的handlers.h文件,doRebootInstances函数代码如下
int doRebootInstances(ncMetadata *meta, char **instIds, int instIdsLen) {
……
rc = ncClientCall(meta, timeout, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncRebootInstance", instId);
…….
return(0);
}
通过上面的rc = ncClientCall(meta, timeout, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncRebootInstance", instId);调用同一文件夹下的ncClientCall函数
#include "client-marshal.h"
int ncClientCall(ncMetadata *meta, int timeout, int ncLock, char *ncURL, char *ncOp, ...) {
……
logprintfl(EUCADEBUG, "ncClientCall(%s): called ncURL=%s timeout=%d/n", ncOp, ncURL, timeout);
rc = pipe(filedes);
if (rc) {
logprintfl(EUCAERROR, "ncClientCall(%s): cannot create pipe/n", ncOp);
return(1);
}
va_start(al, ncOp);
// grab the lock
sem_mywait(ncLock);
pid = fork();
if (!pid) {
ncStub *ncs;
close(filedes[0]);
ncs = ncStubCreate(ncURL, NULL, NULL);
if (config->use_wssec) {
rc = InitWSSEC(ncs->env, ncs->stub, config->policyFile);
}
logprintfl(EUCADEBUG, "/tncClientCall(%s): ppid=%d client calling '%s'/n", ncOp, getppid(), ncOp);
if (!strcmp(ncOp, "ncGetConsoleOutput")) {
……
} else if (!strcmp(ncOp, "ncAttachVolume")) {
……
} else if (!strcmp(ncOp, "ncDetachVolume")) {
……
} else if (!strcmp(ncOp, "ncPowerDown")) {
……
} else if (!strcmp(ncOp, "ncRebootInstance")) {
char *instId = va_arg(al, char *);
rc = ncRebootInstanceStub(ncs, meta, instId);
}
……
return(ret);
}
上面的ncStubCreate(ncURL, NULL, NULL);和 ncRebootInstanceStub(ncs, meta, instId);定义在头文件client-marshal.h中,这个是NC客户端文件
创建NC客户端
在上面ncStubCreate()函数是用来创建NC客户端的,每个客户端都有一个地址,这个地址是从CLC传过来的,在调用ncStubCreate()前的一系列操作都是得到要执行该操作的NC地址,即URL,然后通过调用axis2c的库函数
stub = axis2_stub_create_EucalyptusNC(env, client_home, (axis2_char_t *)uri);
创建该URL的NC客户端。
NC执行命令
创建到客户端后,调用该客户端的函数接口就可以让该NC执行我们想要的操作了。