Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
1eeceaa6
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
1eeceaa6
编写于
11月 25, 2008
作者:
D
Daniel P. Berrange
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Support domain lifecycle events for Xen (Ben Guthro & Daniel Berrange)
上级
b2dbfefc
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
1404 addition
and
70 deletion
+1404
-70
ChangeLog
ChangeLog
+21
-0
configure.in
configure.in
+16
-0
examples/domain-events/events-c/event-test.c
examples/domain-events/events-c/event-test.c
+1
-1
include/libvirt/virterror.h
include/libvirt/virterror.h
+1
-0
po/POTFILES.in
po/POTFILES.in
+1
-0
python/libvir.c
python/libvir.c
+2
-1
src/Makefile.am
src/Makefile.am
+5
-0
src/util.c
src/util.c
+4
-0
src/virterror.c
src/virterror.c
+3
-0
src/xen_inotify.c
src/xen_inotify.c
+458
-0
src/xen_inotify.h
src/xen_inotify.h
+31
-0
src/xen_unified.c
src/xen_unified.c
+197
-0
src/xen_unified.h
src/xen_unified.h
+63
-0
src/xm_internal.c
src/xm_internal.c
+131
-67
src/xm_internal.h
src/xm_internal.h
+6
-0
src/xs_internal.c
src/xs_internal.c
+412
-1
src/xs_internal.h
src/xs_internal.h
+52
-0
未找到文件。
ChangeLog
浏览文件 @
1eeceaa6
Tue Nov 25 10:43:40 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
Xen domain lifecycle events (Ben Guthro & Daniel Berrange)
* configure.in: Probe for inotify availability
* examples/domain-events/events-c/event-test.c: Default to NULL
connection URI to allow probing
* include/libvirt/virterror.h, src/virterror.c: Add error code
for xen inotify driver
* po/POTFILES.in: Add xen_inotify.c
* python/libvir.c: Add bogus const cast for python2.4 brokeness
* src/Makefile.am: Add xen_inotify.c
* src/util.c: Fix file descriptor leak in virRun
* src/xen_inotify.c, src/xen_inotify.h: Monitor /etc/xen and
/var/lib/xen/domains for new/old configs
* src/xen_unified.c, src/xen_unified.h: Wire in inotify driver
for events
* src/xm_internal.c, src/xm_internal.h: Refactor to allow inotify
monitoring of config files
* src/xs_internal.c, src/xs_internal.h: Use xenstore watch to
check for domain start/destroy events
Tue Nov 25 10:36:40 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/node_device_conf.c, src/node_device_conf.h,
...
...
configure.in
浏览文件 @
1eeceaa6
...
...
@@ -147,6 +147,8 @@ fi
dnl Allow to build without Xen, QEMU/KVM, test or remote driver
AC_ARG_WITH([xen],
[ --with-xen add XEN support (on)],[],[with_xen=yes])
AC_ARG_WITH([xen-inotify],
[ --with-xen-inotify add XEN inotify support (on)],[],[with_xen_inotify=yes])
AC_ARG_WITH([qemu],
[ --with-qemu add QEMU/KVM support (on)],[],[with_qemu=yes])
AC_ARG_WITH([uml],
...
...
@@ -334,6 +336,20 @@ AM_CONDITIONAL([WITH_XEN], [test "$with_xen" = "yes"])
AC_SUBST([XEN_CFLAGS])
AC_SUBST([XEN_LIBS])
dnl
dnl check for kernel headers required by xen_inotify
dnl
if test "$with_xen" != "yes"; then
with_xen_inotify=no
fi
if test "$with_xen_inotify" != "no"; then
AC_CHECK_HEADER([linux/inotify.h],[],[with_xen_inotify=no])
fi
if test "$with_xen_inotify" = "yes"; then
AC_DEFINE_UNQUOTED([WITH_XEN_INOTIFY], 1,[whether Xen inotify sub-driver is enabled])
fi
AM_CONDITIONAL([WITH_XEN_INOTIFY], [test "$with_xen_inotify" = "yes"])
dnl
dnl check for kernel headers required by src/bridge.c
dnl
...
...
examples/domain-events/events-c/event-test.c
浏览文件 @
1eeceaa6
...
...
@@ -308,7 +308,7 @@ int main(int argc, char **argv)
myEventRemoveTimeoutFunc
);
virConnectPtr
dconn
=
NULL
;
dconn
=
virConnectOpen
(
argv
[
1
]
?
argv
[
1
]
:
"qemu:///system"
);
dconn
=
virConnectOpen
(
argv
[
1
]
?
argv
[
1
]
:
NULL
);
if
(
!
dconn
)
{
printf
(
"error opening
\n
"
);
return
-
1
;
...
...
include/libvirt/virterror.h
浏览文件 @
1eeceaa6
...
...
@@ -60,6 +60,7 @@ typedef enum {
VIR_FROM_DOMAIN
,
/* Error from domain config */
VIR_FROM_UML
,
/* Error at the UML driver */
VIR_FROM_NODEDEV
,
/* Error from node device monitor */
VIR_FROM_XEN_INOTIFY
,
/* Error from xen inotify layer */
}
virErrorDomain
;
...
...
po/POTFILES.in
浏览文件 @
1eeceaa6
...
...
@@ -35,6 +35,7 @@ src/util.c
src/uuid.c
src/virsh.c
src/virterror.c
src/xen_inotify.c
src/xen_internal.c
src/xend_internal.c
src/xm_internal.c
...
...
python/libvir.c
浏览文件 @
1eeceaa6
...
...
@@ -1577,7 +1577,8 @@ getLibvirtModuleObject (void) {
return
libvirt_module
;
// PyImport_ImportModule returns a new reference
libvirt_module
=
PyImport_ImportModule
(
"libvirt"
);
/* Bogus (char *) cast for RHEL-5 python API brokenness */
libvirt_module
=
PyImport_ImportModule
((
char
*
)
"libvirt"
);
if
(
!
libvirt_module
)
{
#if DEBUG_ERROR
printf
(
"%s Error importing libvirt module
\n
"
,
__FUNCTION__
);
...
...
src/Makefile.am
浏览文件 @
1eeceaa6
...
...
@@ -101,6 +101,9 @@ XEN_DRIVER_SOURCES = \
xend_internal.c xend_internal.h
\
xm_internal.c xm_internal.h
\
xs_internal.c xs_internal.h
if
WITH_XEN_INOTIFY
XEN_DRIVER_SOURCES
+=
xen_inotify.c xen_inotify.h
endif
LXC_DRIVER_SOURCES
=
\
lxc_conf.c lxc_conf.h
\
...
...
@@ -189,6 +192,8 @@ libvirt_driver_la_SOURCES = \
libvirt_driver_la_CFLAGS
=
$(XEN_CFLAGS)
libvirt_driver_la_LDFLAGS
=
$(XEN_LIBS)
libvirt_driver_la_CFLAGS
=
$(XEN_CFLAGS)
if
WITH_TEST
if
WITH_DRIVER_MODULES
mod_LTLIBRARIES
+=
libvirt_driver_test.la
...
...
src/util.c
浏览文件 @
1eeceaa6
...
...
@@ -613,6 +613,10 @@ virRun(virConnectPtr conn,
VIR_FREE
(
outbuf
);
VIR_FREE
(
errbuf
);
VIR_FREE
(
argv_str
);
if
(
outfd
!=
-
1
)
close
(
outfd
);
if
(
errfd
!=
-
1
)
close
(
errfd
);
return
ret
;
}
...
...
src/virterror.c
浏览文件 @
1eeceaa6
...
...
@@ -262,6 +262,9 @@ virDefaultErrorFunc(virErrorPtr err)
case
VIR_FROM_XENSTORE
:
dom
=
"Xen Store "
;
break
;
case
VIR_FROM_XEN_INOTIFY
:
dom
=
"Xen Inotify "
;
break
;
case
VIR_FROM_DOM
:
dom
=
"Domain "
;
break
;
...
...
src/xen_inotify.c
0 → 100644
浏览文件 @
1eeceaa6
/*
* xen_inofify.c: Xen notification of xml file activity in the
* following dirs:
* /etc/xen
* /var/lib/xend/domains
*
* Copyright (C) 2008 VirtualIron
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Ben Guthro
*/
#include <config.h>
#include <dirent.h>
#include <sys/inotify.h>
#include "virterror_internal.h"
#include "datatypes.h"
#include "driver.h"
#include "memory.h"
#include "event.h"
#include "xen_unified.h"
#include "conf.h"
#include "domain_conf.h"
#include "xen_inotify.h"
#include "xend_internal.h"
#include "logging.h"
#include "uuid.h"
#include "xm_internal.h"
/* for xenXMDomainConfigParse */
#define virXenInotifyError(conn, code, fmt...) \
virReportErrorHelper(NULL, VIR_FROM_XEN_INOTIFY, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
#define LIBVIRTD_DOMAINS_DIR "/var/lib/xend/domains"
static
const
char
*
configDir
=
NULL
;
static
int
useXenConfigCache
=
0
;
static
xenUnifiedDomainInfoListPtr
configInfoList
=
NULL
;
struct
xenUnifiedDriver
xenInotifyDriver
=
{
xenInotifyOpen
,
/* open */
xenInotifyClose
,
/* close */
NULL
,
/* version */
NULL
,
/* hostname */
NULL
,
/* URI */
NULL
,
/* nodeGetInfo */
NULL
,
/* getCapabilities */
NULL
,
/* listDomains */
NULL
,
/* numOfDomains */
NULL
,
/* domainCreateLinux */
NULL
,
/* domainSuspend */
NULL
,
/* domainResume */
NULL
,
/* domainShutdown */
NULL
,
/* domainReboot */
NULL
,
/* domainDestroy */
NULL
,
/* domainGetOSType */
NULL
,
/* domainGetMaxMemory */
NULL
,
/* domainSetMaxMemory */
NULL
,
/* domainSetMemory */
NULL
,
/* domainGetInfo */
NULL
,
/* domainSave */
NULL
,
/* domainRestore */
NULL
,
/* domainCoreDump */
NULL
,
/* domainSetVcpus */
NULL
,
/* domainPinVcpu */
NULL
,
/* domainGetVcpus */
NULL
,
/* domainGetMaxVcpus */
NULL
,
/* listDefinedDomains */
NULL
,
/* numOfDefinedDomains */
NULL
,
/* domainCreate */
NULL
,
/* domainDefineXML */
NULL
,
/* domainUndefine */
NULL
,
/* domainAttachDevice */
NULL
,
/* domainDetachDevice */
NULL
,
/* domainGetAutostart */
NULL
,
/* domainSetAutostart */
NULL
,
/* domainGetSchedulerType */
NULL
,
/* domainGetSchedulerParameters */
NULL
,
/* domainSetSchedulerParameters */
};
static
virDomainPtr
xenInotifyXenCacheLookup
(
virConnectPtr
conn
,
const
char
*
filename
)
{
xenXMConfCachePtr
entry
;
virDomainPtr
dom
;
if
(
!
(
entry
=
virHashLookup
(
xenXMGetConfigCache
(),
filename
)))
{
DEBUG
(
"No config found for %s"
,
filename
);
return
NULL
;
}
if
(
!
(
dom
=
virGetDomain
(
conn
,
entry
->
def
->
name
,
(
unsigned
char
*
)
entry
->
def
->
uuid
)))
{
DEBUG0
(
"Error getting dom from def"
);
return
NULL
;
}
return
dom
;
}
static
virDomainPtr
xenInotifyXendDomainsDirLookup
(
virConnectPtr
conn
,
const
char
*
filename
)
{
int
i
;
virDomainPtr
dom
;
const
char
*
uuid_str
;
unsigned
char
uuid
[
VIR_UUID_BUFLEN
];
/* xend is managing domains. we will get
* a filename in the manner:
* /var/lib/xend/domains/<uuid>/
*/
uuid_str
=
filename
+
strlen
(
LIBVIRTD_DOMAINS_DIR
)
+
1
;
if
(
virUUIDParse
(
uuid_str
,
uuid
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"parsing uuid %s"
,
uuid_str
);
return
(
NULL
);
}
/* call directly into xend here, as driver may not yet
be set during open while we are building our
initial list of domains */
DEBUG
(
"Looking for dom with uuid: %s"
,
uuid_str
);
if
(
!
(
dom
=
xenDaemonLookupByUUID
(
conn
,
uuid
)))
{
/* If we are here, the domain has gone away.
search for, and create a domain from the stored
list info */
for
(
i
=
0
;
i
<
configInfoList
->
count
;
i
++
)
{
if
(
!
memcmp
(
uuid
,
configInfoList
->
doms
[
i
]
->
uuid
,
VIR_UUID_BUFLEN
))
{
if
(
!
(
dom
=
virGetDomain
(
conn
,
configInfoList
->
doms
[
i
]
->
name
,
configInfoList
->
doms
[
i
]
->
uuid
)))
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"finding dom for %s"
,
uuid_str
);
return
NULL
;
}
DEBUG0
(
"Found dom on list"
);
return
dom
;
}
}
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"finding dom on config list"
));
return
NULL
;
}
/* succeeded too find domain by uuid */
return
dom
;
}
static
virDomainPtr
xenInotifyDomainLookup
(
virConnectPtr
conn
,
const
char
*
filename
)
{
virDomainPtr
dom
;
virDomainInfo
info
;
dom
=
useXenConfigCache
?
xenInotifyXenCacheLookup
(
conn
,
filename
)
:
xenInotifyXendDomainsDirLookup
(
conn
,
filename
);
if
(
dom
)
{
if
(
(
useXenConfigCache
?
xenXMDomainGetInfo
(
dom
,
&
info
)
:
xenDaemonDomainGetInfo
(
dom
,
&
info
))
<
0
)
dom
->
id
=
-
1
;
else
dom
->
id
=
(
info
.
state
==
VIR_DOMAIN_SHUTOFF
)
?
-
1
:
dom
->
id
;
return
dom
;
}
return
NULL
;
}
static
int
xenInotifyXendDomainsDirRemoveEntry
(
virConnectPtr
conn
ATTRIBUTE_UNUSED
,
const
char
*
fname
)
{
const
char
*
uuidstr
=
fname
+
strlen
(
LIBVIRTD_DOMAINS_DIR
)
+
1
;
unsigned
char
uuid
[
VIR_UUID_BUFLEN
];
int
i
;
if
(
virUUIDParse
(
uuidstr
,
uuid
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"parsing uuid %s"
,
uuidstr
);
return
-
1
;
}
/* match and remove on uuid */
for
(
i
=
0
;
i
<
configInfoList
->
count
;
i
++
)
{
if
(
!
memcmp
(
uuid
,
configInfoList
->
doms
[
i
]
->
uuid
,
VIR_UUID_BUFLEN
))
{
VIR_FREE
(
configInfoList
->
doms
[
i
]
->
name
);
VIR_FREE
(
configInfoList
->
doms
[
i
]);
if
(
i
<
(
configInfoList
->
count
-
1
))
memmove
(
configInfoList
->
doms
+
i
,
configInfoList
->
doms
+
i
+
1
,
sizeof
(
*
(
configInfoList
->
doms
))
*
(
configInfoList
->
count
-
(
i
+
1
)));
if
(
VIR_REALLOC_N
(
configInfoList
->
doms
,
configInfoList
->
count
-
1
)
<
0
)
{
;
/* Failure to reduce memory allocation isn't fatal */
}
configInfoList
->
count
--
;
return
0
;
}
}
return
-
1
;
}
static
int
xenInotifyXendDomainsDirAddEntry
(
virConnectPtr
conn
,
const
char
*
fname
)
{
virDomainPtr
dom
=
xenInotifyDomainLookup
(
conn
,
fname
);
if
(
!
dom
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"Error looking up domain"
));
return
-
1
;
}
if
(
xenUnifiedAddDomainInfo
(
configInfoList
,
dom
->
id
,
dom
->
name
,
dom
->
uuid
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"Error adding file to config cache"
));
virUnrefDomain
(
dom
);
return
-
1
;
}
virUnrefDomain
(
dom
);
return
0
;
}
static
int
xenInotifyRemoveDomainConfigInfo
(
virConnectPtr
conn
,
const
char
*
fname
)
{
return
useXenConfigCache
?
xenXMConfigCacheRemoveFile
(
conn
,
fname
)
:
xenInotifyXendDomainsDirRemoveEntry
(
conn
,
fname
);
}
static
int
xenInotifyAddDomainConfigInfo
(
virConnectPtr
conn
,
const
char
*
fname
)
{
return
useXenConfigCache
?
xenXMConfigCacheAddFile
(
conn
,
fname
)
:
xenInotifyXendDomainsDirAddEntry
(
conn
,
fname
);
}
static
void
xenInotifyEvent
(
int
watch
ATTRIBUTE_UNUSED
,
int
fd
,
int
events
ATTRIBUTE_UNUSED
,
void
*
data
)
{
char
buf
[
1024
];
char
fname
[
1024
];
struct
inotify_event
*
e
;
int
got
;
char
*
tmp
,
*
name
;
virConnectPtr
conn
=
(
virConnectPtr
)
data
;
xenUnifiedPrivatePtr
priv
=
NULL
;
virDomainPtr
dom
=
NULL
;
DEBUG0
(
"got inotify event"
);
if
(
conn
&&
conn
->
privateData
)
{
priv
=
conn
->
privateData
;
}
else
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"conn, or private data is NULL"
));
return
;
}
reread:
got
=
read
(
fd
,
buf
,
sizeof
(
buf
));
if
(
got
==
-
1
)
{
if
(
errno
==
EINTR
)
goto
reread
;
return
;
}
tmp
=
buf
;
while
(
got
)
{
if
(
got
<
sizeof
(
struct
inotify_event
))
return
;
/* bad */
e
=
(
struct
inotify_event
*
)
tmp
;
tmp
+=
sizeof
(
struct
inotify_event
);
got
-=
sizeof
(
struct
inotify_event
);
if
(
got
<
e
->
len
)
return
;
tmp
+=
e
->
len
;
got
-=
e
->
len
;
name
=
(
char
*
)
&
(
e
->
name
);
snprintf
(
fname
,
1024
,
"%s/%s"
,
configDir
,
name
);
if
(
e
->
mask
&
(
IN_DELETE
|
IN_MOVED_FROM
))
{
if
(
!
(
dom
=
xenInotifyDomainLookup
(
conn
,
fname
)))
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"looking up dom"
));
continue
;
}
xenUnifiedDomainEventDispatch
(
conn
->
privateData
,
dom
,
VIR_DOMAIN_EVENT_UNDEFINED
,
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED
);
if
(
xenInotifyRemoveDomainConfigInfo
(
conn
,
fname
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"Error adding file to config cache"
));
return
;
}
}
else
if
(
e
->
mask
&
(
IN_CREATE
|
IN_CLOSE_WRITE
|
IN_MOVED_TO
)
)
{
if
(
xenInotifyAddDomainConfigInfo
(
conn
,
fname
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"Error adding file to config cache"
));
return
;
}
if
(
!
(
dom
=
xenInotifyDomainLookup
(
conn
,
fname
)))
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"looking up dom"
));
continue
;
}
xenUnifiedDomainEventDispatch
(
conn
->
privateData
,
dom
,
VIR_DOMAIN_EVENT_DEFINED
,
VIR_DOMAIN_EVENT_DEFINED_ADDED
);
}
}
}
/**
* xenInotifyOpen:
* @conn: pointer to the connection block
* @name: URL for the target, NULL for local
* @flags: combination of virDrvOpenFlag(s)
*
* Connects and starts listening for inotify events
*
* Returns 0 or -1 in case of error.
*/
int
xenInotifyOpen
(
virConnectPtr
conn
ATTRIBUTE_UNUSED
,
virConnectAuthPtr
auth
ATTRIBUTE_UNUSED
,
int
flags
ATTRIBUTE_UNUSED
)
{
DIR
*
dh
;
struct
dirent
*
ent
;
char
path
[
PATH_MAX
];
xenUnifiedPrivatePtr
priv
=
(
xenUnifiedPrivatePtr
)
conn
->
privateData
;
if
(
priv
->
xendConfigVersion
<=
2
)
{
/* /etc/xen */
configDir
=
xenXMGetConfigDir
();
useXenConfigCache
=
1
;
}
else
{
/* /var/lib/xend/domains/<uuid>/config.sxp */
configDir
=
LIBVIRTD_DOMAINS_DIR
;
useXenConfigCache
=
0
;
if
(
VIR_ALLOC
(
configInfoList
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"failed to allocate configInfoList"
));
return
-
1
;
}
/* populate initial list */
if
(
!
(
dh
=
opendir
(
configDir
)))
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
strerror
(
errno
));
return
-
1
;
}
while
((
ent
=
readdir
(
dh
)))
{
if
(
STRPREFIX
(
ent
->
d_name
,
"."
))
continue
;
/* Build the full file path */
if
((
strlen
(
configDir
)
+
1
+
strlen
(
ent
->
d_name
)
+
1
)
>
PATH_MAX
)
continue
;
strcpy
(
path
,
configDir
);
strcat
(
path
,
"/"
);
strcat
(
path
,
ent
->
d_name
);
if
(
xenInotifyAddDomainConfigInfo
(
conn
,
path
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"Error adding file to config list"
));
return
-
1
;
}
}
}
if
((
priv
->
inotifyFD
=
inotify_init
())
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"initializing inotify"
));
return
-
1
;
}
DEBUG
(
"Adding a watch on %s"
,
configDir
);
if
(
inotify_add_watch
(
priv
->
inotifyFD
,
configDir
,
IN_CREATE
|
IN_CLOSE_WRITE
|
IN_DELETE
|
IN_MOVED_TO
|
IN_MOVED_FROM
)
<
0
)
{
virXenInotifyError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"adding watch on %s"
,
_
(
configDir
));
return
-
1
;
}
DEBUG0
(
"Building initial config cache"
);
if
(
useXenConfigCache
&&
xenXMConfigCacheRefresh
(
conn
)
<
0
)
{
DEBUG
(
"Failed to enable XM config cache %s"
,
conn
->
err
.
message
);
return
-
1
;
}
DEBUG0
(
"Registering with event loop"
);
/* Add the handle for monitoring */
if
((
priv
->
inotifyWatch
=
virEventAddHandle
(
priv
->
inotifyFD
,
VIR_EVENT_HANDLE_READABLE
,
xenInotifyEvent
,
conn
,
NULL
))
<
0
)
{
DEBUG0
(
"Failed to add inotify handle, disabling events"
);
}
conn
->
refs
++
;
return
0
;
}
/**
* xenInotifyClose:
* @conn: pointer to the connection block
*
* Close and stop listening for inotify events
*
* Returns 0 in case of success or -1 in case of error.
*/
int
xenInotifyClose
(
virConnectPtr
conn
)
{
xenUnifiedPrivatePtr
priv
=
(
xenUnifiedPrivatePtr
)
conn
->
privateData
;
if
(
configInfoList
)
xenUnifiedDomainInfoListFree
(
configInfoList
);
if
(
priv
->
inotifyWatch
!=
-
1
)
virEventRemoveHandle
(
priv
->
inotifyWatch
);
close
(
priv
->
inotifyFD
);
virUnrefConnect
(
conn
);
return
0
;
}
src/xen_inotify.h
0 → 100644
浏览文件 @
1eeceaa6
/*
* xen_inofify.h: Xen notification of xml files
*
* Copyright (C) 2008 VirtualIron
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Ben Guthro
*/
#ifndef __VIR_XEN_INOTIFY_H__
#define __VIR_XEN_INOTIFY_H__
#include "internal.h"
extern
struct
xenUnifiedDriver
xenInotifyDriver
;
int
xenInotifyOpen
(
virConnectPtr
conn
,
virConnectAuthPtr
auth
,
int
flags
);
int
xenInotifyClose
(
virConnectPtr
conn
);
#endif
src/xen_unified.c
浏览文件 @
1eeceaa6
...
...
@@ -37,6 +37,9 @@
#include "xend_internal.h"
#include "xs_internal.h"
#include "xm_internal.h"
#if WITH_XEN_INOTIFY
#include "xen_inotify.h"
#endif
#include "xml.h"
#include "util.h"
#include "memory.h"
...
...
@@ -57,6 +60,9 @@ static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
[
XEN_UNIFIED_XEND_OFFSET
]
=
&
xenDaemonDriver
,
[
XEN_UNIFIED_XS_OFFSET
]
=
&
xenStoreDriver
,
[
XEN_UNIFIED_XM_OFFSET
]
=
&
xenXMDriver
,
#if WITH_XEN_INOTIFY
[
XEN_UNIFIED_INOTIFY_OFFSET
]
=
&
xenInotifyDriver
,
#endif
};
#define xenUnifiedError(conn, code, fmt...) \
...
...
@@ -223,6 +229,7 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
{
int
i
,
ret
=
VIR_DRV_OPEN_DECLINED
;
xenUnifiedPrivatePtr
priv
;
virDomainEventCallbackListPtr
cbList
;
if
(
conn
->
uri
==
NULL
)
{
if
(
!
xenUnifiedProbe
())
...
...
@@ -260,6 +267,13 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
}
conn
->
privateData
=
priv
;
/* Allocate callback list */
if
(
VIR_ALLOC
(
cbList
)
<
0
)
{
xenUnifiedError
(
NULL
,
VIR_ERR_NO_MEMORY
,
"allocating callback list"
);
return
VIR_DRV_OPEN_ERROR
;
}
priv
->
domainEventCallbacks
=
cbList
;
priv
->
handle
=
-
1
;
priv
->
xendConfigVersion
=
-
1
;
priv
->
type
=
-
1
;
...
...
@@ -333,6 +347,15 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
goto
fail
;
}
#if WITH_XEN_INOTIFY
DEBUG0
(
"Trying Xen inotify sub-driver"
);
if
(
drivers
[
XEN_UNIFIED_INOTIFY_OFFSET
]
->
open
(
conn
,
auth
,
flags
)
==
VIR_DRV_OPEN_SUCCESS
)
{
DEBUG0
(
"Activated Xen inotify sub-driver"
);
priv
->
opened
[
XEN_UNIFIED_INOTIFY_OFFSET
]
=
1
;
}
#endif
return
VIR_DRV_OPEN_SUCCESS
;
fail:
...
...
@@ -357,6 +380,8 @@ xenUnifiedClose (virConnectPtr conn)
int
i
;
virCapabilitiesFree
(
priv
->
caps
);
virDomainEventCallbackListFree
(
priv
->
domainEventCallbacks
);
for
(
i
=
0
;
i
<
XEN_UNIFIED_NR_DRIVERS
;
++
i
)
if
(
priv
->
opened
[
i
]
&&
drivers
[
i
]
->
close
)
(
void
)
drivers
[
i
]
->
close
(
conn
);
...
...
@@ -1292,6 +1317,40 @@ xenUnifiedNodeGetFreeMemory (virConnectPtr conn)
return
(
0
);
}
static
int
xenUnifiedDomainEventRegister
(
virConnectPtr
conn
,
void
*
callback
,
void
*
opaque
,
void
(
*
freefunc
)(
void
*
))
{
GET_PRIVATE
(
conn
);
if
(
priv
->
xsWatch
==
-
1
)
{
xenUnifiedError
(
conn
,
VIR_ERR_NO_SUPPORT
,
__FUNCTION__
);
return
-
1
;
}
conn
->
refs
++
;
return
virDomainEventCallbackListAdd
(
conn
,
priv
->
domainEventCallbacks
,
callback
,
opaque
,
freefunc
);
}
static
int
xenUnifiedDomainEventDeregister
(
virConnectPtr
conn
,
void
*
callback
)
{
int
ret
;
GET_PRIVATE
(
conn
);
if
(
priv
->
xsWatch
==
-
1
)
{
xenUnifiedError
(
conn
,
VIR_ERR_NO_SUPPORT
,
__FUNCTION__
);
return
-
1
;
}
ret
=
virDomainEventCallbackListRemove
(
conn
,
priv
->
domainEventCallbacks
,
callback
);
virUnrefConnect
(
conn
);
return
ret
;
}
/*----- Register with libvirt.c, and initialise Xen drivers. -----*/
#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 + \
...
...
@@ -1356,6 +1415,8 @@ static virDriver xenUnifiedDriver = {
.
domainBlockPeek
=
xenUnifiedDomainBlockPeek
,
.
nodeGetCellsFreeMemory
=
xenUnifiedNodeGetCellsFreeMemory
,
.
getFreeMemory
=
xenUnifiedNodeGetFreeMemory
,
.
domainEventRegister
=
xenUnifiedDomainEventRegister
,
.
domainEventDeregister
=
xenUnifiedDomainEventDeregister
,
};
/**
...
...
@@ -1375,3 +1436,139 @@ xenRegister (void)
return
virRegisterDriver
(
&
xenUnifiedDriver
);
}
/**
* xenUnifiedDomainInfoListFree:
*
* Free the Domain Info List
*/
void
xenUnifiedDomainInfoListFree
(
xenUnifiedDomainInfoListPtr
list
)
{
int
i
;
for
(
i
=
0
;
i
<
list
->
count
;
i
++
)
{
VIR_FREE
(
list
->
doms
[
i
]
->
name
);
VIR_FREE
(
list
->
doms
[
i
]);
}
VIR_FREE
(
list
);
}
/**
* xenUnifiedAddDomainInfo:
*
* Add name and uuid to the domain info list
*
* Returns: 0 on success, -1 on failure
*/
int
xenUnifiedAddDomainInfo
(
xenUnifiedDomainInfoListPtr
list
,
int
id
,
char
*
name
,
unsigned
char
*
uuid
)
{
xenUnifiedDomainInfoPtr
info
;
int
n
;
/* check if we already have this callback on our list */
for
(
n
=
0
;
n
<
list
->
count
;
n
++
)
{
if
(
STREQ
(
list
->
doms
[
n
]
->
name
,
name
)
&&
!
memcmp
(
list
->
doms
[
n
]
->
uuid
,
uuid
,
VIR_UUID_BUFLEN
))
{
DEBUG0
(
"WARNING: dom already tracked"
);
return
-
1
;
}
}
if
(
VIR_ALLOC
(
info
)
<
0
)
goto
memory_error
;
if
(
!
(
info
->
name
=
strdup
(
name
)))
goto
memory_error
;
memcpy
(
info
->
uuid
,
uuid
,
VIR_UUID_BUFLEN
);
info
->
id
=
id
;
/* Make space on list */
n
=
list
->
count
;
if
(
VIR_REALLOC_N
(
list
->
doms
,
n
+
1
)
<
0
)
{
goto
memory_error
;
}
list
->
doms
[
n
]
=
info
;
list
->
count
++
;
return
0
;
memory_error:
xenUnifiedError
(
NULL
,
VIR_ERR_NO_MEMORY
,
"allocating domain info"
);
if
(
info
)
VIR_FREE
(
info
->
name
);
VIR_FREE
(
info
);
return
-
1
;
}
/**
* xenUnifiedRemoveDomainInfo:
*
* Removes name and uuid to the domain info list
*
* Returns: 0 on success, -1 on failure
*/
int
xenUnifiedRemoveDomainInfo
(
xenUnifiedDomainInfoListPtr
list
,
int
id
,
char
*
name
,
unsigned
char
*
uuid
)
{
int
i
;
for
(
i
=
0
;
i
<
list
->
count
;
i
++
)
{
if
(
list
->
doms
[
i
]
->
id
==
id
&&
STREQ
(
list
->
doms
[
i
]
->
name
,
name
)
&&
!
memcmp
(
list
->
doms
[
i
]
->
uuid
,
uuid
,
VIR_UUID_BUFLEN
))
{
VIR_FREE
(
list
->
doms
[
i
]
->
name
);
VIR_FREE
(
list
->
doms
[
i
]);
if
(
i
<
(
list
->
count
-
1
))
memmove
(
list
->
doms
+
i
,
list
->
doms
+
i
+
1
,
sizeof
(
*
(
list
->
doms
))
*
(
list
->
count
-
(
i
+
1
)));
if
(
VIR_REALLOC_N
(
list
->
doms
,
list
->
count
-
1
)
<
0
)
{
;
/* Failure to reduce memory allocation isn't fatal */
}
list
->
count
--
;
return
0
;
}
}
return
-
1
;
}
/**
* xenUnifiedDomainEventDispatch:
*
* Dispatch domain events to registered callbacks
*
*/
void
xenUnifiedDomainEventDispatch
(
xenUnifiedPrivatePtr
priv
,
virDomainPtr
dom
,
int
event
,
int
detail
)
{
int
i
;
virDomainEventCallbackListPtr
cbList
;
if
(
!
priv
)
return
;
cbList
=
priv
->
domainEventCallbacks
;
if
(
!
cbList
)
return
;
for
(
i
=
0
;
i
<
cbList
->
count
;
i
++
)
{
if
(
cbList
->
callbacks
[
i
]
&&
cbList
->
callbacks
[
i
]
->
cb
)
{
if
(
dom
)
{
DEBUG
(
"Dispatching callback %p %p event %d"
,
cbList
->
callbacks
[
i
],
cbList
->
callbacks
[
i
]
->
cb
,
event
);
cbList
->
callbacks
[
i
]
->
cb
(
cbList
->
callbacks
[
i
]
->
conn
,
dom
,
event
,
detail
,
cbList
->
callbacks
[
i
]
->
opaque
);
}
}
}
}
src/xen_unified.h
浏览文件 @
1eeceaa6
...
...
@@ -14,6 +14,12 @@
#include "internal.h"
#include "capabilities.h"
#include "driver.h"
#include "domain_conf.h"
#include "xs_internal.h"
#if WITH_XEN_INOTIFY
#include "xen_inotify.h"
#endif
#include "domain_event.h"
#ifndef HAVE_WINSOCK2_H
#include <sys/un.h>
...
...
@@ -29,7 +35,13 @@ extern int xenRegister (void);
#define XEN_UNIFIED_XEND_OFFSET 2
#define XEN_UNIFIED_XS_OFFSET 3
#define XEN_UNIFIED_XM_OFFSET 4
#if WITH_XEN_INOTIFY
#define XEN_UNIFIED_INOTIFY_OFFSET 5
#define XEN_UNIFIED_NR_DRIVERS 6
#else
#define XEN_UNIFIED_NR_DRIVERS 5
#endif
#define MIN_XEN_GUEST_SIZE 64
/* 64 megabytes */
...
...
@@ -85,6 +97,33 @@ struct xenUnifiedDriver {
virDrvDomainSetSchedulerParameters
domainSetSchedulerParameters
;
};
typedef
struct
xenXMConfCache
*
xenXMConfCachePtr
;
typedef
struct
xenXMConfCache
{
time_t
refreshedAt
;
char
filename
[
PATH_MAX
];
virDomainDefPtr
def
;
}
xenXMConfCache
;
/* xenUnifiedDomainInfoPtr:
* The minimal state we have about active domains
* This is the minmal info necessary to still get a
* virDomainPtr when the domain goes away
*/
struct
_xenUnifiedDomainInfo
{
int
id
;
char
*
name
;
unsigned
char
uuid
[
VIR_UUID_BUFLEN
];
};
typedef
struct
_xenUnifiedDomainInfo
xenUnifiedDomainInfo
;
typedef
xenUnifiedDomainInfo
*
xenUnifiedDomainInfoPtr
;
struct
_xenUnifiedDomainInfoList
{
unsigned
int
count
;
xenUnifiedDomainInfoPtr
*
doms
;
};
typedef
struct
_xenUnifiedDomainInfoList
xenUnifiedDomainInfoList
;
typedef
xenUnifiedDomainInfoList
*
xenUnifiedDomainInfoListPtr
;
/* xenUnifiedPrivatePtr:
*
* Per-connection private data, stored in conn->privateData. All Xen
...
...
@@ -113,6 +152,19 @@ struct _xenUnifiedPrivate {
* xen_unified.c.
*/
int
opened
[
XEN_UNIFIED_NR_DRIVERS
];
/* A list of xenstore watches */
xenStoreWatchListPtr
xsWatchList
;
int
xsWatch
;
/* An list of callbacks */
virDomainEventCallbackListPtr
domainEventCallbacks
;
#if WITH_XEN_INOTIFY
/* The inotify fd */
int
inotifyFD
;
int
inotifyWatch
;
#endif
};
typedef
struct
_xenUnifiedPrivate
*
xenUnifiedPrivatePtr
;
...
...
@@ -122,4 +174,15 @@ int xenNbCells(virConnectPtr conn);
int
xenNbCpus
(
virConnectPtr
conn
);
char
*
xenDomainUsedCpus
(
virDomainPtr
dom
);
void
xenUnifiedDomainInfoListFree
(
xenUnifiedDomainInfoListPtr
info
);
int
xenUnifiedAddDomainInfo
(
xenUnifiedDomainInfoListPtr
info
,
int
id
,
char
*
name
,
unsigned
char
*
uuid
);
int
xenUnifiedRemoveDomainInfo
(
xenUnifiedDomainInfoListPtr
info
,
int
id
,
char
*
name
,
unsigned
char
*
uuid
);
void
xenUnifiedDomainEventDispatch
(
xenUnifiedPrivatePtr
priv
,
virDomainPtr
dom
,
int
event
,
int
detail
);
#endif
/* __VIR_XEN_UNIFIED_H__ */
src/xm_internal.c
浏览文件 @
1eeceaa6
...
...
@@ -45,6 +45,8 @@
#include "uuid.h"
#include "util.h"
#include "memory.h"
#include "logging.h"
/* The true Xen limit varies but so far is always way
less than 1024, which is the Linux kernel limit according
...
...
@@ -54,13 +56,6 @@
static
int
xenXMConfigSetString
(
virConfPtr
conf
,
const
char
*
setting
,
const
char
*
str
);
typedef
struct
xenXMConfCache
*
xenXMConfCachePtr
;
typedef
struct
xenXMConfCache
{
time_t
refreshedAt
;
char
filename
[
PATH_MAX
];
virDomainDefPtr
def
;
}
xenXMConfCache
;
static
char
configDir
[
PATH_MAX
];
/* Config file name to config object */
static
virHashTablePtr
configCache
=
NULL
;
...
...
@@ -124,6 +119,14 @@ struct xenUnifiedDriver xenXMDriver = {
NULL
,
/* domainSetSchedulerParameters */
};
virHashTablePtr
xenXMGetConfigCache
(
void
)
{
return
configCache
;
}
char
*
xenXMGetConfigDir
(
void
)
{
return
configDir
;
}
#define xenXMError(conn, code, fmt...) \
virReportErrorHelper(conn, VIR_FROM_XENXM, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
...
...
@@ -371,13 +374,121 @@ xenXMConfigSaveFile(virConnectPtr conn, const char *filename, virDomainDefPtr de
return
ret
;
}
int
xenXMConfigCacheRemoveFile
(
virConnectPtr
conn
ATTRIBUTE_UNUSED
,
const
char
*
filename
)
{
xenXMConfCachePtr
entry
;
entry
=
virHashLookup
(
configCache
,
filename
);
if
(
!
entry
)
{
DEBUG
(
"No config entry for %s"
,
filename
);
return
0
;
}
virHashRemoveEntry
(
nameConfigMap
,
entry
->
def
->
name
,
NULL
);
virHashRemoveEntry
(
configCache
,
filename
,
xenXMConfigFree
);
DEBUG
(
"Removed %s %s"
,
entry
->
def
->
name
,
filename
);
return
0
;
}
int
xenXMConfigCacheAddFile
(
virConnectPtr
conn
,
const
char
*
filename
)
{
xenXMConfCachePtr
entry
;
struct
stat
st
;
int
newborn
=
0
;
time_t
now
=
time
(
NULL
);
DEBUG
(
"Adding file %s"
,
filename
);
/* Get modified time */
if
((
stat
(
filename
,
&
st
)
<
0
))
{
xenXMError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"cannot stat %s: %s"
,
filename
,
strerror
(
errno
));
return
-
1
;
}
/* Ignore zero length files, because inotify fires before
any content has actually been created */
if
(
st
.
st_size
==
0
)
{
DEBUG
(
"Ignoring zero length file %s"
,
filename
);
return
-
1
;
}
/* If we already have a matching entry and it is not
modified, then carry on to next one*/
if
((
entry
=
virHashLookup
(
configCache
,
filename
)))
{
char
*
nameowner
;
if
(
entry
->
refreshedAt
>=
st
.
st_mtime
)
{
entry
->
refreshedAt
=
now
;
/* return success if up-to-date */
return
0
;
}
/* If we currently own the name, then release it and
re-acquire it later - just in case it was renamed */
nameowner
=
(
char
*
)
virHashLookup
(
nameConfigMap
,
entry
->
def
->
name
);
if
(
nameowner
&&
STREQ
(
nameowner
,
filename
))
{
virHashRemoveEntry
(
nameConfigMap
,
entry
->
def
->
name
,
NULL
);
}
/* Clear existing config entry which needs refresh */
virDomainDefFree
(
entry
->
def
);
entry
->
def
=
NULL
;
}
else
{
/* Completely new entry */
newborn
=
1
;
if
(
VIR_ALLOC
(
entry
)
<
0
)
{
xenXMError
(
conn
,
VIR_ERR_NO_MEMORY
,
"%s"
,
strerror
(
errno
));
return
-
1
;
}
memcpy
(
entry
->
filename
,
filename
,
PATH_MAX
);
}
entry
->
refreshedAt
=
now
;
if
(
!
(
entry
->
def
=
xenXMConfigReadFile
(
conn
,
entry
->
filename
)))
{
DEBUG
(
"Failed to read %s"
,
entry
->
filename
);
if
(
!
newborn
)
virHashRemoveEntry
(
configCache
,
filename
,
NULL
);
VIR_FREE
(
entry
);
return
-
1
;
}
/* If its a completely new entry, it must be stuck into
the cache (refresh'd entries are already registered) */
if
(
newborn
)
{
if
(
virHashAddEntry
(
configCache
,
entry
->
filename
,
entry
)
<
0
)
{
virDomainDefFree
(
entry
->
def
);
VIR_FREE
(
entry
);
xenXMError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"xenXMConfigCacheRefresh: virHashAddEntry"
));
return
-
1
;
}
}
/* See if we need to map this config file in as the primary owner
* of the domain in question
*/
if
(
!
virHashLookup
(
nameConfigMap
,
entry
->
def
->
name
))
{
if
(
virHashAddEntry
(
nameConfigMap
,
entry
->
def
->
name
,
entry
->
filename
)
<
0
)
{
virHashRemoveEntry
(
configCache
,
filename
,
NULL
);
virDomainDefFree
(
entry
->
def
);
VIR_FREE
(
entry
);
}
}
DEBUG
(
"Added config %s %s"
,
entry
->
def
->
name
,
filename
);
return
0
;
}
/* This method is called by various methods to scan /etc/xen
(or whatever directory was set by LIBVIRT_XM_CONFIG_DIR
environment variable) and process any domain configs. It
has rate-limited so never rescans more frequently than
once every X seconds */
static
int
xenXMConfigCacheRefresh
(
virConnectPtr
conn
)
{
int
xenXMConfigCacheRefresh
(
virConnectPtr
conn
)
{
DIR
*
dh
;
struct
dirent
*
ent
;
time_t
now
=
time
(
NULL
);
...
...
@@ -401,9 +512,7 @@ static int xenXMConfigCacheRefresh (virConnectPtr conn) {
}
while
((
ent
=
readdir
(
dh
)))
{
xenXMConfCachePtr
entry
;
struct
stat
st
;
int
newborn
=
0
;
char
path
[
PATH_MAX
];
/*
...
...
@@ -447,62 +556,8 @@ static int xenXMConfigCacheRefresh (virConnectPtr conn) {
/* If we already have a matching entry and it is not
modified, then carry on to next one*/
if
((
entry
=
virHashLookup
(
configCache
,
path
)))
{
char
*
nameowner
;
if
(
entry
->
refreshedAt
>=
st
.
st_mtime
)
{
entry
->
refreshedAt
=
now
;
continue
;
}
/* If we currently own the name, then release it and
re-acquire it later - just in case it was renamed */
nameowner
=
(
char
*
)
virHashLookup
(
nameConfigMap
,
entry
->
def
->
name
);
if
(
nameowner
&&
STREQ
(
nameowner
,
path
))
{
virHashRemoveEntry
(
nameConfigMap
,
entry
->
def
->
name
,
NULL
);
}
/* Clear existing config entry which needs refresh */
virDomainDefFree
(
entry
->
def
);
entry
->
def
=
NULL
;
}
else
{
/* Completely new entry */
newborn
=
1
;
if
(
VIR_ALLOC
(
entry
)
<
0
)
{
xenXMError
(
conn
,
VIR_ERR_NO_MEMORY
,
"%s"
,
strerror
(
errno
));
goto
cleanup
;
}
memcpy
(
entry
->
filename
,
path
,
PATH_MAX
);
}
entry
->
refreshedAt
=
now
;
if
(
!
(
entry
->
def
=
xenXMConfigReadFile
(
conn
,
entry
->
filename
)))
{
if
(
!
newborn
)
virHashRemoveEntry
(
configCache
,
path
,
NULL
);
VIR_FREE
(
entry
);
continue
;
}
/* If its a completely new entry, it must be stuck into
the cache (refresh'd entries are already registered) */
if
(
newborn
)
{
if
(
virHashAddEntry
(
configCache
,
entry
->
filename
,
entry
)
<
0
)
{
virDomainDefFree
(
entry
->
def
);
VIR_FREE
(
entry
);
xenXMError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"xenXMConfigCacheRefresh: virHashAddEntry"
));
goto
cleanup
;
}
}
/* See if we need to map this config file in as the primary owner
* of the domain in question
*/
if
(
!
virHashLookup
(
nameConfigMap
,
entry
->
def
->
name
))
{
if
(
virHashAddEntry
(
nameConfigMap
,
entry
->
def
->
name
,
entry
->
filename
)
<
0
)
{
virHashRemoveEntry
(
configCache
,
ent
->
d_name
,
NULL
);
virDomainDefFree
(
entry
->
def
);
VIR_FREE
(
entry
);
}
if
(
xenXMConfigCacheAddFile
(
conn
,
path
)
<
0
)
{
/* Ignoring errors, since alot of stuff goes wrong in /etc/xen */
}
}
...
...
@@ -513,7 +568,6 @@ static int xenXMConfigCacheRefresh (virConnectPtr conn) {
virHashRemoveSet
(
configCache
,
xenXMConfigReaper
,
xenXMConfigFree
,
(
const
void
*
)
&
now
);
ret
=
0
;
cleanup:
if
(
dh
)
closedir
(
dh
);
...
...
@@ -1503,8 +1557,10 @@ virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname) {
return
(
NULL
);
}
#ifndef WITH_XEN_INOTIFY
if
(
xenXMConfigCacheRefresh
(
conn
)
<
0
)
return
(
NULL
);
#endif
if
(
!
(
filename
=
virHashLookup
(
nameConfigMap
,
domname
)))
return
(
NULL
);
...
...
@@ -1555,8 +1611,10 @@ virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
return
(
NULL
);
}
#ifndef WITH_XEN_INOTIFY
if
(
xenXMConfigCacheRefresh
(
conn
)
<
0
)
return
(
NULL
);
#endif
if
(
!
(
entry
=
virHashSearch
(
configCache
,
xenXMDomainSearchForUUID
,
(
const
void
*
)
uuid
)))
{
return
(
NULL
);
...
...
@@ -2208,8 +2266,10 @@ virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) {
if
(
conn
->
flags
&
VIR_CONNECT_RO
)
return
(
NULL
);
#ifndef WITH_XEN_INOTIFY
if
(
xenXMConfigCacheRefresh
(
conn
)
<
0
)
return
(
NULL
);
#endif
if
(
!
(
def
=
virDomainDefParseString
(
conn
,
priv
->
caps
,
xml
)))
return
(
NULL
);
...
...
@@ -2376,8 +2436,10 @@ int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames
return
(
-
1
);
}
#ifndef WITH_XEN_INOTIFY
if
(
xenXMConfigCacheRefresh
(
conn
)
<
0
)
return
(
-
1
);
#endif
if
(
maxnames
>
virHashSize
(
configCache
))
maxnames
=
virHashSize
(
configCache
);
...
...
@@ -2401,8 +2463,10 @@ int xenXMNumOfDefinedDomains(virConnectPtr conn) {
return
(
-
1
);
}
#ifndef WITH_XEN_INOTIFY
if
(
xenXMConfigCacheRefresh
(
conn
)
<
0
)
return
(
-
1
);
#endif
return
virHashSize
(
nameConfigMap
);
}
...
...
src/xm_internal.h
浏览文件 @
1eeceaa6
...
...
@@ -32,6 +32,12 @@
extern
struct
xenUnifiedDriver
xenXMDriver
;
int
xenXMInit
(
void
);
virHashTablePtr
xenXMGetConfigCache
(
void
);
char
*
xenXMGetConfigDir
(
void
);
int
xenXMConfigCacheRefresh
(
virConnectPtr
conn
);
int
xenXMConfigCacheAddFile
(
virConnectPtr
conn
,
const
char
*
filename
);
int
xenXMConfigCacheRemoveFile
(
virConnectPtr
conn
,
const
char
*
filename
);
int
xenXMOpen
(
virConnectPtr
conn
,
virConnectAuthPtr
auth
,
int
flags
);
int
xenXMClose
(
virConnectPtr
conn
);
const
char
*
xenXMGetType
(
virConnectPtr
conn
);
...
...
src/xs_internal.c
浏览文件 @
1eeceaa6
...
...
@@ -29,6 +29,10 @@
#include "virterror_internal.h"
#include "datatypes.h"
#include "driver.h"
#include "memory.h"
#include "event.h"
#include "logging.h"
#include "uuid.h"
#include "xen_unified.h"
#include "xs_internal.h"
#include "xen_internal.h"
/* for xenHypervisorCheckID */
...
...
@@ -42,6 +46,9 @@
#endif
#ifndef PROXY
/* A list of active domain name/uuids */
static
xenUnifiedDomainInfoListPtr
activeDomainList
=
NULL
;
static
char
*
xenStoreDomainGetOSType
(
virDomainPtr
domain
);
struct
xenUnifiedDriver
xenStoreDriver
=
{
...
...
@@ -302,7 +309,52 @@ xenStoreOpen(virConnectPtr conn,
}
return
(
-
1
);
}
return
(
0
);
#ifndef PROXY
/* Init activeDomainList */
if
(
VIR_ALLOC
(
activeDomainList
)
<
0
)
{
virXenStoreError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"failed to allocate activeDomainList"
));
return
-
1
;
}
/* Init watch list before filling in domInfoList,
so we can know if it is the first time through
when the callback fires */
if
(
VIR_ALLOC
(
priv
->
xsWatchList
)
<
0
)
{
virXenStoreError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"failed to allocate xsWatchList"
));
return
-
1
;
}
/* This will get called once at start */
if
(
xenStoreAddWatch
(
conn
,
"@releaseDomain"
,
"releaseDomain"
,
xenStoreDomainReleased
,
priv
)
<
0
)
{
virXenStoreError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"adding watch @releaseDomain"
));
return
-
1
;
}
/* The initial call of this will fill domInfoList */
if
(
xenStoreAddWatch
(
conn
,
"@introduceDomain"
,
"introduceDomain"
,
xenStoreDomainIntroduced
,
priv
)
<
0
)
{
virXenStoreError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"adding watch @introduceDomain"
));
return
-
1
;
}
/* Add an event handle */
if
((
priv
->
xsWatch
=
virEventAddHandle
(
xs_fileno
(
priv
->
xshandle
),
VIR_EVENT_HANDLE_READABLE
,
xenStoreWatchEvent
,
conn
,
NULL
))
<
0
)
DEBUG0
(
"Failed to add event handle, disabling events
\n
"
);
#endif //PROXY
return
0
;
}
/**
...
...
@@ -324,10 +376,29 @@ xenStoreClose(virConnectPtr conn)
}
priv
=
(
xenUnifiedPrivatePtr
)
conn
->
privateData
;
if
(
xenStoreRemoveWatch
(
conn
,
"@introduceDomain"
,
"introduceDomain"
)
<
0
)
{
DEBUG0
(
"Warning, could not remove @introduceDomain watch"
);
/* not fatal */
}
if
(
xenStoreRemoveWatch
(
conn
,
"@releaseDomain"
,
"releaseDomain"
)
<
0
)
{
DEBUG0
(
"Warning, could not remove @releaseDomain watch"
);
/* not fatal */
}
xenStoreWatchListFree
(
priv
->
xsWatchList
);
#ifndef PROXY
xenUnifiedDomainInfoListFree
(
activeDomainList
);
#endif
if
(
priv
->
xshandle
==
NULL
)
return
(
-
1
);
if
(
priv
->
xsWatch
!=
-
1
)
virEventRemoveHandle
(
priv
->
xsWatch
);
xs_daemon_close
(
priv
->
xshandle
);
priv
->
xshandle
=
NULL
;
return
(
0
);
}
...
...
@@ -920,3 +991,343 @@ char *xenStoreDomainGetName(virConnectPtr conn,
return
xs_read
(
priv
->
xshandle
,
0
,
prop
,
&
len
);
}
#ifndef PROXY
int
xenStoreDomainGetUUID
(
virConnectPtr
conn
,
int
id
,
unsigned
char
*
uuid
)
{
char
prop
[
200
];
xenUnifiedPrivatePtr
priv
;
unsigned
int
len
;
char
*
uuidstr
;
int
ret
=
0
;
priv
=
(
xenUnifiedPrivatePtr
)
conn
->
privateData
;
if
(
priv
->
xshandle
==
NULL
)
return
-
1
;
snprintf
(
prop
,
199
,
"/local/domain/%d/vm"
,
id
);
prop
[
199
]
=
0
;
// This will return something like
// /vm/00000000-0000-0000-0000-000000000000
uuidstr
=
xs_read
(
priv
->
xshandle
,
0
,
prop
,
&
len
);
// remove "/vm/"
ret
=
virUUIDParse
(
uuidstr
+
4
,
uuid
);
VIR_FREE
(
uuidstr
);
return
ret
;
}
#endif //PROXY
void
xenStoreWatchListFree
(
xenStoreWatchListPtr
list
)
{
int
i
;
for
(
i
=
0
;
i
<
list
->
count
;
i
++
)
{
VIR_FREE
(
list
->
watches
[
i
]
->
path
);
VIR_FREE
(
list
->
watches
[
i
]
->
token
);
VIR_FREE
(
list
->
watches
[
i
]);
}
VIR_FREE
(
list
);
}
int
xenStoreAddWatch
(
virConnectPtr
conn
,
const
char
*
path
,
const
char
*
token
,
xenStoreWatchCallback
cb
,
void
*
opaque
)
{
xenStoreWatchPtr
watch
;
int
n
;
xenStoreWatchListPtr
list
;
xenUnifiedPrivatePtr
priv
=
(
xenUnifiedPrivatePtr
)
conn
->
privateData
;
if
(
priv
->
xshandle
==
NULL
)
return
-
1
;
list
=
priv
->
xsWatchList
;
if
(
!
list
)
return
-
1
;
/* check if we already have this callback on our list */
for
(
n
=
0
;
n
<
list
->
count
;
n
++
)
{
if
(
STREQ
(
list
->
watches
[
n
]
->
path
,
path
)
&&
STREQ
(
list
->
watches
[
n
]
->
token
,
token
))
{
virXenStoreError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"watch already tracked"
));
return
-
1
;
}
}
if
(
VIR_ALLOC
(
watch
)
<
0
)
return
-
1
;
watch
->
path
=
strdup
(
path
);
watch
->
token
=
strdup
(
token
);
watch
->
cb
=
cb
;
watch
->
opaque
=
opaque
;
/* Make space on list */
n
=
list
->
count
;
if
(
VIR_REALLOC_N
(
list
->
watches
,
n
+
1
)
<
0
)
{
virXenStoreError
(
NULL
,
VIR_ERR_INTERNAL_ERROR
,
"%s"
,
_
(
"reallocating list"
));
VIR_FREE
(
watch
);
return
-
1
;
}
list
->
watches
[
n
]
=
watch
;
list
->
count
++
;
conn
->
refs
++
;
return
xs_watch
(
priv
->
xshandle
,
watch
->
path
,
watch
->
token
);
}
int
xenStoreRemoveWatch
(
virConnectPtr
conn
,
const
char
*
path
,
const
char
*
token
)
{
int
i
;
xenStoreWatchListPtr
list
;
xenUnifiedPrivatePtr
priv
=
(
xenUnifiedPrivatePtr
)
conn
->
privateData
;
if
(
priv
->
xshandle
==
NULL
)
return
-
1
;
list
=
priv
->
xsWatchList
;
if
(
!
list
)
return
-
1
;
for
(
i
=
0
;
i
<
list
->
count
;
i
++
)
{
if
(
STREQ
(
list
->
watches
[
i
]
->
path
,
path
)
&&
STREQ
(
list
->
watches
[
i
]
->
token
,
token
))
{
if
(
!
xs_unwatch
(
priv
->
xshandle
,
list
->
watches
[
i
]
->
path
,
list
->
watches
[
i
]
->
path
))
{
DEBUG0
(
"WARNING: Could not remove watch"
);
/* Not fatal, continue */
}
VIR_FREE
(
list
->
watches
[
i
]
->
path
);
VIR_FREE
(
list
->
watches
[
i
]
->
token
);
VIR_FREE
(
list
->
watches
[
i
]);
if
(
i
<
(
list
->
count
-
1
))
memmove
(
list
->
watches
+
i
,
list
->
watches
+
i
+
1
,
sizeof
(
*
(
list
->
watches
))
*
(
list
->
count
-
(
i
+
1
)));
if
(
VIR_REALLOC_N
(
list
->
watches
,
list
->
count
-
1
)
<
0
)
{
;
/* Failure to reduce memory allocation isn't fatal */
}
list
->
count
--
;
#ifndef PROXY
virUnrefConnect
(
conn
);
#endif
return
0
;
}
}
return
-
1
;
}
xenStoreWatchPtr
xenStoreFindWatch
(
xenStoreWatchListPtr
list
,
const
char
*
path
,
const
char
*
token
)
{
int
i
;
for
(
i
=
0
;
i
<
list
->
count
;
i
++
)
if
(
STREQ
(
path
,
list
->
watches
[
i
]
->
path
)
&&
STREQ
(
token
,
list
->
watches
[
i
]
->
token
)
)
return
list
->
watches
[
i
];
return
NULL
;
}
void
xenStoreWatchEvent
(
int
watch
ATTRIBUTE_UNUSED
,
int
fd
ATTRIBUTE_UNUSED
,
int
events
ATTRIBUTE_UNUSED
,
void
*
data
)
{
char
**
event
;
char
*
path
;
char
*
token
;
unsigned
int
stringCount
;
xenStoreWatchPtr
sw
;
virConnectPtr
conn
=
data
;
xenUnifiedPrivatePtr
priv
=
(
xenUnifiedPrivatePtr
)
conn
->
privateData
;
if
(
!
priv
)
return
;
if
(
!
priv
->
xshandle
)
return
;
event
=
xs_read_watch
(
priv
->
xshandle
,
&
stringCount
);
if
(
!
event
)
return
;
path
=
event
[
XS_WATCH_PATH
];
token
=
event
[
XS_WATCH_TOKEN
];
sw
=
xenStoreFindWatch
(
priv
->
xsWatchList
,
path
,
token
);
if
(
sw
)
sw
->
cb
(
conn
,
path
,
token
,
sw
->
opaque
);
VIR_FREE
(
event
);
}
#ifndef PROXY
/* The domain callback for the @introduceDomain watch */
int
xenStoreDomainIntroduced
(
virConnectPtr
conn
,
const
char
*
path
ATTRIBUTE_UNUSED
,
const
char
*
token
ATTRIBUTE_UNUSED
,
void
*
opaque
)
{
int
i
,
j
,
found
,
missing
=
0
,
retries
=
20
;
int
new_domain_cnt
;
int
*
new_domids
;
int
nread
;
xenUnifiedPrivatePtr
priv
=
(
xenUnifiedPrivatePtr
)
opaque
;
retry:
new_domain_cnt
=
xenStoreNumOfDomains
(
conn
);
if
(
VIR_ALLOC_N
(
new_domids
,
new_domain_cnt
)
<
0
)
{
virXenStoreError
(
NULL
,
VIR_ERR_NO_MEMORY
,
"%s"
,
_
(
"failed to allocate domids"
));
return
-
1
;
}
nread
=
xenStoreListDomains
(
conn
,
new_domids
,
new_domain_cnt
);
if
(
nread
!=
new_domain_cnt
)
{
// mismatch. retry this read
VIR_FREE
(
new_domids
);
goto
retry
;
}
missing
=
0
;
for
(
i
=
0
;
i
<
new_domain_cnt
;
i
++
)
{
found
=
0
;
for
(
j
=
0
;
j
<
activeDomainList
->
count
;
j
++
)
{
if
(
activeDomainList
->
doms
[
j
]
->
id
==
new_domids
[
i
])
{
found
=
1
;
break
;
}
}
if
(
!
found
)
{
virDomainPtr
dom
;
char
*
name
;
unsigned
char
uuid
[
VIR_UUID_BUFLEN
];
if
(
!
(
name
=
xenStoreDomainGetName
(
conn
,
new_domids
[
i
])))
{
missing
=
1
;
continue
;
}
if
(
xenStoreDomainGetUUID
(
conn
,
new_domids
[
i
],
uuid
)
<
0
)
{
missing
=
1
;
VIR_FREE
(
name
);
continue
;
}
dom
=
virGetDomain
(
conn
,
name
,
uuid
);
if
(
dom
)
{
dom
->
id
=
new_domids
[
i
];
/* This domain was not in the old list. Emit an event */
xenUnifiedDomainEventDispatch
(
priv
,
dom
,
VIR_DOMAIN_EVENT_STARTED
,
VIR_DOMAIN_EVENT_STARTED_BOOTED
);
/* Add to the list */
xenUnifiedAddDomainInfo
(
activeDomainList
,
new_domids
[
i
],
name
,
uuid
);
virUnrefDomain
(
dom
);
}
VIR_FREE
(
name
);
}
}
VIR_FREE
(
new_domids
);
if
(
missing
&&
retries
--
)
{
DEBUG0
(
"Some domains were missing, trying again"
);
usleep
(
100
*
1000
);
goto
retry
;
}
return
0
;
}
/* The domain callback for the @destroyDomain watch */
int
xenStoreDomainReleased
(
virConnectPtr
conn
,
const
char
*
path
ATTRIBUTE_UNUSED
,
const
char
*
token
ATTRIBUTE_UNUSED
,
void
*
opaque
)
{
int
i
,
j
,
found
,
removed
,
retries
=
20
;
int
new_domain_cnt
;
int
*
new_domids
;
int
nread
;
xenUnifiedPrivatePtr
priv
=
(
xenUnifiedPrivatePtr
)
opaque
;
if
(
!
activeDomainList
->
count
)
return
0
;
retry:
new_domain_cnt
=
xenStoreNumOfDomains
(
conn
);
if
(
VIR_ALLOC_N
(
new_domids
,
new_domain_cnt
)
<
0
)
{
virXenStoreError
(
NULL
,
VIR_ERR_NO_MEMORY
,
"%s"
,
_
(
"failed to allocate domids"
));
return
-
1
;
}
nread
=
xenStoreListDomains
(
conn
,
new_domids
,
new_domain_cnt
);
if
(
nread
!=
new_domain_cnt
)
{
// mismatch. retry this read
VIR_FREE
(
new_domids
);
goto
retry
;
}
removed
=
0
;
for
(
j
=
0
;
j
<
activeDomainList
->
count
;
j
++
)
{
found
=
0
;
for
(
i
=
0
;
i
<
new_domain_cnt
;
i
++
)
{
if
(
activeDomainList
->
doms
[
j
]
->
id
==
new_domids
[
i
])
{
found
=
1
;
break
;
}
}
if
(
!
found
)
{
virDomainPtr
dom
=
virGetDomain
(
conn
,
activeDomainList
->
doms
[
j
]
->
name
,
activeDomainList
->
doms
[
j
]
->
uuid
);
if
(
dom
)
{
dom
->
id
=
-
1
;
/* This domain was not in the new list. Emit an event */
xenUnifiedDomainEventDispatch
(
priv
,
dom
,
VIR_DOMAIN_EVENT_STOPPED
,
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN
);
/* Remove from the list */
xenUnifiedRemoveDomainInfo
(
activeDomainList
,
activeDomainList
->
doms
[
j
]
->
id
,
activeDomainList
->
doms
[
j
]
->
name
,
activeDomainList
->
doms
[
j
]
->
uuid
);
virUnrefDomain
(
dom
);
removed
=
1
;
}
}
}
VIR_FREE
(
new_domids
);
if
(
!
removed
&&
retries
--
)
{
DEBUG0
(
"No domains removed, retrying"
);
usleep
(
100
*
1000
);
goto
retry
;
}
return
0
;
}
#endif //PROXY
src/xs_internal.h
浏览文件 @
1eeceaa6
...
...
@@ -51,5 +51,57 @@ char * xenStoreDomainGetDiskID(virConnectPtr conn,
const
char
*
dev
);
char
*
xenStoreDomainGetName
(
virConnectPtr
conn
,
int
id
);
int
xenStoreDomainGetUUID
(
virConnectPtr
conn
,
int
id
,
unsigned
char
*
uuid
);
typedef
int
(
*
xenStoreWatchCallback
)(
virConnectPtr
conn
,
const
char
*
path
,
const
char
*
token
,
void
*
opaque
);
struct
_xenStoreWatch
{
char
*
path
;
char
*
token
;
xenStoreWatchCallback
cb
;
void
*
opaque
;
};
typedef
struct
_xenStoreWatch
xenStoreWatch
;
typedef
xenStoreWatch
*
xenStoreWatchPtr
;
struct
_xenStoreWatchList
{
unsigned
int
count
;
xenStoreWatchPtr
*
watches
;
};
typedef
struct
_xenStoreWatchList
xenStoreWatchList
;
typedef
xenStoreWatchList
*
xenStoreWatchListPtr
;
void
xenStoreWatchListFree
(
xenStoreWatchListPtr
head
);
int
xenStoreAddWatch
(
virConnectPtr
conn
,
const
char
*
path
,
const
char
*
token
,
xenStoreWatchCallback
cb
,
void
*
opaque
);
int
xenStoreRemoveWatch
(
virConnectPtr
conn
,
const
char
*
path
,
const
char
*
token
);
xenStoreWatchPtr
xenStoreFindWatch
(
xenStoreWatchListPtr
list
,
const
char
*
path
,
const
char
*
token
);
void
xenStoreWatchEvent
(
int
watch
,
int
fd
,
int
events
,
void
*
data
);
/* domain events */
int
xenStoreDomainIntroduced
(
virConnectPtr
conn
,
const
char
*
path
,
const
char
*
token
,
void
*
opaque
);
int
xenStoreDomainReleased
(
virConnectPtr
conn
,
const
char
*
path
,
const
char
*
token
,
void
*
opaque
);
int
xenStoreDomainEventEmitted
(
virDomainEventType
evt
);
#endif
/* __VIR_XS_INTERNAL_H__ */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录