Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.toolbox
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Gabriel Monnerat
slapos.toolbox
Commits
f3aa60e4
Commit
f3aa60e4
authored
Feb 07, 2018
by
Alain Takoudjou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
some improvement
parent
bdd0294a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
217 additions
and
62 deletions
+217
-62
slapos/qemuqmpclient/__init__.py
slapos/qemuqmpclient/__init__.py
+174
-58
slapos/test/test_qemuqmpclient.py
slapos/test/test_qemuqmpclient.py
+43
-4
No files found.
slapos/qemuqmpclient/__init__.py
View file @
f3aa60e4
...
@@ -31,6 +31,8 @@ import os
...
@@ -31,6 +31,8 @@ import os
import
pprint
import
pprint
import
socket
import
socket
import
time
import
time
import
errno
import
psutil
from
operator
import
itemgetter
from
operator
import
itemgetter
def
parseArgument
():
def
parseArgument
():
...
@@ -59,6 +61,37 @@ def parseArgument():
...
@@ -59,6 +61,37 @@ def parseArgument():
parser
.
add_argument
(
'remainding_argument_list'
,
nargs
=
argparse
.
REMAINDER
)
parser
.
add_argument
(
'remainding_argument_list'
,
nargs
=
argparse
.
REMAINDER
)
return
parser
.
parse_args
()
return
parser
.
parse_args
()
def
getInitialQemuResourceDict
(
pid_file
):
"""
Return CPU ad RAM initial values used to start Qemu process
"""
if
not
os
.
path
.
exists
(
pid_file
):
return
None
with
open
(
pid_file
)
as
f
:
pid
=
int
(
f
.
read
())
try
:
process
=
psutil
.
Process
(
pid
)
except
psutil
.
NoSuchProcess
:
print
'No process with pid %s'
%
pid
return
None
resource_dict
=
{
'cpu'
:
None
,
'ram'
:
None
}
cmd_list
=
process
.
cmdline
()
cpu_index
=
cmd_list
.
index
(
'-smp'
)
ram_index
=
cmd_list
.
index
(
'-m'
)
if
cpu_index
>=
0
:
resource_dict
[
'cpu'
]
=
cmd_list
[
cpu_index
+
1
].
split
(
','
)[
0
]
if
ram_index
>=
0
:
resource_dict
[
'ram'
]
=
cmd_list
[
ram_index
+
1
].
split
(
','
)[
0
]
return
resource_dict
class
QmpCommandError
(
Exception
):
pass
class
QmpDeviceRemoveError
(
Exception
):
pass
class
QemuQMPWrapper
(
object
):
class
QemuQMPWrapper
(
object
):
"""
"""
...
@@ -67,8 +100,12 @@ class QemuQMPWrapper(object):
...
@@ -67,8 +100,12 @@ class QemuQMPWrapper(object):
QMP API definition.
QMP API definition.
"""
"""
def
__init__
(
self
,
unix_socket_location
,
auto_connect
=
True
):
def
__init__
(
self
,
unix_socket_location
,
auto_connect
=
True
):
self
.
_event_list
=
[]
self
.
socket
=
None
self
.
sockf
=
None
if
auto_connect
:
if
auto_connect
:
self
.
socket
=
self
.
connectToQemu
(
unix_socket_location
)
self
.
socket
=
self
.
connectToQemu
(
unix_socket_location
)
self
.
sockf
=
self
.
socket
.
makefile
()
self
.
capabilities
()
self
.
capabilities
()
@
staticmethod
@
staticmethod
...
@@ -94,21 +131,26 @@ class QemuQMPWrapper(object):
...
@@ -94,21 +131,26 @@ class QemuQMPWrapper(object):
return
so
return
so
def
_readResponse
(
self
,
only_event
=
False
):
def
_send
(
self
,
message
,
check_result
=
False
):
response
=
None
self
.
socket
.
send
(
json
.
dumps
(
message
))
while
True
:
data
=
self
.
socket
.
recv
(
65535
)
data
=
self
.
sockf
.
readline
()
try
:
if
not
data
:
result
=
json
.
loads
(
data
)
return
if
check_result
and
result
.
get
(
'return'
,
None
)
!=
{}
and
'error'
in
data
:
response
=
json
.
loads
(
data
)
raise
Exception
(
'ERROR: %s'
%
data
)
if
'error'
in
response
:
return
result
raise
QmpCommandError
(
response
[
"error"
][
"desc"
])
except
ValueError
:
if
'event'
in
response
:
# if error the raise
self
.
_event_list
.
append
(
response
)
if
"error"
in
data
:
print
response
raise
Exception
(
'ERROR: %s'
%
data
)
if
not
only_event
:
else
:
continue
print
'Wrong data: %s'
%
data
return
response
def
_send
(
self
,
message
):
self
.
socket
.
sendall
(
json
.
dumps
(
message
))
return
self
.
_readResponse
()
def
_sendRetry
(
self
,
message
):
def
_sendRetry
(
self
,
message
):
"""
"""
...
@@ -143,6 +185,43 @@ class QemuQMPWrapper(object):
...
@@ -143,6 +185,43 @@ class QemuQMPWrapper(object):
print
'Asking for capabilities...'
print
'Asking for capabilities...'
self
.
_send
({
'execute'
:
'qmp_capabilities'
})
self
.
_send
({
'execute'
:
'qmp_capabilities'
})
def
getEventList
(
self
,
timeout
=
0
,
cleanup
=
False
):
"""
Get a list of available QMP events.
"""
if
self
.
socket
is
None
:
return
[]
if
cleanup
:
self
.
cleanupEventList
()
if
not
self
.
_event_list
and
timeout
>
0
:
self
.
socket
.
settimeout
(
timeout
)
try
:
# Read then wait a bit
self
.
_readResponse
(
only_event
=
True
)
except
socket
.
timeout
:
pass
finally
:
self
.
socket
.
settimeout
(
None
)
else
:
self
.
socket
.
setblocking
(
0
)
try
:
self
.
_readResponse
(
only_event
=
True
)
except
socket
.
error
,
err
:
if
err
[
0
]
==
errno
.
EAGAIN
:
# No data available
pass
finally
:
self
.
socket
.
setblocking
(
1
)
return
self
.
_event_list
def
cleanupEventList
(
self
):
"""
Clear current list of pending events.
"""
self
.
__events
=
[]
def
setVNCPassword
(
self
,
password
):
def
setVNCPassword
(
self
,
password
):
# Set VNC password
# Set VNC password
print
'Setting VNC password...'
print
'Setting VNC password...'
...
@@ -267,29 +346,67 @@ class QemuQMPWrapper(object):
...
@@ -267,29 +346,67 @@ class QemuQMPWrapper(object):
return
mem_info_dict
return
mem_info_dict
def
_removeDevice
(
self
,
dev_id
,
command_dict
):
def
_removeDevice
(
self
,
dev_id
,
command_dict
,
auto_reboot
=
False
):
max_retry
=
3
max_retry
=
5
result
=
None
result
=
None
while
max_retry
>
0
and
result
is
None
:
resend
=
True
result
=
self
.
_send
(
command_dict
)
stop_retry
=
False
while
max_retry
>
0
:
max_retry
-=
1
max_retry
-=
1
if
(
not
result
or
result
.
get
(
'return'
,
None
)
!=
{})
and
\
try
:
max_retry
>
0
:
if
resend
:
result
=
self
.
_send
(
command_dict
)
except
QmpCommandError
,
e
:
print
"ERROR: "
,
str
(
e
)
print
"%s
\
n
Retry remove %r in few seconds..."
%
(
result
,
dev_id
)
print
"%s
\
n
Retry remove %r in few seconds..."
%
(
result
,
dev_id
)
time
.
sleep
(
3
)
resend
=
True
result
=
None
else
:
for
event
in
self
.
getEventList
(
timeout
=
2
,
cleanup
=
True
):
if
'ACPI_DEVICE_OST'
==
event
[
'event'
]:
# request was received
resend
=
False
if
'DEVICE_DELETED'
==
event
[
'event'
]:
# device was deleted
stop_retry
=
True
break
if
stop_retry
:
break
elif
result
is
None
and
max_retry
>
0
:
print
"Retry remove %r in few seconds..."
%
dev_id
time
.
sleep
(
2
)
if
result
is
not
None
:
if
result
is
not
None
:
if
result
.
get
(
'return'
,
None
)
!=
{}:
if
result
.
get
(
'return'
,
None
)
==
{}
or
(
'error'
in
result
and
\
if
result
.
get
(
'error'
)
and
\
result
[
'error'
].
get
(
'class'
,
''
)
==
'DeviceNotFound'
):
result
[
'error'
].
get
(
'class'
,
''
)
==
'DeviceNotFound'
:
print
'Device %s was removed.'
%
dev_id
print
'Device %s was removed.'
%
dev_id
return
else
:
raise
ValueError
(
"Error: Could not remove device %s... %s"
%
(
# device was not remove after retries
dev_id
,
result
))
if
not
auto_reboot
:
else
:
raise
ValueError
(
"Cannot remove device %s"
%
dev_id
)
raise
ValueError
(
"Cannot remove device %s"
%
dev_id
)
# try soft reboot of the VM
self
.
powerdown
()
system_exited
=
False
# wait for ~10 seconds if the system exit, else quit Qemu
for
i
in
range
(
0
,
5
):
for
event
in
self
.
getEventList
(
timeout
=
2
,
cleanup
=
True
):
if
event
[
'event'
]
==
'SHUTDOWN'
:
# qemu is about to exit
system_exited
=
True
if
system_exited
:
break
else
:
time
.
sleep
(
2
)
if
not
system_exited
:
# hard reset the VM
print
"Trying hard shutdown of the VM..."
self
.
_send
({
"execute"
:
"quit"
})
raise
QmpDeviceRemoveError
(
"Stopped Qemu in order to remove the device %r"
%
dev_id
)
def
_updateCPU
(
self
,
amount
,
cpu_model
):
def
_updateCPU
(
self
,
amount
,
cpu_model
):
"""
"""
Add or remove CPU according current value
Add or remove CPU according current value
...
@@ -300,8 +417,8 @@ class QemuQMPWrapper(object):
...
@@ -300,8 +417,8 @@ class QemuQMPWrapper(object):
used_socket_id_list
=
[]
used_socket_id_list
=
[]
unremovable_cpu
=
0
unremovable_cpu
=
0
cpu_hotplugable_list
=
self
.
_send
({
cpu_hotplugable_list
=
self
.
_send
({
'execute'
:
'query-hotpluggable-cpus'
'execute'
:
'query-hotpluggable-cpus'
})[
'return'
]
})[
'return'
]
cpu_hotplugable_list
.
reverse
()
cpu_hotplugable_list
.
reverse
()
for
cpu
in
cpu_hotplugable_list
:
for
cpu
in
cpu_hotplugable_list
:
if
cpu
.
get
(
'qom-path'
,
''
)
==
''
:
if
cpu
.
get
(
'qom-path'
,
''
)
==
''
:
...
@@ -350,7 +467,7 @@ class QemuQMPWrapper(object):
...
@@ -350,7 +467,7 @@ class QemuQMPWrapper(object):
self
.
_send
({
self
.
_send
({
'execute'
:
'device_add'
,
'execute'
:
'device_add'
,
'arguments'
:
empty_socket_list
[
i
]
'arguments'
:
empty_socket_list
[
i
]
}
,
check_result
=
True
)
})
# check that hotplugged memery amount is consistent
# check that hotplugged memery amount is consistent
cpu_info
=
self
.
getCPUInfo
()
cpu_info
=
self
.
getCPUInfo
()
...
@@ -360,19 +477,19 @@ class QemuQMPWrapper(object):
...
@@ -360,19 +477,19 @@ class QemuQMPWrapper(object):
" current CPU amount is %s"
%
(
hotplug_amount
,
final_cpu_count
))
" current CPU amount is %s"
%
(
hotplug_amount
,
final_cpu_count
))
print
"Done."
print
"Done."
def
_removeMemory
(
self
,
id_dict
):
def
_removeMemory
(
self
,
id_dict
,
auto_reboot
=
False
):
print
"Trying to remove devices %s, %s..."
%
(
id_dict
[
'id'
],
id_dict
[
'memdev'
])
print
"Trying to remove devices %s, %s..."
%
(
id_dict
[
'id'
],
id_dict
[
'memdev'
])
self
.
_removeDevice
(
id_dict
[
'id'
]
,{
self
.
_removeDevice
(
id_dict
[
'id'
]
,{
'execute'
:
'device_del'
,
'execute'
:
'device_del'
,
'arguments'
:
{
'id'
:
id_dict
[
'id'
]}
'arguments'
:
{
'id'
:
id_dict
[
'id'
]}
})
}
,
auto_reboot
=
auto_reboot
)
# when dimm is removed, remove memdev object
# when dimm is removed, remove memdev object
self
.
_removeDevice
(
id_dict
[
'memdev'
],
{
self
.
_removeDevice
(
id_dict
[
'memdev'
],
{
'execute'
:
'object-del'
,
'execute'
:
'object-del'
,
'arguments'
:
{
'arguments'
:
{
'id'
:
id_dict
[
'memdev'
]
'id'
:
id_dict
[
'memdev'
]
}
}
})
}
,
auto_reboot
=
auto_reboot
)
def
_updateMemory
(
self
,
mem_size
,
slot_size
,
slot_amount
,
allow_reboot
=
False
):
def
_updateMemory
(
self
,
mem_size
,
slot_size
,
slot_amount
,
allow_reboot
=
False
):
"""
"""
...
@@ -417,16 +534,9 @@ class QemuQMPWrapper(object):
...
@@ -417,16 +534,9 @@ class QemuQMPWrapper(object):
'arguments'
:
{
'arguments'
:
{
'id'
:
memdev
'id'
:
memdev
}
}
})
}
,
auto_reboot
=
allow_reboot
)
num_slot_used
=
len
(
memory_id_list
)
num_slot_used
=
len
(
memory_id_list
)
if
num_slot_used
>
0
and
slot_size
!=
memory_id_list
[
0
][
'size'
]:
# XXX - we won't change the defined size of RAM on slots on live,
# restart qemu will allow to change the value
if
allow_reboot
:
self
.
powerdown
()
raise
ValueError
(
"The Size of RAM Slot changed. Rebooting..."
)
if
(
mem_size
%
slot_size
)
!=
0
:
if
(
mem_size
%
slot_size
)
!=
0
:
raise
ValueError
(
"Memory size %r is not a multiple of %r"
%
(
mem_size
,
raise
ValueError
(
"Memory size %r is not a multiple of %r"
%
(
mem_size
,
slot_size
))
slot_size
))
...
@@ -442,22 +552,28 @@ class QemuQMPWrapper(object):
...
@@ -442,22 +552,28 @@ class QemuQMPWrapper(object):
raise
ValueError
(
"Memory size is not valid: %s"
%
option_dict
)
raise
ValueError
(
"Memory size is not valid: %s"
%
option_dict
)
elif
current_size
>
mem_size
:
elif
current_size
>
mem_size
:
# Request to remove memory
# Request to remove memory
if
allow_reboot
:
to_remove_size
=
current_size
-
mem_size
# reboot so new memory size will be configured safely
print
"Removing %s MB of memory..."
%
to_remove_size
self
.
powerdown
()
raise
ValueError
(
"Rebooting because memory size was reduced..."
)
for
i
in
range
(
num_slot_used
,
0
,
-
1
):
# remove all slots that won't be used
slot_remove
=
(
current_size
-
mem_size
)
/
slot_size
index
=
i
-
1
print
"Removing %s memory slots of %s MB..."
%
(
slot_remove
,
slot_size
)
to_remove_size
-=
memory_id_list
[
index
][
'size'
]
if
to_remove_size
>=
0
:
for
i
in
range
(
num_slot_used
,
(
num_slot_used
-
slot_remove
),
-
1
):
self
.
_removeMemory
(
memory_id_list
[
index
],
auto_reboot
=
allow_reboot
)
# remove all slot that won't be used
if
to_remove_size
==
0
:
self
.
_removeMemory
(
memory_id_list
[
i
-
1
])
break
else
:
raise
ValueError
(
"Cannot remove the requested size of memory. "
\
"Remaining to remove: %s, RAM slot size: %s"
%
(
to_remove_size
+
memory_id_list
[
index
][
'size'
],
memory_id_list
[
index
][
'size'
])
)
elif
current_size
<
mem_size
:
elif
current_size
<
mem_size
:
# ask for increase memory
# ask for increase memory
slot_add
=
(
mem_size
-
current_size
)
/
slot_size
slot_add
=
(
mem_size
-
current_size
)
/
slot_size
print
"Adding %s memory slot
s
of %s MB..."
%
(
slot_add
,
slot_size
)
print
"Adding %s memory slot
(s)
of %s MB..."
%
(
slot_add
,
slot_size
)
for
i
in
range
(
0
,
slot_add
):
for
i
in
range
(
0
,
slot_add
):
index
=
num_slot_used
+
i
+
1
index
=
num_slot_used
+
i
+
1
self
.
_send
({
self
.
_send
({
...
@@ -475,7 +591,7 @@ class QemuQMPWrapper(object):
...
@@ -475,7 +591,7 @@ class QemuQMPWrapper(object):
'id'
:
'dimm%s'
%
index
,
'id'
:
'dimm%s'
%
index
,
'memdev'
:
'mem%s'
%
index
'memdev'
:
'mem%s'
%
index
}
}
}
,
check_result
=
True
)
})
# check that hotplugged memery amount is consistent
# check that hotplugged memery amount is consistent
mem_info
=
self
.
getMemoryInfo
()
mem_info
=
self
.
getMemoryInfo
()
...
...
slapos/test/test_qemuqmpclient.py
View file @
f3aa60e4
...
@@ -31,7 +31,7 @@ import os
...
@@ -31,7 +31,7 @@ import os
import
tempfile
import
tempfile
import
shutil
import
shutil
from
slapos.qemuqmpclient
import
QemuQMPWrapper
from
slapos.qemuqmpclient
import
QemuQMPWrapper
,
QmpDeviceRemoveError
class
TestQemuQMPWrapper
(
unittest
.
TestCase
):
class
TestQemuQMPWrapper
(
unittest
.
TestCase
):
...
@@ -43,6 +43,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
...
@@ -43,6 +43,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
self
.
hotplugged_memory_amount
=
0
self
.
hotplugged_memory_amount
=
0
# slot of 1G
# slot of 1G
self
.
memory_slot_size
=
1024
self
.
memory_slot_size
=
1024
self
.
event_list
=
[]
self
.
fail
=
False
def
tearDown
(
self
):
def
tearDown
(
self
):
if
os
.
path
.
exists
(
self
.
base_dir
):
if
os
.
path
.
exists
(
self
.
base_dir
):
...
@@ -73,8 +75,16 @@ class TestQemuQMPWrapper(unittest.TestCase):
...
@@ -73,8 +75,16 @@ class TestQemuQMPWrapper(unittest.TestCase):
self
.
setChange
(
'dimm'
,
-
1
*
self
.
memory_slot_size
)
self
.
setChange
(
'dimm'
,
-
1
*
self
.
memory_slot_size
)
if
message
[
'arguments'
][
'id'
].
startswith
(
'cpu'
):
if
message
[
'arguments'
][
'id'
].
startswith
(
'cpu'
):
self
.
setChange
(
'cpu'
,
-
1
)
self
.
setChange
(
'cpu'
,
-
1
)
if
self
.
fail
:
return
{
"error"
:
{
"class"
:
"CommandFailed"
,
"message"
:
""
}}
return
{
"return"
:
{}}
return
{
"return"
:
{}}
def
fake_getEventList
(
self
,
timeout
=
0
,
cleanup
=
False
):
if
self
.
event_list
:
return
self
.
event_list
else
:
return
[]
def
returnQueryResult
(
self
,
message
):
def
returnQueryResult
(
self
,
message
):
if
message
[
'execute'
]
==
'query-hotpluggable-cpus'
:
if
message
[
'execute'
]
==
'query-hotpluggable-cpus'
:
# return 4 hotpluggable cpu slots
# return 4 hotpluggable cpu slots
...
@@ -263,6 +273,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
...
@@ -263,6 +273,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
self
.
free_cpu_slot_amount
=
2
self
.
free_cpu_slot_amount
=
2
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
getEventList
=
self
.
fake_getEventList
self
.
event_list
=
[{
"event"
:
"DEVICE_DELETED"
}]
# add 2 more cpu
# add 2 more cpu
cpu_option
=
{
cpu_option
=
{
'device'
:
'cpu'
,
'device'
:
'cpu'
,
...
@@ -397,6 +409,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
...
@@ -397,6 +409,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
def
test_updateDevice_memory_delete
(
self
):
def
test_updateDevice_memory_delete
(
self
):
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
getEventList
=
self
.
fake_getEventList
self
.
event_list
=
[{
"event"
:
"DEVICE_DELETED"
}]
self
.
hotplugged_memory_amount
=
3072
self
.
hotplugged_memory_amount
=
3072
# slot of 1G
# slot of 1G
self
.
memory_slot_size
=
1024
self
.
memory_slot_size
=
1024
...
@@ -436,6 +450,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
...
@@ -436,6 +450,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
def
test_updateDevice_memory_delete_all
(
self
):
def
test_updateDevice_memory_delete_all
(
self
):
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
getEventList
=
self
.
fake_getEventList
self
.
event_list
=
[{
"event"
:
"DEVICE_DELETED"
}]
self
.
hotplugged_memory_amount
=
3072
self
.
hotplugged_memory_amount
=
3072
# slot of 1G
# slot of 1G
self
.
memory_slot_size
=
1024
self
.
memory_slot_size
=
1024
...
@@ -505,6 +521,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
...
@@ -505,6 +521,8 @@ class TestQemuQMPWrapper(unittest.TestCase):
def
test_updateDevice_memory_will_reboot
(
self
):
def
test_updateDevice_memory_will_reboot
(
self
):
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
=
QemuQMPWrapper
(
self
.
socket_file
,
auto_connect
=
False
)
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
_send
=
self
.
fake_send
qmpwrapper
.
getEventList
=
self
.
fake_getEventList
self
.
fail
=
True
self
.
hotplugged_memory_amount
=
3072
self
.
hotplugged_memory_amount
=
3072
# slot of 1G
# slot of 1G
self
.
memory_slot_size
=
1024
self
.
memory_slot_size
=
1024
...
@@ -516,15 +534,36 @@ class TestQemuQMPWrapper(unittest.TestCase):
...
@@ -516,15 +534,36 @@ class TestQemuQMPWrapper(unittest.TestCase):
'slot'
:
self
.
memory_slot_size
,
'slot'
:
self
.
memory_slot_size
,
'canreboot'
:
True
'canreboot'
:
True
}
}
with
self
.
assertRaises
(
Valu
eError
):
with
self
.
assertRaises
(
QmpDeviceRemov
eError
):
qmpwrapper
.
updateDevice
(
cpu_option
)
qmpwrapper
.
updateDevice
(
cpu_option
)
expected_result
=
[
expected_result
=
[
{
'execute'
:
'query-memory-devices'
},
{
'execute'
:
'query-memory-devices'
},
{
'execute'
:
'query-memdev'
},
{
'execute'
:
'query-memdev'
},
{
'execute'
:
'system_powerdown'
}
{
'execute'
:
'device_del'
,
'arguments'
:
{
'id'
:
u'dimm3'
}
},
{
'execute'
:
'device_del'
,
'arguments'
:
{
'id'
:
u'dimm3'
}
},
{
'execute'
:
'device_del'
,
'arguments'
:
{
'id'
:
u'dimm3'
}
},
{
'execute'
:
'device_del'
,
'arguments'
:
{
'id'
:
u'dimm3'
}
},
{
'execute'
:
'device_del'
,
'arguments'
:
{
'id'
:
u'dimm3'
}
},
{
'execute'
:
'system_powerdown'
},
{
'execute'
:
'quit'
}
]
]
self
.
assertEquals
(
len
(
self
.
call_stack_list
),
3
)
self
.
assertEquals
(
len
(
self
.
call_stack_list
),
9
)
self
.
assertEquals
(
self
.
call_stack_list
,
expected_result
)
self
.
assertEquals
(
self
.
call_stack_list
,
expected_result
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment