Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
763dacda
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
763dacda
编写于
8月 13, 2008
作者:
D
Daniel P. Berrange
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make LXC I/O controller process a parent of the container process
上级
518c2144
变更
11
展开全部
隐藏空白更改
内联
并排
Showing
11 changed file
with
854 addition
and
555 deletion
+854
-555
ChangeLog
ChangeLog
+21
-0
configure.in
configure.in
+1
-1
src/lxc_conf.c
src/lxc_conf.c
+10
-185
src/lxc_conf.h
src/lxc_conf.h
+4
-8
src/lxc_container.c
src/lxc_container.c
+18
-17
src/lxc_container.h
src/lxc_container.h
+4
-4
src/lxc_controller.c
src/lxc_controller.c
+318
-17
src/lxc_controller.h
src/lxc_controller.h
+9
-1
src/lxc_driver.c
src/lxc_driver.c
+291
-322
src/util.c
src/util.c
+166
-0
src/util.h
src/util.h
+12
-0
未找到文件。
ChangeLog
浏览文件 @
763dacda
Wed Aug 13 11:48:36 BST 2008 Daniel Berrange <berrange@redhat.com>
* configure.in: Add check for termios.h
* src/util.h, src/util.c: Add virFileOpenTty and helpers
for creating/deleting/reading PID files
* src/lxc_conf.h, src/lxc_conf.c, src/lxc_container.c,
src/lxc_container.h, src/lxc_controller.c,
src/lxc_controller.h, src/lxc_driver.c: Re-arrange
container launch process so that the I/O helper is
a direct parent of the container process. Daemonize
container so it survives restarts of libvirtd.
Wed Aug 13 11:23:36 BST 2008 Daniel Berrange <berrange@redhat.com>
Re-arrange code between LXC driver files
* src/lxc_container.c, src/lxc_container.h,
src/lxc_controller.h, src/lxc_container.c,
src/lxc_driver.c: Move code for I/O handling into
a seprate lxc_controller module, and move code for
creating containers into lcx_container module.
Wed Aug 13 10:55:36 BST 2008 Daniel Berrange <berrange@redhat.com>
Wed Aug 13 10:55:36 BST 2008 Daniel Berrange <berrange@redhat.com>
* src/lxc_conf.h, src/lxc_conf.c, src/lxc_container.h,
* src/lxc_conf.h, src/lxc_conf.c, src/lxc_container.h,
...
...
configure.in
浏览文件 @
763dacda
...
@@ -68,7 +68,7 @@ dnl Availability of various common functions (non-fatal if missing).
...
@@ -68,7 +68,7 @@ dnl Availability of various common functions (non-fatal if missing).
AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity])
AC_CHECK_FUNCS([cfmakeraw regexec uname sched_getaffinity])
dnl Availability of various common headers (non-fatal if missing).
dnl Availability of various common headers (non-fatal if missing).
AC_CHECK_HEADERS([pwd.h paths.h sys/syslimits.h sys/utsname.h sys/wait.h winsock2.h sched.h])
AC_CHECK_HEADERS([pwd.h paths.h sys/syslimits.h sys/utsname.h sys/wait.h winsock2.h sched.h
termios.h
])
dnl Where are the XDR functions?
dnl Where are the XDR functions?
dnl If portablexdr is installed, prefer that.
dnl If portablexdr is installed, prefer that.
...
...
src/lxc_conf.c
浏览文件 @
763dacda
...
@@ -833,25 +833,24 @@ static lxc_vm_t * lxcLoadConfig(lxc_driver_t *driver,
...
@@ -833,25 +833,24 @@ static lxc_vm_t * lxcLoadConfig(lxc_driver_t *driver,
strncpy
(
vm
->
configFileBase
,
file
,
PATH_MAX
);
strncpy
(
vm
->
configFileBase
,
file
,
PATH_MAX
);
vm
->
configFile
[
PATH_MAX
-
1
]
=
'\0'
;
vm
->
configFile
[
PATH_MAX
-
1
]
=
'\0'
;
if
(
lxcLoadTtyPid
(
driver
,
vm
)
<
0
)
{
DEBUG0
(
"failed to load tty pid"
);
}
return
vm
;
return
vm
;
}
}
int
lxcLoadDriverConfig
(
lxc_driver_t
*
driver
)
int
lxcLoadDriverConfig
(
lxc_driver_t
*
driver
)
{
{
/* Set the container configuration directory */
/* Set the container configuration directory */
driver
->
configDir
=
strdup
(
SYSCONF_DIR
"/libvirt/lxc"
);
if
((
driver
->
configDir
=
strdup
(
SYSCONF_DIR
"/libvirt/lxc"
))
==
NULL
)
if
(
NULL
==
driver
->
configDir
)
{
goto
no_memory
;
lxcError
(
NULL
,
NULL
,
VIR_ERR_NO_MEMORY
,
"configDir"
);
if
((
driver
->
stateDir
=
strdup
(
LOCAL_STATE_DIR
"/run/libvirt/lxc"
))
==
NULL
)
return
-
1
;
goto
no_memory
;
}
if
((
driver
->
logDir
=
strdup
(
LOCAL_STATE_DIR
"/log/libvirt/lxc"
))
==
NULL
)
goto
no_memory
;
driver
->
stateDir
=
strdup
(
LOCAL_STATE_DIR
"/run/libvirt/lxc"
);
return
0
;
return
0
;
no_memory:
lxcError
(
NULL
,
NULL
,
VIR_ERR_NO_MEMORY
,
"configDir"
);
return
-
1
;
}
}
int
lxcLoadContainerConfigFile
(
lxc_driver_t
*
driver
,
int
lxcLoadContainerConfigFile
(
lxc_driver_t
*
driver
,
...
@@ -1012,9 +1011,7 @@ void lxcFreeVMDef(lxc_vm_def_t *vmdef)
...
@@ -1012,9 +1011,7 @@ void lxcFreeVMDef(lxc_vm_def_t *vmdef)
curNet
=
vmdef
->
nets
;
curNet
=
vmdef
->
nets
;
while
(
curNet
)
{
while
(
curNet
)
{
nextNet
=
curNet
->
next
;
nextNet
=
curNet
->
next
;
printf
(
"Freeing %s:%s
\n
"
,
curNet
->
parentVeth
,
curNet
->
containerVeth
);
VIR_FREE
(
curNet
->
parentVeth
);
VIR_FREE
(
curNet
->
parentVeth
);
VIR_FREE
(
curNet
->
containerVeth
);
VIR_FREE
(
curNet
->
txName
);
VIR_FREE
(
curNet
->
txName
);
VIR_FREE
(
curNet
);
VIR_FREE
(
curNet
);
curNet
=
nextNet
;
curNet
=
nextNet
;
...
@@ -1106,176 +1103,4 @@ int lxcDeleteConfig(virConnectPtr conn,
...
@@ -1106,176 +1103,4 @@ int lxcDeleteConfig(virConnectPtr conn,
return
0
;
return
0
;
}
}
/**
* lxcStoreTtyPid:
* @driver: pointer to driver
* @vm: Ptr to VM
*
* Stores the pid of the tty forward process contained in vm->pid
* LOCAL_STATE_DIR/run/libvirt/lxc/{container_name}.pid
*
* Returns 0 on success or -1 in case of error
*/
int
lxcStoreTtyPid
(
const
lxc_driver_t
*
driver
,
lxc_vm_t
*
vm
)
{
int
rc
=
-
1
;
int
fd
;
FILE
*
file
=
NULL
;
if
(
vm
->
ttyPidFile
[
0
]
==
0x00
)
{
if
((
rc
=
virFileMakePath
(
driver
->
stateDir
)))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot create lxc state directory %s: %s"
),
driver
->
stateDir
,
strerror
(
rc
));
goto
error_out
;
}
if
(
virFileBuildPath
(
driver
->
stateDir
,
vm
->
def
->
name
,
".pid"
,
vm
->
ttyPidFile
,
PATH_MAX
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot construct tty pid file path"
));
goto
error_out
;
}
}
if
((
fd
=
open
(
vm
->
ttyPidFile
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
))
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot create tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
goto
error_out
;
}
if
(
!
(
file
=
fdopen
(
fd
,
"w"
)))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot fdopen tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
if
(
close
(
fd
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"failed to close tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
}
goto
error_out
;
}
if
(
fprintf
(
file
,
"%d"
,
vm
->
pid
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot write tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
goto
fclose_error_out
;
}
rc
=
0
;
fclose_error_out:
if
(
fclose
(
file
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"failed to close tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
}
error_out:
return
rc
;
}
/**
* lxcLoadTtyPid:
* @driver: pointer to driver
* @vm: Ptr to VM
*
* Loads the pid of the tty forward process from the pid file.
* LOCAL_STATE_DIR/run/libvirt/lxc/{container_name}.pid
*
* Returns
* > 0 - pid of tty process
* 0 - no tty pid file
* -1 - error
*/
int
lxcLoadTtyPid
(
const
lxc_driver_t
*
driver
,
lxc_vm_t
*
vm
)
{
int
rc
=
-
1
;
FILE
*
file
;
if
(
vm
->
ttyPidFile
[
0
]
==
0x00
)
{
if
((
rc
=
virFileMakePath
(
driver
->
stateDir
)))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot create lxc state directory %s: %s"
),
driver
->
stateDir
,
strerror
(
rc
));
goto
cleanup
;
}
if
(
virFileBuildPath
(
driver
->
stateDir
,
vm
->
def
->
name
,
".pid"
,
vm
->
ttyPidFile
,
PATH_MAX
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot construct tty pid file path"
));
goto
cleanup
;
}
}
if
(
!
(
file
=
fopen
(
vm
->
ttyPidFile
,
"r"
)))
{
if
(
ENOENT
==
errno
)
{
rc
=
0
;
goto
cleanup
;
}
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot open tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
goto
cleanup
;
}
if
(
fscanf
(
file
,
"%d"
,
&
(
vm
->
pid
))
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot read tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
goto
cleanup
;
}
if
(
fclose
(
file
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"failed to close tty pid file %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
goto
cleanup
;
}
rc
=
vm
->
pid
;
cleanup:
return
rc
;
}
/**
* lxcDeleteTtyPid:
* @vm: Ptr to VM
*
* Unlinks the tty pid file for the vm
* LOCAL_STATE_DIR/run/libvirt/lxc/{container_name}.pid
*
* Returns on 0 success or -1 in case of error
*/
int
lxcDeleteTtyPidFile
(
const
lxc_vm_t
*
vm
)
{
if
(
vm
->
ttyPidFile
[
0
]
==
0x00
)
{
goto
no_file
;
}
if
(
unlink
(
vm
->
ttyPidFile
)
<
0
)
{
if
(
errno
==
ENOENT
)
{
goto
no_file
;
}
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"cannot remove ttyPidFile %s: %s"
),
vm
->
ttyPidFile
,
strerror
(
errno
));
return
-
1
;
}
no_file:
return
0
;
}
#endif
/* WITH_LXC */
#endif
/* WITH_LXC */
src/lxc_conf.h
浏览文件 @
763dacda
...
@@ -46,7 +46,6 @@ typedef struct __lxc_net_def lxc_net_def_t;
...
@@ -46,7 +46,6 @@ typedef struct __lxc_net_def lxc_net_def_t;
struct
__lxc_net_def
{
struct
__lxc_net_def
{
int
type
;
int
type
;
char
*
parentVeth
;
/* veth device in parent namespace */
char
*
parentVeth
;
/* veth device in parent namespace */
char
*
containerVeth
;
/* veth device in container namespace */
char
*
txName
;
/* bridge or network name */
char
*
txName
;
/* bridge or network name */
lxc_net_def_t
*
next
;
lxc_net_def_t
*
next
;
...
@@ -87,12 +86,11 @@ typedef struct __lxc_vm lxc_vm_t;
...
@@ -87,12 +86,11 @@ typedef struct __lxc_vm lxc_vm_t;
struct
__lxc_vm
{
struct
__lxc_vm
{
int
pid
;
int
pid
;
int
state
;
int
state
;
int
monitor
;
char
configFile
[
PATH_MAX
];
char
configFile
[
PATH_MAX
];
char
configFileBase
[
PATH_MAX
];
char
configFileBase
[
PATH_MAX
];
char
ttyPidFile
[
PATH_MAX
];
lxc_vm_def_t
*
def
;
lxc_vm_def_t
*
def
;
lxc_vm_t
*
next
;
lxc_vm_t
*
next
;
...
@@ -103,8 +101,9 @@ struct __lxc_driver {
...
@@ -103,8 +101,9 @@ struct __lxc_driver {
lxc_vm_t
*
vms
;
lxc_vm_t
*
vms
;
int
nactivevms
;
int
nactivevms
;
int
ninactivevms
;
int
ninactivevms
;
char
*
configDir
;
char
*
configDir
;
char
*
stateDir
;
char
*
stateDir
;
char
*
logDir
;
int
have_netns
;
int
have_netns
;
};
};
...
@@ -154,9 +153,6 @@ int lxcDeleteConfig(virConnectPtr conn,
...
@@ -154,9 +153,6 @@ int lxcDeleteConfig(virConnectPtr conn,
lxc_driver_t
*
driver
,
lxc_driver_t
*
driver
,
const
char
*
configFile
,
const
char
*
configFile
,
const
char
*
name
);
const
char
*
name
);
int
lxcStoreTtyPid
(
const
lxc_driver_t
*
driver
,
lxc_vm_t
*
vm
);
int
lxcLoadTtyPid
(
const
lxc_driver_t
*
driver
,
lxc_vm_t
*
vm
);
int
lxcDeleteTtyPidFile
(
const
lxc_vm_t
*
vm
);
void
lxcError
(
virConnectPtr
conn
,
void
lxcError
(
virConnectPtr
conn
,
virDomainPtr
dom
,
virDomainPtr
dom
,
...
...
src/lxc_container.c
浏览文件 @
763dacda
...
@@ -69,6 +69,8 @@ typedef char lxc_message_t;
...
@@ -69,6 +69,8 @@ typedef char lxc_message_t;
typedef
struct
__lxc_child_argv
lxc_child_argv_t
;
typedef
struct
__lxc_child_argv
lxc_child_argv_t
;
struct
__lxc_child_argv
{
struct
__lxc_child_argv
{
lxc_vm_def_t
*
config
;
lxc_vm_def_t
*
config
;
unsigned
int
nveths
;
char
**
veths
;
int
monitor
;
int
monitor
;
char
*
ttyPath
;
char
*
ttyPath
;
};
};
...
@@ -171,8 +173,7 @@ error_out:
...
@@ -171,8 +173,7 @@ error_out:
*
*
* Returns 0 on success or -1 in case of error
* Returns 0 on success or -1 in case of error
*/
*/
int
lxcContainerSendContinue
(
virConnectPtr
conn
,
int
lxcContainerSendContinue
(
int
control
)
int
control
)
{
{
int
rc
=
-
1
;
int
rc
=
-
1
;
lxc_message_t
msg
=
LXC_CONTINUE_MSG
;
lxc_message_t
msg
=
LXC_CONTINUE_MSG
;
...
@@ -180,7 +181,7 @@ int lxcContainerSendContinue(virConnectPtr conn,
...
@@ -180,7 +181,7 @@ int lxcContainerSendContinue(virConnectPtr conn,
writeCount
=
safewrite
(
control
,
&
msg
,
sizeof
(
msg
));
writeCount
=
safewrite
(
control
,
&
msg
,
sizeof
(
msg
));
if
(
writeCount
!=
sizeof
(
msg
))
{
if
(
writeCount
!=
sizeof
(
msg
))
{
lxcError
(
conn
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"unable to send container continue message: %s"
),
_
(
"unable to send container continue message: %s"
),
strerror
(
errno
));
strerror
(
errno
));
goto
error_out
;
goto
error_out
;
...
@@ -230,21 +231,22 @@ static int lxcContainerWaitForContinue(int control)
...
@@ -230,21 +231,22 @@ static int lxcContainerWaitForContinue(int control)
*
*
* Returns 0 on success or nonzero in case of error
* Returns 0 on success or nonzero in case of error
*/
*/
static
int
lxcContainerEnableInterfaces
(
const
lxc_vm_def_t
*
def
)
static
int
lxcContainerEnableInterfaces
(
unsigned
int
nveths
,
char
**
veths
)
{
{
int
rc
=
0
;
int
rc
=
0
;
const
lxc_net_def_t
*
net
;
unsigned
int
i
;
for
(
net
=
def
->
nets
;
net
;
net
=
net
->
next
)
{
for
(
i
=
0
;
i
<
nveths
;
i
++
)
{
DEBUG
(
"Enabling %s"
,
net
->
containerVeth
);
DEBUG
(
"Enabling %s"
,
veths
[
i
]
);
rc
=
vethInterfaceUpOrDown
(
net
->
containerVeth
,
1
);
rc
=
vethInterfaceUpOrDown
(
veths
[
i
]
,
1
);
if
(
0
!=
rc
)
{
if
(
0
!=
rc
)
{
goto
error_out
;
goto
error_out
;
}
}
}
}
/* enable lo device only if there were other net devices */
/* enable lo device only if there were other net devices */
if
(
def
->
net
s
)
if
(
veth
s
)
rc
=
vethInterfaceUpOrDown
(
"lo"
,
1
);
rc
=
vethInterfaceUpOrDown
(
"lo"
,
1
);
error_out:
error_out:
...
@@ -311,7 +313,7 @@ static int lxcContainerChild( void *data )
...
@@ -311,7 +313,7 @@ static int lxcContainerChild( void *data )
return
-
1
;
return
-
1
;
/* enable interfaces */
/* enable interfaces */
if
(
lxcContainerEnableInterfaces
(
vmDef
)
<
0
)
if
(
lxcContainerEnableInterfaces
(
argv
->
nveths
,
argv
->
veths
)
<
0
)
return
-
1
;
return
-
1
;
/* this function will only return if an error occured */
/* this function will only return if an error occured */
...
@@ -320,7 +322,6 @@ static int lxcContainerChild( void *data )
...
@@ -320,7 +322,6 @@ static int lxcContainerChild( void *data )
/**
/**
* lxcContainerStart:
* lxcContainerStart:
* @conn: pointer to connection
* @driver: pointer to driver structure
* @driver: pointer to driver structure
* @vm: pointer to virtual machine structure
* @vm: pointer to virtual machine structure
*
*
...
@@ -328,8 +329,9 @@ static int lxcContainerChild( void *data )
...
@@ -328,8 +329,9 @@ static int lxcContainerChild( void *data )
*
*
* Returns PID of container on success or -1 in case of error
* Returns PID of container on success or -1 in case of error
*/
*/
int
lxcContainerStart
(
virConnectPtr
conn
,
int
lxcContainerStart
(
lxc_vm_def_t
*
def
,
lxc_vm_def_t
*
def
,
unsigned
int
nveths
,
char
**
veths
,
int
control
,
int
control
,
char
*
ttyPath
)
char
*
ttyPath
)
{
{
...
@@ -337,12 +339,11 @@ int lxcContainerStart(virConnectPtr conn,
...
@@ -337,12 +339,11 @@ int lxcContainerStart(virConnectPtr conn,
int
flags
;
int
flags
;
int
stacksize
=
getpagesize
()
*
4
;
int
stacksize
=
getpagesize
()
*
4
;
char
*
stack
,
*
stacktop
;
char
*
stack
,
*
stacktop
;
lxc_child_argv_t
args
=
{
def
,
control
,
ttyPath
};
lxc_child_argv_t
args
=
{
def
,
nveths
,
veths
,
control
,
ttyPath
};
/* allocate a stack for the container */
/* allocate a stack for the container */
if
(
VIR_ALLOC_N
(
stack
,
stacksize
)
<
0
)
{
if
(
VIR_ALLOC_N
(
stack
,
stacksize
)
<
0
)
{
lxcError
(
conn
,
NULL
,
VIR_ERR_NO_MEMORY
,
lxcError
(
NULL
,
NULL
,
VIR_ERR_NO_MEMORY
,
NULL
);
_
(
"unable to allocate container stack"
));
return
-
1
;
return
-
1
;
}
}
stacktop
=
stack
+
stacksize
;
stacktop
=
stack
+
stacksize
;
...
@@ -357,7 +358,7 @@ int lxcContainerStart(virConnectPtr conn,
...
@@ -357,7 +358,7 @@ int lxcContainerStart(virConnectPtr conn,
DEBUG
(
"clone() returned, %d"
,
pid
);
DEBUG
(
"clone() returned, %d"
,
pid
);
if
(
pid
<
0
)
{
if
(
pid
<
0
)
{
lxcError
(
conn
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"clone() failed, %s"
),
strerror
(
errno
));
_
(
"clone() failed, %s"
),
strerror
(
errno
));
return
-
1
;
return
-
1
;
}
}
...
...
src/lxc_container.h
浏览文件 @
763dacda
...
@@ -32,11 +32,11 @@ enum {
...
@@ -32,11 +32,11 @@ enum {
LXC_CONTAINER_FEATURE_NET
=
(
1
<<
0
),
LXC_CONTAINER_FEATURE_NET
=
(
1
<<
0
),
};
};
int
lxcContainerSendContinue
(
virConnectPtr
conn
,
int
lxcContainerSendContinue
(
int
control
);
int
control
);
int
lxcContainerStart
(
virConnectPtr
conn
,
int
lxcContainerStart
(
lxc_vm_def_t
*
def
,
lxc_vm_def_t
*
def
,
unsigned
int
nveths
,
char
**
veths
,
int
control
,
int
control
,
char
*
ttyPath
);
char
*
ttyPath
);
...
...
src/lxc_controller.c
浏览文件 @
763dacda
...
@@ -26,16 +26,27 @@
...
@@ -26,16 +26,27 @@
#ifdef WITH_LXC
#ifdef WITH_LXC
#include <sys/epoll.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <unistd.h>
#include <unistd.h>
#include <paths.h>
#include <fcntl.h>
#include <signal.h>
#include "internal.h"
#include "internal.h"
#include "util.h"
#include "util.h"
#include "lxc_conf.h"
#include "lxc_conf.h"
#include "lxc_container.h"
#include "lxc_controller.h"
#include "lxc_controller.h"
#include "veth.h"
#include "memory.h"
#include "util.h"
#define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt, __VA_ARGS__)
#define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt, __VA_ARGS__)
#define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg)
/**
/**
* lxcFdForward:
* lxcFdForward:
...
@@ -91,7 +102,10 @@ typedef struct _lxcTtyForwardFd_t {
...
@@ -91,7 +102,10 @@ typedef struct _lxcTtyForwardFd_t {
*
*
* Returns 0 on success or -1 in case of error
* Returns 0 on success or -1 in case of error
*/
*/
int
lxcControllerMain
(
int
appPty
,
int
contPty
)
static
int
lxcControllerMain
(
int
monitor
,
int
client
,
int
appPty
,
int
contPty
)
{
{
int
rc
=
-
1
;
int
rc
=
-
1
;
int
epollFd
;
int
epollFd
;
...
@@ -120,41 +134,77 @@ int lxcControllerMain(int appPty, int contPty)
...
@@ -120,41 +134,77 @@ int lxcControllerMain(int appPty, int contPty)
memset
(
&
epollEvent
,
0x00
,
sizeof
(
epollEvent
));
memset
(
&
epollEvent
,
0x00
,
sizeof
(
epollEvent
));
epollEvent
.
events
=
EPOLLIN
|
EPOLLET
;
/* edge triggered */
epollEvent
.
events
=
EPOLLIN
|
EPOLLET
;
/* edge triggered */
epollEvent
.
data
.
fd
=
appPty
;
epollEvent
.
data
.
fd
=
appPty
;
epollEvent
.
data
.
u32
=
0
;
/* fdArray position */
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
appPty
,
&
epollEvent
))
{
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
appPty
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(appPty) failed: %s"
),
strerror
(
errno
));
_
(
"epoll_ctl(appPty) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
goto
cleanup
;
}
}
epollEvent
.
data
.
fd
=
contPty
;
epollEvent
.
data
.
fd
=
contPty
;
epollEvent
.
data
.
u32
=
1
;
/* fdArray position */
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
contPty
,
&
epollEvent
))
{
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
contPty
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(contPty) failed: %s"
),
strerror
(
errno
));
_
(
"epoll_ctl(contPty) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
goto
cleanup
;
}
}
epollEvent
.
events
=
EPOLLIN
;
epollEvent
.
data
.
fd
=
monitor
;
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
monitor
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(contPty) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
epollEvent
.
events
=
EPOLLHUP
;
epollEvent
.
data
.
fd
=
client
;
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
client
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(contPty) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
while
(
1
)
{
while
(
1
)
{
/* if active fd's, return if no events, else wait forever */
/* if active fd's, return if no events, else wait forever */
timeout
=
(
numActive
>
0
)
?
0
:
-
1
;
timeout
=
(
numActive
>
0
)
?
0
:
-
1
;
numEvents
=
epoll_wait
(
epollFd
,
&
epollEvent
,
1
,
timeout
);
numEvents
=
epoll_wait
(
epollFd
,
&
epollEvent
,
1
,
timeout
);
if
(
0
<
numEvents
)
{
if
(
numEvents
>
0
)
{
if
(
epollEvent
.
events
&
EPOLLIN
)
{
if
(
epollEvent
.
data
.
fd
==
monitor
)
{
curFdOff
=
epollEvent
.
data
.
u32
;
int
fd
=
accept
(
monitor
,
NULL
,
0
)
;
if
(
!
fdArray
[
curFdOff
].
active
)
{
if
(
client
!=
-
1
)
{
/* Already connected, so kick new one out */
fdArray
[
curFdOff
].
active
=
1
;
close
(
fd
)
;
++
numActiv
e
;
continu
e
;
}
}
client
=
fd
;
}
else
if
(
epollEvent
.
events
&
EPOLLHUP
)
{
epollEvent
.
events
=
EPOLLHUP
;
DEBUG
(
"EPOLLHUP from fd %d"
,
epollEvent
.
data
.
fd
);
epollEvent
.
data
.
fd
=
client
;
continue
;
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
client
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(contPty) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
}
else
if
(
client
!=
-
1
&&
epollEvent
.
data
.
fd
==
client
)
{
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_DEL
,
client
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(contPty) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
close
(
client
);
client
=
-
1
;
}
else
{
}
else
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
if
(
epollEvent
.
events
&
EPOLLIN
)
{
_
(
"error event %d"
),
epollEvent
.
events
);
curFdOff
=
epollEvent
.
data
.
fd
==
appPty
?
0
:
1
;
goto
cleanup
;
if
(
!
fdArray
[
curFdOff
].
active
)
{
fdArray
[
curFdOff
].
active
=
1
;
++
numActive
;
}
}
else
if
(
epollEvent
.
events
&
EPOLLHUP
)
{
DEBUG
(
"EPOLLHUP from fd %d"
,
epollEvent
.
data
.
fd
);
continue
;
}
else
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"error event %d"
),
epollEvent
.
events
);
goto
cleanup
;
}
}
}
}
else
if
(
0
==
numEvents
)
{
}
else
if
(
0
==
numEvents
)
{
if
(
2
==
numActive
)
{
if
(
2
==
numActive
)
{
/* both fds active, toggle between the two */
/* both fds active, toggle between the two */
...
@@ -202,4 +252,255 @@ cleanup:
...
@@ -202,4 +252,255 @@ cleanup:
return
rc
;
return
rc
;
}
}
/**
* lxcControllerMoveInterfaces
* @nveths: number of interfaces
* @veths: interface names
* @container: pid of container
*
* Moves network interfaces into a container's namespace
*
* Returns 0 on success or -1 in case of error
*/
static
int
lxcControllerMoveInterfaces
(
unsigned
int
nveths
,
char
**
veths
,
pid_t
container
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
nveths
;
i
++
)
if
(
moveInterfaceToNetNs
(
veths
[
i
],
container
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"failed to move interface %s to ns %d"
),
veths
[
i
],
container
);
return
-
1
;
}
return
0
;
}
/**
* lxcCleanupInterfaces:
* @conn: pointer to connection
* @vm: pointer to virtual machine structure
*
* Cleans up the container interfaces by deleting the veth device pairs.
*
* Returns 0 on success or -1 in case of error
*/
static
int
lxcControllerCleanupInterfaces
(
unsigned
int
nveths
,
char
**
veths
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
nveths
;
i
++
)
if
(
vethDelete
(
veths
[
i
])
<
0
)
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"failed to delete veth: %s"
),
veths
[
i
]);
/* will continue to try to cleanup any other interfaces */
return
0
;
}
static
int
lxcControllerRun
(
const
char
*
stateDir
,
lxc_vm_def_t
*
def
,
unsigned
int
nveths
,
char
**
veths
,
int
monitor
,
int
client
,
int
appPty
)
{
int
rc
=
-
1
;
int
control
[
2
]
=
{
-
1
,
-
1
};
int
containerPty
;
char
*
containerPtyPath
;
pid_t
container
=
-
1
;
if
(
socketpair
(
PF_UNIX
,
SOCK_STREAM
,
0
,
control
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"sockpair failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
if
(
virFileOpenTty
(
&
containerPty
,
&
containerPtyPath
,
0
)
<
0
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"failed to allocate tty: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
if
((
container
=
lxcContainerStart
(
def
,
nveths
,
veths
,
control
[
1
],
containerPtyPath
))
<
0
)
goto
cleanup
;
close
(
control
[
1
]);
control
[
1
]
=
-
1
;
if
(
lxcControllerMoveInterfaces
(
nveths
,
veths
,
container
)
<
0
)
goto
cleanup
;
if
(
lxcContainerSendContinue
(
control
[
0
])
<
0
)
goto
cleanup
;
rc
=
lxcControllerMain
(
monitor
,
client
,
appPty
,
containerPty
);
cleanup:
if
(
control
[
0
]
!=
-
1
)
close
(
control
[
0
]);
if
(
control
[
1
]
!=
-
1
)
close
(
control
[
1
]);
VIR_FREE
(
containerPtyPath
);
if
(
containerPty
!=
-
1
)
close
(
containerPty
);
kill
(
container
,
SIGTERM
);
waitpid
(
container
,
NULL
,
0
);
lxcControllerCleanupInterfaces
(
nveths
,
veths
);
virFileDeletePid
(
stateDir
,
def
->
name
);
return
rc
;
}
int
lxcControllerStart
(
const
char
*
stateDir
,
lxc_vm_def_t
*
def
,
unsigned
int
nveths
,
char
**
veths
,
int
monitor
,
int
appPty
,
int
logfd
)
{
pid_t
pid
;
int
rc
;
int
status
,
null
;
int
open_max
,
i
;
int
client
;
struct
sigaction
sig_action
;
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
pid
>
0
)
{
/* Original caller waits for first child to exit */
while
(
1
)
{
rc
=
waitpid
(
pid
,
&
status
,
0
);
if
(
rc
<
0
)
{
if
(
errno
==
EINTR
)
continue
;
return
-
1
;
}
if
(
rc
!=
pid
)
{
fprintf
(
stderr
,
_
(
"Unexpected pid %d != %d from waitpid
\n
"
),
rc
,
pid
);
return
-
1
;
}
if
(
WIFEXITED
(
status
)
&&
WEXITSTATUS
(
status
)
==
0
)
return
0
;
else
{
fprintf
(
stderr
,
_
(
"Unexpected status %d from pid %d
\n
"
),
status
,
pid
);
return
-
1
;
}
}
}
/* First child is running here */
/* Clobber all libvirtd's signal handlers so they
* don't affect us
*/
sig_action
.
sa_handler
=
SIG_DFL
;
sig_action
.
sa_flags
=
0
;
sigemptyset
(
&
sig_action
.
sa_mask
);
sigaction
(
SIGHUP
,
&
sig_action
,
NULL
);
sigaction
(
SIGINT
,
&
sig_action
,
NULL
);
sigaction
(
SIGQUIT
,
&
sig_action
,
NULL
);
sigaction
(
SIGTERM
,
&
sig_action
,
NULL
);
sigaction
(
SIGCHLD
,
&
sig_action
,
NULL
);
sig_action
.
sa_handler
=
SIG_IGN
;
sigaction
(
SIGPIPE
,
&
sig_action
,
NULL
);
/* Don't hold onto any cwd we inherit from libvirtd either */
if
(
chdir
(
"/"
)
<
0
)
{
fprintf
(
stderr
,
_
(
"Unable to change to root dir: %s
\n
"
),
strerror
(
errno
));
_exit
(
-
1
);
}
if
(
setsid
()
<
0
)
{
fprintf
(
stderr
,
_
(
"Unable to become session leader: %s
\n
"
),
strerror
(
errno
));
_exit
(
-
1
);
}
if
((
null
=
open
(
_PATH_DEVNULL
,
O_RDONLY
))
<
0
)
{
fprintf
(
stderr
,
_
(
"Unable to open %s: %s
\n
"
),
_PATH_DEVNULL
,
strerror
(
errno
));
_exit
(
-
1
);
}
open_max
=
sysconf
(
_SC_OPEN_MAX
);
for
(
i
=
0
;
i
<
open_max
;
i
++
)
if
(
i
!=
appPty
&&
i
!=
monitor
&&
i
!=
logfd
&&
i
!=
null
)
close
(
i
);
if
(
dup2
(
null
,
STDIN_FILENO
)
<
0
||
dup2
(
logfd
,
STDOUT_FILENO
)
<
0
||
dup2
(
logfd
,
STDERR_FILENO
)
<
0
)
{
fprintf
(
stderr
,
_
(
"Unable to redirect stdio: %s
\n
"
),
strerror
(
errno
));
_exit
(
-
1
);
}
close
(
null
);
close
(
logfd
);
/* Now fork the real controller process */
if
((
pid
=
fork
())
<
0
)
{
fprintf
(
stderr
,
_
(
"Unable to fork controller: %s
\n
"
),
strerror
(
errno
));
_exit
(
-
1
);
}
if
(
pid
>
0
)
{
if
((
rc
=
virFileWritePid
(
stateDir
,
def
->
name
,
pid
))
!=
0
)
{
fprintf
(
stderr
,
_
(
"Unable to write pid file: %s
\n
"
),
strerror
(
rc
));
_exit
(
-
1
);
}
/* First child now exits, allowing originall caller to
* complete their waitpid & continue */
_exit
(
0
);
}
/* This is real controller running finally... */
/* Accept initial client which is the libvirtd daemon */
if
((
client
=
accept
(
monitor
,
NULL
,
0
)))
{
fprintf
(
stderr
,
_
(
"Failed connection from LXC driver: %s
\n
"
),
strerror
(
errno
));
_exit
(
-
1
);
}
/* Controlling libvirtd LXC driver now knows
what our PID is, and is able to cleanup after
us from now on */
_exit
(
lxcControllerRun
(
stateDir
,
def
,
nveths
,
veths
,
monitor
,
client
,
appPty
));
}
#endif
#endif
src/lxc_controller.h
浏览文件 @
763dacda
...
@@ -26,7 +26,15 @@
...
@@ -26,7 +26,15 @@
#ifdef WITH_LXC
#ifdef WITH_LXC
int
lxcControllerMain
(
int
appPty
,
int
contPty
);
#include "lxc_conf.h"
int
lxcControllerStart
(
const
char
*
stateDir
,
lxc_vm_def_t
*
def
,
unsigned
int
nveths
,
char
**
veths
,
int
monitor
,
int
appPty
,
int
logfd
);
#endif
/* WITH_LXC */
#endif
/* WITH_LXC */
...
...
src/lxc_driver.c
浏览文件 @
763dacda
此差异已折叠。
点击以展开。
src/util.c
浏览文件 @
763dacda
...
@@ -37,6 +37,9 @@
...
@@ -37,6 +37,9 @@
#include <sys/wait.h>
#include <sys/wait.h>
#endif
#endif
#include <string.h>
#include <string.h>
#if HAVE_TERMIOS_H
#include <termios.h>
#endif
#include "c-ctype.h"
#include "c-ctype.h"
#ifdef HAVE_PATHS_H
#ifdef HAVE_PATHS_H
...
@@ -472,6 +475,169 @@ int virFileBuildPath(const char *dir,
...
@@ -472,6 +475,169 @@ int virFileBuildPath(const char *dir,
return
0
;
return
0
;
}
}
#ifdef __linux__
int
virFileOpenTty
(
int
*
ttymaster
,
char
**
ttyName
,
int
rawmode
)
{
int
rc
=
-
1
;
if
((
*
ttymaster
=
posix_openpt
(
O_RDWR
|
O_NOCTTY
|
O_NONBLOCK
))
<
0
)
goto
cleanup
;
if
(
unlockpt
(
*
ttymaster
)
<
0
)
goto
cleanup
;
if
(
grantpt
(
*
ttymaster
)
<
0
)
goto
cleanup
;
if
(
rawmode
)
{
struct
termios
ttyAttr
;
if
(
tcgetattr
(
*
ttymaster
,
&
ttyAttr
)
<
0
)
goto
cleanup
;
cfmakeraw
(
&
ttyAttr
);
if
(
tcsetattr
(
*
ttymaster
,
TCSADRAIN
,
&
ttyAttr
)
<
0
)
goto
cleanup
;
}
if
(
ttyName
)
{
char
tempTtyName
[
PATH_MAX
];
if
(
ptsname_r
(
*
ttymaster
,
tempTtyName
,
sizeof
(
tempTtyName
))
<
0
)
goto
cleanup
;
if
((
*
ttyName
=
strdup
(
tempTtyName
))
==
NULL
)
{
errno
=
ENOMEM
;
goto
cleanup
;
}
}
rc
=
0
;
cleanup:
if
(
rc
!=
0
&&
*
ttymaster
!=
-
1
)
{
close
(
*
ttymaster
);
}
return
rc
;
}
#else
int
virFileOpenTty
(
int
*
ttymaster
ATTRIBUTE_UNUSED
,
char
**
ttyName
ATTRIBUTE_UNUSED
,
int
rawmode
ATTRIBUTE_UNUSED
)
{
return
-
1
;
}
#endif
int
virFileWritePid
(
const
char
*
dir
,
const
char
*
name
,
pid_t
pid
)
{
int
rc
;
int
fd
;
FILE
*
file
=
NULL
;
char
*
pidfile
=
NULL
;
if
((
rc
=
virFileMakePath
(
dir
)))
goto
cleanup
;
if
(
asprintf
(
&
pidfile
,
"%s/%s.pid"
,
dir
,
name
)
<
0
)
{
rc
=
ENOMEM
;
goto
cleanup
;
}
if
((
fd
=
open
(
pidfile
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
))
<
0
)
{
rc
=
errno
;
goto
cleanup
;
}
if
(
!
(
file
=
fdopen
(
fd
,
"w"
)))
{
rc
=
errno
;
close
(
fd
);
goto
cleanup
;
}
if
(
fprintf
(
file
,
"%d"
,
pid
)
<
0
)
{
rc
=
errno
;
goto
cleanup
;
}
rc
=
0
;
cleanup:
if
(
file
&&
fclose
(
file
)
<
0
)
{
rc
=
errno
;
}
VIR_FREE
(
pidfile
);
return
rc
;
}
int
virFileReadPid
(
const
char
*
dir
,
const
char
*
name
,
pid_t
*
pid
)
{
int
rc
;
FILE
*
file
;
char
*
pidfile
=
NULL
;
*
pid
=
0
;
if
(
asprintf
(
&
pidfile
,
"%s/%s.pid"
,
dir
,
name
)
<
0
)
{
rc
=
ENOMEM
;
goto
cleanup
;
}
if
(
!
(
file
=
fopen
(
pidfile
,
"r"
)))
{
rc
=
errno
;
goto
cleanup
;
}
if
(
fscanf
(
file
,
"%d"
,
pid
)
!=
1
)
{
rc
=
EINVAL
;
goto
cleanup
;
}
if
(
fclose
(
file
)
<
0
)
{
rc
=
errno
;
goto
cleanup
;
}
rc
=
0
;
cleanup:
VIR_FREE
(
pidfile
);
return
rc
;
}
int
virFileDeletePid
(
const
char
*
dir
,
const
char
*
name
)
{
int
rc
=
0
;
char
*
pidfile
=
NULL
;
if
(
asprintf
(
&
pidfile
,
"%s/%s.pid"
,
dir
,
name
)
<
0
)
{
rc
=
errno
;
goto
cleanup
;
}
if
(
unlink
(
pidfile
)
<
0
&&
errno
!=
ENOENT
)
rc
=
errno
;
cleanup:
VIR_FREE
(
pidfile
);
return
rc
;
}
/* Like strtol, but produce an "int" result, and check more carefully.
/* Like strtol, but produce an "int" result, and check more carefully.
Return 0 upon success; return -1 to indicate failure.
Return 0 upon success; return -1 to indicate failure.
When END_PTR is NULL, the byte after the final valid digit must be NUL.
When END_PTR is NULL, the byte after the final valid digit must be NUL.
...
...
src/util.h
浏览文件 @
763dacda
...
@@ -58,6 +58,18 @@ int virFileBuildPath(const char *dir,
...
@@ -58,6 +58,18 @@ int virFileBuildPath(const char *dir,
char
*
buf
,
char
*
buf
,
unsigned
int
buflen
);
unsigned
int
buflen
);
int
virFileOpenTty
(
int
*
ttymaster
,
char
**
ttyName
,
int
rawmode
);
int
virFileWritePid
(
const
char
*
dir
,
const
char
*
name
,
pid_t
pid
);
int
virFileReadPid
(
const
char
*
dir
,
const
char
*
name
,
pid_t
*
pid
);
int
virFileDeletePid
(
const
char
*
dir
,
const
char
*
name
);
int
__virStrToLong_i
(
char
const
*
s
,
int
__virStrToLong_i
(
char
const
*
s
,
char
**
end_ptr
,
char
**
end_ptr
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录