mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 09:23:56 +00:00
1494c44918
Usage of GlusterFS states did not change except the state 'created' was deprecated in favor of more descriptive name 'volume_present'. - Improved separation of functionality in the execution module from the states. Module functions now return booleans instead of varying strings. Parsing those strings in the states was very error-prone. In glusterfs.peer() function this problem was earlier solved by returning a dict containing both the exit value and output string of the gluster call. This could be a good idea, although without calling the gluster calls twice, and applied to other functios too. - Calls to gluster are now logged more verbosely, while a failing call no longer raises an immediate exception. - Improved checking and verbosity in the state level. Cleaned code a lot, removed some bugs and other odd behaviour. - Updated tests to match the changes. Refactored some test code to be more readable. Added assertions to test that some functions are not called when things are already in the desired state. Preferred changing behaviour of the mocked functions while proceeding instead of listing all of the return values first. - Replaced glusterfs.list_peers() with more informative peer_status() and deprecated the old name. The function now returns a dict with UUIDs as its keys. - glusterfs.info() can now be called without volume name. It always returns a dictionary. Use this function instead of status() in sates. - Functions glusterfs.delete() and glusterfs.create() were deprecated and renamed to delete_volume() and create_volume().
685 lines
25 KiB
Python
685 lines
25 KiB
Python
# -*- coding: utf-8 -*-
|
|
'''
|
|
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
|
|
:codeauthor: :email:`Joe Julian <me@joejulian.name>`
|
|
'''
|
|
|
|
# Import Python libs
|
|
from __future__ import absolute_import
|
|
|
|
# Import Salt Testing Libs
|
|
from salttesting import TestCase, skipIf
|
|
from salttesting.mock import (
|
|
MagicMock,
|
|
patch,
|
|
NO_MOCK,
|
|
NO_MOCK_REASON
|
|
)
|
|
|
|
# Import Salt Libs
|
|
from salt.modules import glusterfs
|
|
from salt.exceptions import SaltInvocationError
|
|
|
|
# Globals
|
|
glusterfs.__salt__ = {}
|
|
|
|
|
|
class GlusterResults(object):
|
|
''' This class holds the xml results from gluster cli transactions '''
|
|
|
|
class v34(object):
|
|
''' This is for version 3.4 results '''
|
|
|
|
class list_peers(object):
|
|
''' results from "peer status" '''
|
|
pass
|
|
|
|
class peer_probe(object):
|
|
fail_cant_connect = fail_bad_hostname = '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
|
|
'<cliOutput>',
|
|
' <opRet>-1</opRet>',
|
|
' <opErrno>107</opErrno>',
|
|
' <opErrstr>Probe returned with unknown errno 107</opErrstr>',
|
|
'</cliOutput>',
|
|
''])
|
|
|
|
success_self = '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>1</opErrno>',
|
|
' <opErrstr>(null)</opErrstr>',
|
|
' <output>success: on localhost not needed</output>',
|
|
'</cliOutput>',
|
|
''])
|
|
success_other = '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>0</opErrno>',
|
|
' <opErrstr>(null)</opErrstr>',
|
|
' <output>success</output>',
|
|
'</cliOutput>',
|
|
''])
|
|
success_hostname_after_ip = success_other
|
|
success_ip_after_hostname = success_other
|
|
success_already_peer = {
|
|
'ip': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr>(null)</opErrstr>',
|
|
' <output>success: host 10.0.0.2 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
'']),
|
|
'hostname': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr>(null)</opErrstr>',
|
|
' <output>success: host server2 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
''])}
|
|
success_reverse_already_peer = {
|
|
'ip': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr>(null)</opErrstr>',
|
|
' <output>success: host 10.0.0.1 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
'']),
|
|
'hostname': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr>(null)</opErrstr>',
|
|
' <output>success: host server1 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
''])}
|
|
success_first_hostname_from_second_first_time = success_other
|
|
success_first_hostname_from_second_second_time = success_reverse_already_peer[
|
|
'hostname']
|
|
success_first_ip_from_second_first_time = success_reverse_already_peer[
|
|
'ip']
|
|
|
|
class v37(object):
|
|
|
|
class peer_probe(object):
|
|
fail_cant_connect = fail_bad_hostname = '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
|
|
'<cliOutput>',
|
|
' <opRet>-1</opRet>',
|
|
' <opErrno>107</opErrno>',
|
|
' <opErrstr>Probe returned with Transport endpoint is not connected</opErrstr>',
|
|
'</cliOutput>',
|
|
''])
|
|
success_self = '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>1</opErrno>',
|
|
' <opErrstr/>',
|
|
' <output>Probe on localhost not needed</output>',
|
|
'</cliOutput>',
|
|
''])
|
|
success_other = '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>0</opErrno>',
|
|
' <opErrstr/>',
|
|
' <output/>',
|
|
'</cliOutput>',
|
|
''])
|
|
success_hostname_after_ip = success_other
|
|
success_ip_after_hostname = success_other
|
|
success_already_peer = {
|
|
'ip': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr/>',
|
|
' <output>Host 10.0.0.2 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
'']),
|
|
'hostname': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr/>',
|
|
' <output>Host server2 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
''])}
|
|
success_reverse_already_peer = {
|
|
'ip': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr/>',
|
|
' <output>Host 10.0.0.1 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
'']),
|
|
'hostname': '\n'.join([
|
|
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
' <cliOutput>',
|
|
' <opRet>0</opRet>',
|
|
' <opErrno>2</opErrno>',
|
|
' <opErrstr/>',
|
|
' <output>Host server1 port 24007 already in peer list</output>',
|
|
'</cliOutput>',
|
|
''])}
|
|
success_first_hostname_from_second_first_time = success_reverse_already_peer[
|
|
'hostname']
|
|
success_first_ip_from_second_first_time = success_other
|
|
success_first_ip_from_second_second_time = success_reverse_already_peer[
|
|
'ip']
|
|
|
|
xml_peer_present = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<peer>
|
|
<uuid>uuid1</uuid>
|
|
<hostname>node02</hostname>
|
|
<hostnames>
|
|
<hostname>node02.domain.dom</hostname>
|
|
<hostname>10.0.0.2</hostname>
|
|
</hostnames>
|
|
</peer>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_volume_present = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<volList>
|
|
<volume>Newvolume1</volume>
|
|
<volume>Newvolume2</volume>
|
|
</volList>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_volume_absent = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<volList>
|
|
<count>0</count>
|
|
</volList>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_volume_status = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<volStatus>
|
|
<volumes>
|
|
<volume>
|
|
<volName>myvol1</volName>
|
|
<nodeCount>3</nodeCount>
|
|
<node>
|
|
<hostname>node01</hostname>
|
|
<path>/tmp/foo</path>
|
|
<peerid>830700d7-0684-497c-a12c-c02e365fb90b</peerid>
|
|
<status>1</status>
|
|
<port>49155</port>
|
|
<ports>
|
|
<tcp>49155</tcp>
|
|
<rdma>N/A</rdma>
|
|
</ports>
|
|
<pid>2470</pid>
|
|
</node>
|
|
<node>
|
|
<hostname>NFS Server</hostname>
|
|
<path>localhost</path>
|
|
<peerid>830700d7-0684-497c-a12c-c02e365fb90b</peerid>
|
|
<status>0</status>
|
|
<port>N/A</port>
|
|
<ports>
|
|
<tcp>N/A</tcp>
|
|
<rdma>N/A</rdma>
|
|
</ports>
|
|
<pid>-1</pid>
|
|
</node>
|
|
<tasks/>
|
|
</volume>
|
|
</volumes>
|
|
</volStatus>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_volume_info_running = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<volInfo>
|
|
<volumes>
|
|
<volume>
|
|
<name>myvol1</name>
|
|
<id>f03c2180-cf55-4f77-ae0b-3650f57c82a1</id>
|
|
<status>1</status>
|
|
<statusStr>Started</statusStr>
|
|
<brickCount>1</brickCount>
|
|
<distCount>1</distCount>
|
|
<stripeCount>1</stripeCount>
|
|
<replicaCount>1</replicaCount>
|
|
<disperseCount>0</disperseCount>
|
|
<redundancyCount>0</redundancyCount>
|
|
<type>0</type>
|
|
<typeStr>Distribute</typeStr>
|
|
<transport>0</transport>
|
|
<bricks>
|
|
<brick uuid="830700d7-0684-497c-a12c-c02e365fb90b">node01:/tmp/foo<name>node01:/tmp/foo</name><hostUuid>830700d7-0684-497c-a12c-c02e365fb90b</hostUuid></brick>
|
|
</bricks>
|
|
<optCount>1</optCount>
|
|
<options>
|
|
<option>
|
|
<name>performance.readdir-ahead</name>
|
|
<value>on</value>
|
|
</option>
|
|
</options>
|
|
</volume>
|
|
<count>1</count>
|
|
</volumes>
|
|
</volInfo>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_volume_info_stopped = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<volInfo>
|
|
<volumes>
|
|
<volume>
|
|
<name>myvol1</name>
|
|
<status>1</status>
|
|
</volume>
|
|
</volumes>
|
|
</volInfo>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_peer_probe_success = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<opErrno>0</opErrno>
|
|
<opErrstr/>
|
|
<output/>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_peer_probe_already_member = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<opErrno>2</opErrno>
|
|
<opErrstr/>
|
|
<output>Host salt port 24007 already in peer list</output>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_peer_probe_localhost = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
<opErrno>1</opErrno>
|
|
<opErrstr/>
|
|
<output>Probe on localhost not needed</output>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_peer_probe_fail_cant_connect = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>-1</opRet>
|
|
<opErrno>107</opErrno>
|
|
<opErrstr>Probe returned with Transport endpoint is not connected</opErrstr>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_command_success = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>0</opRet>
|
|
</cliOutput>
|
|
"""
|
|
|
|
xml_command_fail = """
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<cliOutput>
|
|
<opRet>-1</opRet>
|
|
<opErrno>0</opErrno>
|
|
<opErrstr>Command Failed</opErrstr>
|
|
</cliOutput>
|
|
"""
|
|
|
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
class GlusterfsTestCase(TestCase):
|
|
|
|
'''
|
|
Test cases for salt.modules.glusterfs
|
|
'''
|
|
maxDiff = None
|
|
|
|
# 'peer_status' function tests: 1
|
|
|
|
def test_peer_status(self):
|
|
'''
|
|
Test gluster peer status
|
|
'''
|
|
mock_run = MagicMock(return_value=xml_peer_present)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertDictEqual(
|
|
glusterfs.peer_status(),
|
|
{'uuid1': {
|
|
'hostnames': ['node02', 'node02.domain.dom', '10.0.0.2']}})
|
|
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertDictEqual(glusterfs.peer_status(), {})
|
|
|
|
# 'peer' function tests: 1
|
|
|
|
def test_peer(self):
|
|
'''
|
|
Test if gluster peer call is successful.
|
|
'''
|
|
mock_run = MagicMock()
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
mock_run.return_value = xml_peer_probe_already_member
|
|
self.assertTrue(glusterfs.peer('salt'))
|
|
|
|
mock_run.return_value = xml_peer_probe_localhost
|
|
self.assertTrue(glusterfs.peer('salt'))
|
|
|
|
mock_run.return_value = xml_peer_probe_fail_cant_connect
|
|
self.assertFalse(glusterfs.peer('salt'))
|
|
|
|
# 'create_volume' function tests: 1
|
|
|
|
def test_create_volume(self):
|
|
'''
|
|
Test if it creates a glusterfs volume.
|
|
'''
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertRaises(
|
|
SaltInvocationError,
|
|
glusterfs.create_volume,
|
|
'newvolume',
|
|
'host1:brick')
|
|
|
|
self.assertRaises(
|
|
SaltInvocationError,
|
|
glusterfs.create_volume,
|
|
'newvolume',
|
|
'host1/brick')
|
|
|
|
self.assertFalse(mock_run.called)
|
|
|
|
mock_start_volume = MagicMock(return_value=True)
|
|
with patch.object(glusterfs, 'start_volume', mock_start_volume):
|
|
# Create, do not start
|
|
self.assertTrue(glusterfs.create_volume('newvolume',
|
|
'host1:/brick'))
|
|
self.assertFalse(mock_start_volume.called)
|
|
|
|
# Create and start
|
|
self.assertTrue(glusterfs.create_volume('newvolume',
|
|
'host1:/brick',
|
|
start=True))
|
|
self.assertTrue(mock_start_volume.called)
|
|
|
|
mock_start_volume.return_value = False
|
|
# Create and fail start
|
|
self.assertFalse(glusterfs.create_volume('newvolume',
|
|
'host1:/brick',
|
|
start=True))
|
|
|
|
mock_run.return_value = xml_command_fail
|
|
self.assertFalse(glusterfs.create_volume('newvolume', 'host1:/brick',
|
|
True, True, True, 'tcp', True))
|
|
|
|
# 'list_volumes' function tests: 1
|
|
|
|
def test_list_volumes(self):
|
|
'''
|
|
Test if it list configured volumes
|
|
'''
|
|
mock = MagicMock(return_value=xml_volume_absent)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock}):
|
|
self.assertListEqual(glusterfs.list_volumes(), [])
|
|
|
|
mock = MagicMock(return_value=xml_volume_present)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock}):
|
|
self.assertListEqual(glusterfs.list_volumes(),
|
|
['Newvolume1', 'Newvolume2'])
|
|
|
|
# 'status' function tests: 1
|
|
|
|
def test_status(self):
|
|
'''
|
|
Test if it check the status of a gluster volume.
|
|
'''
|
|
mock_run = MagicMock(return_value=xml_command_fail)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertIsNone(glusterfs.status('myvol1'))
|
|
|
|
res = {'bricks': {
|
|
'node01:/tmp/foo': {
|
|
'host': 'node01',
|
|
'hostname': 'node01',
|
|
'online': True,
|
|
'path': '/tmp/foo',
|
|
'peerid': '830700d7-0684-497c-a12c-c02e365fb90b',
|
|
'pid': '2470',
|
|
'port': '49155',
|
|
'ports': {
|
|
'rdma': 'N/A',
|
|
'tcp': '49155'},
|
|
'status': '1'}},
|
|
'healers': {},
|
|
'nfs': {
|
|
'node01': {
|
|
'host': 'NFS Server',
|
|
'hostname': 'NFS Server',
|
|
'online': False,
|
|
'path': 'localhost',
|
|
'peerid': '830700d7-0684-497c-a12c-c02e365fb90b',
|
|
'pid': '-1',
|
|
'port': 'N/A',
|
|
'ports': {
|
|
'rdma': 'N/A',
|
|
'tcp': 'N/A'},
|
|
'status': '0'}}}
|
|
mock = MagicMock(return_value=xml_volume_status)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock}):
|
|
self.assertDictEqual(glusterfs.status('myvol1'), res)
|
|
|
|
# 'start_volume' function tests: 1
|
|
|
|
def test_volume_info(self):
|
|
'''
|
|
Test if it returns the volume info.
|
|
'''
|
|
res = {'myvol1': {
|
|
'brickCount': '1',
|
|
'bricks': {
|
|
'brick1': {
|
|
'hostUuid': '830700d7-0684-497c-a12c-c02e365fb90b',
|
|
'path': 'node01:/tmp/foo',
|
|
'uuid': '830700d7-0684-497c-a12c-c02e365fb90b'}},
|
|
'disperseCount': '0',
|
|
'distCount': '1',
|
|
'id': 'f03c2180-cf55-4f77-ae0b-3650f57c82a1',
|
|
'name': 'myvol1',
|
|
'optCount': '1',
|
|
'options': {
|
|
'performance.readdir-ahead': 'on'},
|
|
'redundancyCount': '0',
|
|
'replicaCount': '1',
|
|
'status': '1',
|
|
'statusStr': 'Started',
|
|
'stripeCount': '1',
|
|
'transport': '0',
|
|
'type': '0',
|
|
'typeStr': 'Distribute'}}
|
|
mock = MagicMock(return_value=xml_volume_info_running)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock}):
|
|
self.assertDictEqual(glusterfs.info('myvol1'), res)
|
|
|
|
def test_start_volume(self):
|
|
'''
|
|
Test if it start a gluster volume.
|
|
'''
|
|
# Stopped volume
|
|
mock_info = MagicMock(return_value={'Newvolume1': {'status': '0'}})
|
|
with patch.object(glusterfs, 'info', mock_info):
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertEqual(glusterfs.start_volume('Newvolume1'), True)
|
|
self.assertEqual(glusterfs.start_volume('nonExisting'), False)
|
|
mock_run = MagicMock(return_value=xml_command_fail)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertEqual(glusterfs.start_volume('Newvolume1'), False)
|
|
|
|
# Started volume
|
|
mock_info = MagicMock(return_value={'Newvolume1': {'status': '1'}})
|
|
with patch.object(glusterfs, 'info', mock_info):
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertEqual(
|
|
glusterfs.start_volume('Newvolume1', force=True),
|
|
True
|
|
)
|
|
mock_run = MagicMock(return_value=xml_command_fail)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
# cmd.run should not be called for already running volume:
|
|
self.assertEqual(glusterfs.start_volume('Newvolume1'), True)
|
|
# except when forcing:
|
|
self.assertEqual(
|
|
glusterfs.start_volume('Newvolume1', force=True),
|
|
False
|
|
)
|
|
|
|
# 'stop_volume' function tests: 1
|
|
|
|
def test_stop_volume(self):
|
|
'''
|
|
Test if it stop a gluster volume.
|
|
'''
|
|
# Stopped volume
|
|
mock_info = MagicMock(return_value={'Newvolume1': {'status': '0'}})
|
|
with patch.object(glusterfs, 'info', mock_info):
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertEqual(glusterfs.stop_volume('Newvolume1'), True)
|
|
self.assertEqual(glusterfs.stop_volume('nonExisting'), False)
|
|
mock_run = MagicMock(return_value=xml_command_fail)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
# cmd.run should not be called for already stopped volume:
|
|
self.assertEqual(glusterfs.stop_volume('Newvolume1'), True)
|
|
|
|
# Started volume
|
|
mock_info = MagicMock(return_value={'Newvolume1': {'status': '1'}})
|
|
with patch.object(glusterfs, 'info', mock_info):
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertEqual(glusterfs.stop_volume('Newvolume1'), True)
|
|
self.assertEqual(glusterfs.stop_volume('nonExisting'), False)
|
|
mock_run = MagicMock(return_value=xml_command_fail)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertEqual(glusterfs.stop_volume('Newvolume1'), False)
|
|
|
|
# 'delete_volume' function tests: 1
|
|
|
|
def test_delete_volume(self):
|
|
'''
|
|
Test if it deletes a gluster volume.
|
|
'''
|
|
mock_info = MagicMock(return_value={'Newvolume1': {'status': '1'}})
|
|
with patch.object(glusterfs, 'info', mock_info):
|
|
# volume doesn't exist
|
|
self.assertFalse(glusterfs.delete_volume('Newvolume3'))
|
|
|
|
mock_stop_volume = MagicMock(return_value=True)
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
with patch.object(glusterfs, 'stop_volume', mock_stop_volume):
|
|
# volume exists, should not be stopped, and is started
|
|
self.assertFalse(glusterfs.delete_volume('Newvolume1',
|
|
False))
|
|
self.assertFalse(mock_run.called)
|
|
self.assertFalse(mock_stop_volume.called)
|
|
|
|
# volume exists, should be stopped, and is started
|
|
self.assertTrue(glusterfs.delete_volume('Newvolume1'))
|
|
self.assertTrue(mock_run.called)
|
|
self.assertTrue(mock_stop_volume.called)
|
|
|
|
# volume exists and isn't started
|
|
mock_info = MagicMock(return_value={'Newvolume1': {'status': '2'}})
|
|
with patch.object(glusterfs, 'info', mock_info):
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
self.assertTrue(glusterfs.delete_volume('Newvolume1'))
|
|
mock_run.return_value = xml_command_fail
|
|
self.assertFalse(glusterfs.delete_volume('Newvolume1'))
|
|
|
|
# 'add_volume_bricks' function tests: 1
|
|
|
|
def test_add_volume_bricks(self):
|
|
'''
|
|
Test if it add brick(s) to an existing volume
|
|
'''
|
|
mock_info = MagicMock(return_value={
|
|
'Newvolume1': {
|
|
'status': '1',
|
|
'bricks': {
|
|
'brick1': {'path': 'host:/path1'},
|
|
'brick2': {'path': 'host:/path2'}
|
|
}
|
|
}
|
|
})
|
|
with patch.object(glusterfs, 'info', mock_info):
|
|
mock_run = MagicMock(return_value=xml_command_success)
|
|
with patch.dict(glusterfs.__salt__, {'cmd.run': mock_run}):
|
|
# Volume does not exist
|
|
self.assertFalse(glusterfs.add_volume_bricks('nonExisting',
|
|
['bricks']))
|
|
# Brick already exists
|
|
self.assertTrue(glusterfs.add_volume_bricks('Newvolume1',
|
|
['host:/path2']))
|
|
# Already existing brick as a string
|
|
self.assertTrue(glusterfs.add_volume_bricks('Newvolume1',
|
|
'host:/path2'))
|
|
self.assertFalse(mock_run.called)
|
|
# A new brick:
|
|
self.assertTrue(glusterfs.add_volume_bricks('Newvolume1',
|
|
['host:/new1']))
|
|
self.assertTrue(mock_run.called)
|
|
|
|
# Gluster call fails
|
|
mock_run.return_value = xml_command_fail
|
|
self.assertFalse(glusterfs.add_volume_bricks('Newvolume1',
|
|
['new:/path']))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
from integration import run_tests
|
|
run_tests(GlusterfsTestCase, needs_daemon=False)
|