mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
add volume, list_images, snapshot methods and tests
This commit is contained in:
parent
3f3565429c
commit
277933e8d8
@ -197,12 +197,8 @@ def reboot_node(node_id, profile, **libcloud_kwargs):
|
||||
salt myminion libcloud_compute.reboot_node as-2346 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
matches = [node for node in conn.list_nodes(**libcloud_kwargs) if node.id == node_id]
|
||||
if len(matches) == 0:
|
||||
raise ValueError('Could not find a matching node')
|
||||
elif len(matches) > 1:
|
||||
raise ValueError('The node_id matched {0} nodes, not 1'.format(len(matches)))
|
||||
return conn.reboot_node(matches[0], **libcloud_kwargs)
|
||||
node = _get_by_id(conn.list_nodes(**libcloud_kwargs), node_id)
|
||||
return conn.reboot_node(node, **libcloud_kwargs)
|
||||
|
||||
|
||||
def destroy_node(node_id, profile, **libcloud_kwargs):
|
||||
@ -225,12 +221,8 @@ def destroy_node(node_id, profile, **libcloud_kwargs):
|
||||
salt myminion libcloud_compute.destry_node as-2346 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
matches = [node for node in conn.list_nodes(**libcloud_kwargs) if node.id == node_id]
|
||||
if len(matches) == 0:
|
||||
raise ValueError('Could not find a matching node')
|
||||
elif len(matches) > 1:
|
||||
raise ValueError('The node_id matched {0} nodes, not 1'.format(len(matches)))
|
||||
return conn.destroy_node(matches[0], **libcloud_kwargs)
|
||||
node = _get_by_id(conn.list_nodes(**libcloud_kwargs), node_id)
|
||||
return conn.destroy_node(node, **libcloud_kwargs)
|
||||
|
||||
|
||||
def list_volumes(profile, **libcloud_kwargs):
|
||||
@ -258,19 +250,254 @@ def list_volumes(profile, **libcloud_kwargs):
|
||||
ret.append(_simple_volume(volume))
|
||||
return ret
|
||||
|
||||
|
||||
def list_volume_snapshots(volume_id, profile, **libcloud_kwargs):
|
||||
'''
|
||||
Return a list of storage volumes snapshots for this cloud
|
||||
|
||||
:param volume_id: The volume identifier
|
||||
:type volume_id: ``str``
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's list_volume_snapshots method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.list_volume_snapshots vol1 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
volume = _get_by_id(conn.list_volumes(), volume_id)
|
||||
snapshots = conn.list_volume_snapshots(volume, **libcloud_kwargs)
|
||||
|
||||
ret = []
|
||||
for snapshot in snapshots:
|
||||
ret.append(_simple_volume_snapshot(snapshot))
|
||||
return ret
|
||||
|
||||
def create_volume(size, name, profile, location_id=None, **libcloud_kwargs):
|
||||
'''
|
||||
Create a storage volume
|
||||
|
||||
:param size: Size of volume in gigabytes (required)
|
||||
:type size: ``int``
|
||||
|
||||
:param name: Name of the volume to be created
|
||||
:type name: ``str``
|
||||
|
||||
:param location_id: Which data center to create a volume in. If
|
||||
empty, undefined behavior will be selected.
|
||||
(optional)
|
||||
:type location_id: ``str``
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's list_volumes method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.create_volume 1000 vol1 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
if location_id is not None:
|
||||
location = _get_by_id(conn.list_locations(), location_id)
|
||||
else:
|
||||
location = None
|
||||
# TODO : Support creating from volume snapshot
|
||||
|
||||
volume = conn.create_volume(size, name, location, snapshot=None, **libcloud_kwargs)
|
||||
return _simple_volume(volume)
|
||||
|
||||
|
||||
def create_volume_snapshot(volume_id, profile, name=None, **libcloud_kwargs):
|
||||
'''
|
||||
Create a storage volume snapshot
|
||||
|
||||
:param volume_id: Volume ID from which to create the new
|
||||
snapshot.
|
||||
:type volume_id: ``str``
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param name: Name of the snapshot to be created (optional)
|
||||
:type name: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's create_volume_snapshot method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.create_volume_snapshot vol1 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
volume = _get_by_id(conn.list_volumes(), volume_id)
|
||||
|
||||
snapshot = conn.create_volume_snapshot(volume, name=name, **libcloud_kwargs)
|
||||
return _simple_volume_snapshot(snapshot)
|
||||
|
||||
|
||||
def attach_volume(node_id, volume_id, profile, device=None, **libcloud_kwargs):
|
||||
'''
|
||||
Attaches volume to node.
|
||||
|
||||
:param node_id: Node ID to target
|
||||
:type node_id: ``str``
|
||||
|
||||
:param volume_id: Volume ID from which to attach
|
||||
:type volume_id: ``str``
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param device: Where the device is exposed, e.g. '/dev/sdb'
|
||||
:type device: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's attach_volume method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.detach_volume vol1 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
volume = _get_by_id(conn.list_volumes(), volume_id)
|
||||
node = _get_by_id(conn.list_nodes(), node_id)
|
||||
return conn.attach_volume(node, volume, device=device, **libcloud_kwargs)
|
||||
|
||||
|
||||
def detach_volume(volume_id, profile, **libcloud_kwargs):
|
||||
'''
|
||||
Detaches a volume from a node.
|
||||
|
||||
:param volume_id: Volume ID from which to detach
|
||||
:type volume_id: ``str``
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's detach_volume method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.detach_volume vol1 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
volume = _get_by_id(conn.list_volumes(), volume_id)
|
||||
return conn.detach_volume(volume, **libcloud_kwargs)
|
||||
|
||||
|
||||
def destroy_volume(volume_id, profile, **libcloud_kwargs):
|
||||
'''
|
||||
Destroy a volume.
|
||||
|
||||
:param volume_id: Volume ID from which to destroy
|
||||
:type volume_id: ``str``
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's destroy_volume method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.destroy_volume vol1 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
volume = _get_by_id(conn.list_volumes(), volume_id)
|
||||
return conn.destroy_volume(volume, **libcloud_kwargs)
|
||||
|
||||
|
||||
def destroy_volume_snapshot(volume_id, snapshot_id, profile, **libcloud_kwargs):
|
||||
'''
|
||||
Destroy a volume snapshot.
|
||||
|
||||
:param volume_id: Volume ID from which the snapshot belongs
|
||||
:type volume_id: ``str``
|
||||
|
||||
:param snapshot_id: Volume Snapshot ID from which to destroy
|
||||
:type snapshot_id: ``str``
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's destroy_volume_snapshot method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.destroy_volume_snapshot snap1 profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
volume = _get_by_id(conn.list_volumes(), volume_id)
|
||||
snapshot = _get_by_id(conn.list_volume_snapshots(volume), snapshot_id)
|
||||
return conn.destroy_volume_snapshot(snapshot, **libcloud_kwargs)
|
||||
|
||||
|
||||
def list_images(profile, location_id=None, **libcloud_kwargs):
|
||||
'''
|
||||
Return a list of images for this cloud
|
||||
|
||||
:param profile: The profile key
|
||||
:type profile: ``str``
|
||||
|
||||
:param location_id: The location key, from list_locations
|
||||
:type location_id: ``str``
|
||||
|
||||
:param libcloud_kwargs: Extra arguments for the driver's list_images method
|
||||
:type libcloud_kwargs: ``dict``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion libcloud_compute.list_images profile1
|
||||
'''
|
||||
conn = _get_driver(profile=profile)
|
||||
libcloud_kwargs = clean_kwargs(**libcloud_kwargs)
|
||||
if location_id is not None:
|
||||
location = _get_by_id(conn.list_locations(), location_id)
|
||||
else:
|
||||
location = None
|
||||
images = conn.list_images(location=location, **libcloud_kwargs)
|
||||
|
||||
ret = []
|
||||
for image in images:
|
||||
ret.append(_simple_image(image))
|
||||
return ret
|
||||
|
||||
'''
|
||||
Remaining functions to implement:
|
||||
|
||||
def create_node(self, **kwargs):
|
||||
def deploy_node(self, **kwargs):
|
||||
def list_volume_snapshots(self, volume):
|
||||
def create_volume(self, size, name, location=None, snapshot=None):
|
||||
def create_volume_snapshot(self, volume, name=None):
|
||||
def attach_volume(self, node, volume, device=None):
|
||||
def detach_volume(self, volume):
|
||||
def destroy_volume(self, volume):
|
||||
def destroy_volume_snapshot(self, snapshot):
|
||||
def list_images(self, location=None):
|
||||
def create_image(self, node, name, description=None):
|
||||
def delete_image(self, node_image):
|
||||
def get_image(self, image_id):
|
||||
@ -282,6 +509,17 @@ Remaining functions to implement:
|
||||
def import_key_pair_from_file(self, name, key_file_path):
|
||||
def delete_key_pair(self, key_pair):
|
||||
'''
|
||||
def _get_by_id(collection, id):
|
||||
'''
|
||||
Get item from a list by the id field
|
||||
'''
|
||||
matches = [item for item in collection if item.id == id]
|
||||
if len(matches) == 0:
|
||||
raise ValueError('Could not find a matching item')
|
||||
elif len(matches) > 1:
|
||||
raise ValueError('The id matched {0} items, not 1'.format(len(matches)))
|
||||
return matches[0]
|
||||
|
||||
|
||||
def _simple_volume(volume):
|
||||
return {
|
||||
@ -323,3 +561,22 @@ def _simple_node(node):
|
||||
'size': _simple_size(node.size) if node.size else {},
|
||||
'extra': node.extra
|
||||
}
|
||||
|
||||
|
||||
def _simple_volume_snapshot(snapshot):
|
||||
return {
|
||||
'id': snapshot.id,
|
||||
'name': snapshot.name,
|
||||
'size': snapshot.size,
|
||||
'extra': snapshot.extra,
|
||||
'created': snapshot.created,
|
||||
'state': snapshot.state
|
||||
}
|
||||
|
||||
|
||||
def _simple_image(image):
|
||||
return {
|
||||
'id': image.id,
|
||||
'name': image.name,
|
||||
'extra': image.extra,
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ import salt.modules.libcloud_compute as libcloud_compute
|
||||
|
||||
from libcloud.compute.base import (BaseDriver, Node,
|
||||
NodeSize, NodeState, NodeLocation,
|
||||
StorageVolume, StorageVolumeState)
|
||||
StorageVolume, StorageVolumeState,
|
||||
VolumeSnapshot, NodeImage)
|
||||
|
||||
|
||||
class MockComputeDriver(BaseDriver):
|
||||
@ -48,6 +49,21 @@ class MockComputeDriver(BaseDriver):
|
||||
'ex_key': 'ex_value'
|
||||
}
|
||||
)
|
||||
self._TEST_VOLUME_SNAPSHOT = VolumeSnapshot(
|
||||
id='snap1',
|
||||
name='snap_name',
|
||||
size=80960,
|
||||
driver=self
|
||||
)
|
||||
self._TEST_IMAGE = NodeImage(
|
||||
id='image1',
|
||||
name='test_image',
|
||||
extra={
|
||||
'ex_key': 'ex_value'
|
||||
},
|
||||
driver=self
|
||||
)
|
||||
|
||||
|
||||
def list_nodes(self):
|
||||
return [self._TEST_NODE]
|
||||
@ -71,6 +87,47 @@ class MockComputeDriver(BaseDriver):
|
||||
def list_volumes(self):
|
||||
return [self._TEST_VOLUME]
|
||||
|
||||
def list_volume_snapshots(self, volume):
|
||||
assert volume.id == 'vol1'
|
||||
return [self._TEST_VOLUME_SNAPSHOT]
|
||||
|
||||
def create_volume(self, size, name, location=None, snapshot=None):
|
||||
assert size == 9000
|
||||
assert name == 'test_new_volume'
|
||||
if location:
|
||||
assert location.country == 'Australia'
|
||||
return self._TEST_VOLUME
|
||||
|
||||
def create_volume_snapshot(self, volume, name=None):
|
||||
assert volume.id == 'vol1'
|
||||
if name:
|
||||
assert name == 'test_snapshot'
|
||||
return self._TEST_VOLUME_SNAPSHOT
|
||||
|
||||
def attach_volume(self, node, volume, device=None):
|
||||
assert node.id == 'test_id'
|
||||
assert volume.id == 'vol1'
|
||||
if device:
|
||||
assert device == '/dev/sdc'
|
||||
return True
|
||||
|
||||
def detach_volume(self, volume):
|
||||
assert volume.id == 'vol1'
|
||||
return True
|
||||
|
||||
def destroy_volume(self, volume):
|
||||
assert volume.id == 'vol1'
|
||||
return True
|
||||
|
||||
def destroy_volume_snapshot(self, snapshot):
|
||||
assert snapshot.id == 'snap1'
|
||||
return True
|
||||
|
||||
def list_images(self, location=None):
|
||||
if location:
|
||||
assert location.id == 'test_location'
|
||||
return [self._TEST_IMAGE]
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
@patch('salt.modules.libcloud_compute._get_driver',
|
||||
@ -126,6 +183,16 @@ class LibcloudComputeModuleTestCase(TestCase, LoaderModuleMockMixin):
|
||||
self.assertEqual(volume['state'], 'available')
|
||||
self.assertEqual(volume['extra'], {'ex_key': 'ex_value'})
|
||||
|
||||
def _validate_volume_snapshot(self, volume):
|
||||
self.assertEqual(volume['id'], 'snap1')
|
||||
self.assertEqual(volume['name'], 'snap_name')
|
||||
self.assertEqual(volume['size'], 80960)
|
||||
|
||||
def _validate_image(self, image):
|
||||
self.assertEqual(image['id'], 'image1')
|
||||
self.assertEqual(image['name'], 'test_image')
|
||||
self.assertEqual(image['extra'], {'ex_key': 'ex_value'})
|
||||
|
||||
def test_list_nodes(self):
|
||||
nodes = libcloud_compute.list_nodes('test')
|
||||
self.assertEqual(len(nodes), 1)
|
||||
@ -166,3 +233,50 @@ class LibcloudComputeModuleTestCase(TestCase, LoaderModuleMockMixin):
|
||||
volumes = libcloud_compute.list_volumes('test')
|
||||
self.assertEqual(len(volumes), 1)
|
||||
self._validate_volume(volumes[0])
|
||||
|
||||
def test_list_volume_snapshots(self):
|
||||
volumes = libcloud_compute.list_volume_snapshots('vol1', 'test')
|
||||
self.assertEqual(len(volumes), 1)
|
||||
self._validate_volume_snapshot(volumes[0])
|
||||
|
||||
def test_create_volume(self):
|
||||
volume = libcloud_compute.create_volume(9000, 'test_new_volume', 'test')
|
||||
self._validate_volume(volume)
|
||||
|
||||
def test_create_volume_in_location(self):
|
||||
volume = libcloud_compute.create_volume(9000, 'test_new_volume', 'test', location_id='test_location')
|
||||
self._validate_volume(volume)
|
||||
|
||||
def test_create_volume_snapshot(self):
|
||||
snapshot = libcloud_compute.create_volume_snapshot('vol1', 'test')
|
||||
self._validate_volume_snapshot(snapshot)
|
||||
|
||||
def test_create_volume_snapshot_named(self):
|
||||
snapshot = libcloud_compute.create_volume_snapshot('vol1', 'test', name='test_snapshot')
|
||||
self._validate_volume_snapshot(snapshot)
|
||||
|
||||
def test_attach_volume(self):
|
||||
result = libcloud_compute.attach_volume('test_id', 'vol1', 'test')
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_detatch_volume(self):
|
||||
result = libcloud_compute.detach_volume('vol1', 'test')
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_destroy_volume(self):
|
||||
result = libcloud_compute.destroy_volume('vol1', 'test')
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_destroy_volume_snapshot(self):
|
||||
result = libcloud_compute.destroy_volume_snapshot('vol1', 'snap1', 'test')
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_list_images(self):
|
||||
images = libcloud_compute.list_images('test')
|
||||
self.assertEqual(len(images), 1)
|
||||
self._validate_image(images[0])
|
||||
|
||||
def test_list_images_in_location(self):
|
||||
images = libcloud_compute.list_images('test', location_id='test_location')
|
||||
self.assertEqual(len(images), 1)
|
||||
self._validate_image(images[0])
|
||||
|
Loading…
Reference in New Issue
Block a user