mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Add virt.volume_defined state
In order to help creating storage volumes in virtual storage pools from states, add a virt.volume_defined state.
This commit is contained in:
parent
1a45660920
commit
a7218588ae
2 changed files with 706 additions and 2 deletions
|
@ -23,7 +23,7 @@ import salt.utils.args
|
|||
import salt.utils.files
|
||||
import salt.utils.stringutils
|
||||
import salt.utils.versions
|
||||
from salt.exceptions import CommandExecutionError
|
||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||
|
||||
# Import 3rd-party libs
|
||||
from salt.ext import six
|
||||
|
@ -1545,3 +1545,149 @@ def pool_deleted(name, purge=False, connection=None, username=None, password=Non
|
|||
ret["result"] = False
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def volume_defined(
|
||||
pool,
|
||||
name,
|
||||
size,
|
||||
allocation=0,
|
||||
format=None,
|
||||
type=None,
|
||||
permissions=None,
|
||||
backing_store=None,
|
||||
nocow=False,
|
||||
connection=None,
|
||||
username=None,
|
||||
password=None,
|
||||
):
|
||||
"""
|
||||
Ensure a disk volume is existing.
|
||||
|
||||
:param pool: name of the pool containing the volume
|
||||
:param name: name of the volume
|
||||
:param size: capacity of the volume to define in MiB
|
||||
:param allocation: allocated size of the volume in MiB. Defaults to 0.
|
||||
:param format:
|
||||
volume format. The allowed values are depending on the pool type.
|
||||
Check the virt.pool_capabilities output for the possible values and the default.
|
||||
:param type:
|
||||
type of the volume. One of file, block, dir, network, netdiri, ploop or None.
|
||||
By default, the type is guessed by libvirt from the pool type.
|
||||
:param permissions:
|
||||
Permissions to set on the target folder. This is mostly used for filesystem-based
|
||||
pool types. See :ref:`pool-define-permissions` for more details on this structure.
|
||||
:param backing_store:
|
||||
dictionary describing a backing file for the volume. It must contain a ``path``
|
||||
property pointing to the base volume and a ``format`` property defining the format
|
||||
of the base volume.
|
||||
|
||||
The base volume format will not be guessed for security reasons and is thus mandatory.
|
||||
:param nocow: disable COW for the volume.
|
||||
:param connection: libvirt connection URI, overriding defaults
|
||||
:param username: username to connect with, overriding defaults
|
||||
:param password: password to connect with, overriding defaults
|
||||
|
||||
.. rubric:: CLI Example:
|
||||
|
||||
Volume on ESX:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
esx_volume:
|
||||
virt.volume_defined:
|
||||
- pool: "[local-storage]"
|
||||
- name: myvm/myvm.vmdk
|
||||
- size: 8192
|
||||
|
||||
QCow2 volume with backing file:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
myvolume:
|
||||
virt.volume_defined:
|
||||
- pool: default
|
||||
- name: myvm.qcow2
|
||||
- format: qcow2
|
||||
- size: 8192
|
||||
- permissions:
|
||||
mode: '0775'
|
||||
owner: '123'
|
||||
group: '345'
|
||||
- backing_store:
|
||||
path: /path/to/base.img
|
||||
format: raw
|
||||
- nocow: True
|
||||
|
||||
.. versionadded:: Sodium
|
||||
"""
|
||||
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
|
||||
|
||||
pools = __salt__["virt.list_pools"](
|
||||
connection=connection, username=username, password=password
|
||||
)
|
||||
if pool not in pools:
|
||||
raise SaltInvocationError("Storage pool {} not existing".format(pool))
|
||||
|
||||
vol_infos = (
|
||||
__salt__["virt.volume_infos"](
|
||||
pool, name, connection=connection, username=username, password=password
|
||||
)
|
||||
.get(pool, {})
|
||||
.get(name)
|
||||
)
|
||||
|
||||
if vol_infos:
|
||||
ret["comment"] = "volume is existing"
|
||||
# if backing store or format are different, return an error
|
||||
backing_store_info = vol_infos.get("backing_store") or {}
|
||||
same_backing_store = backing_store_info.get("path") == (
|
||||
backing_store or {}
|
||||
).get("path") and backing_store_info.get("format") == (backing_store or {}).get(
|
||||
"format"
|
||||
)
|
||||
if not same_backing_store or (
|
||||
vol_infos.get("format") != format and format is not None
|
||||
):
|
||||
ret["result"] = False
|
||||
ret[
|
||||
"comment"
|
||||
] = "A volume with the same name but different backing store or format is existing"
|
||||
return ret
|
||||
|
||||
# otherwise assume the volume has already been defined
|
||||
# if the sizes don't match, issue a warning comment: too dangerous to do this for now
|
||||
if int(vol_infos.get("capacity")) != int(size) * 1024 * 1024:
|
||||
ret[
|
||||
"comment"
|
||||
] = "The capacity of the volume is different, but no resize performed"
|
||||
return ret
|
||||
|
||||
ret["result"] = None if __opts__["test"] else True
|
||||
test_comment = "would be "
|
||||
try:
|
||||
if not __opts__["test"]:
|
||||
__salt__["virt.volume_define"](
|
||||
pool,
|
||||
name,
|
||||
size,
|
||||
allocation=allocation,
|
||||
format=format,
|
||||
type=type,
|
||||
permissions=permissions,
|
||||
backing_store=backing_store,
|
||||
nocow=nocow,
|
||||
connection=connection,
|
||||
username=username,
|
||||
password=password,
|
||||
)
|
||||
test_comment = ""
|
||||
|
||||
ret["comment"] = "Volume {} {}defined in pool {}".format(
|
||||
name, test_comment, pool
|
||||
)
|
||||
ret["changes"] = {"{}/{}".format(pool, name): {"old": "", "new": "defined"}}
|
||||
except libvirt.libvirtError as err:
|
||||
ret["comment"] = err.get_error_message()
|
||||
ret["result"] = False
|
||||
return ret
|
||||
|
|
|
@ -11,7 +11,7 @@ import tempfile
|
|||
# Import Salt Libs
|
||||
import salt.states.virt as virt
|
||||
import salt.utils.files
|
||||
from salt.exceptions import CommandExecutionError
|
||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||
|
||||
# Import 3rd-party libs
|
||||
from salt.ext import six
|
||||
|
@ -2756,3 +2756,561 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(virt.__opts__, {"test": True}):
|
||||
expected["result"] = None
|
||||
self.assertDictEqual(expected, virt.pool_deleted("test01", purge=True))
|
||||
|
||||
def test_volume_defined(self):
|
||||
"""
|
||||
test the virt.volume_defined state
|
||||
"""
|
||||
with patch.dict(virt.__opts__, {"test": False}):
|
||||
# test case: creating a volume
|
||||
define_mock = MagicMock()
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(return_value={"mypool": {}}),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {"mypool/myvol": {"old": "", "new": "defined"}},
|
||||
"result": True,
|
||||
"comment": "Volume myvol defined in pool mypool",
|
||||
},
|
||||
)
|
||||
define_mock.assert_called_once_with(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
)
|
||||
|
||||
# test case: with existing volume
|
||||
define_mock.reset_mock()
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "qcow2",
|
||||
"capacity": "1293942784",
|
||||
"backing_store": {
|
||||
"path": "/path/to/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": True,
|
||||
"comment": "volume is existing",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different sizes
|
||||
define_mock.reset_mock()
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "qcow2",
|
||||
"capacity": "12345",
|
||||
"backing_store": {
|
||||
"path": "/path/to/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": True,
|
||||
"comment": "The capacity of the volume is different, but no resize performed",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different backing store
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "qcow2",
|
||||
"capacity": "1234",
|
||||
"backing_store": {
|
||||
"path": "/path/to/other/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": False,
|
||||
"comment": "A volume with the same name but different backing store or format is existing",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different format
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "raw",
|
||||
"capacity": "1234",
|
||||
"backing_store": {
|
||||
"path": "/path/to/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": False,
|
||||
"comment": "A volume with the same name but different backing store or format is existing",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: no pool
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "qcow2",
|
||||
"capacity": "1234",
|
||||
"backing_store": {
|
||||
"path": "/path/to/other/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": False,
|
||||
"comment": "A volume with the same name but different backing store or format is existing",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different format
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=[]),
|
||||
"virt.volume_infos": MagicMock(return_value={}),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertRaisesRegex(
|
||||
SaltInvocationError,
|
||||
"Storage pool mypool not existing",
|
||||
virt.volume_defined,
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
)
|
||||
|
||||
# Test mode cases
|
||||
with patch.dict(virt.__opts__, {"test": True}):
|
||||
# test case: creating a volume
|
||||
define_mock.reset_mock()
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(return_value={"mypool": {}}),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {"mypool/myvol": {"old": "", "new": "defined"}},
|
||||
"result": None,
|
||||
"comment": "Volume myvol would be defined in pool mypool",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different sizes
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "qcow2",
|
||||
"capacity": "12345",
|
||||
"backing_store": {
|
||||
"path": "/path/to/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": True,
|
||||
"comment": "The capacity of the volume is different, but no resize performed",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different backing store
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "qcow2",
|
||||
"capacity": "1234",
|
||||
"backing_store": {
|
||||
"path": "/path/to/other/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": False,
|
||||
"comment": "A volume with the same name but different backing store or format is existing",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different format
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "raw",
|
||||
"capacity": "1234",
|
||||
"backing_store": {
|
||||
"path": "/path/to/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": False,
|
||||
"comment": "A volume with the same name but different backing store or format is existing",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: no pool
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=["mypool"]),
|
||||
"virt.volume_infos": MagicMock(
|
||||
return_value={
|
||||
"mypool": {
|
||||
"myvol": {
|
||||
"format": "qcow2",
|
||||
"capacity": "1234",
|
||||
"backing_store": {
|
||||
"path": "/path/to/other/image",
|
||||
"format": "raw",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertDictEqual(
|
||||
virt.volume_defined(
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
),
|
||||
{
|
||||
"name": "myvol",
|
||||
"changes": {},
|
||||
"result": False,
|
||||
"comment": "A volume with the same name but different backing store or format is existing",
|
||||
},
|
||||
)
|
||||
define_mock.assert_not_called()
|
||||
|
||||
# test case: with existing volume, different format
|
||||
with patch.dict(
|
||||
virt.__salt__,
|
||||
{
|
||||
"virt.list_pools": MagicMock(return_value=[]),
|
||||
"virt.volume_infos": MagicMock(return_value={}),
|
||||
"virt.volume_define": define_mock,
|
||||
},
|
||||
):
|
||||
self.assertRaisesRegex(
|
||||
SaltInvocationError,
|
||||
"Storage pool mypool not existing",
|
||||
virt.volume_defined,
|
||||
"mypool",
|
||||
"myvol",
|
||||
"1234",
|
||||
allocation="12345",
|
||||
format="qcow2",
|
||||
type="file",
|
||||
permissions={"mode": "0755", "owner": "123", "group": "456"},
|
||||
backing_store={"path": "/path/to/image", "format": "raw"},
|
||||
nocow=True,
|
||||
connection="test:///",
|
||||
username="jdoe",
|
||||
password="supersecret",
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue