~ubuntu-branches/ubuntu/utopic/cinder/utopic

« back to all changes in this revision

Viewing changes to cinder/tests/test_netapp_ssc.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, James Page, Adam Gandelman, Chuck Short
  • Date: 2013-09-08 21:09:46 UTC
  • mfrom: (1.1.18)
  • Revision ID: package-import@ubuntu.com-20130908210946-3dbzq1jy5uji4wad
Tags: 1:2013.2~b3-0ubuntu1
[ James Page ]
* d/control: Switch ceph-common -> python-ceph inline with upstream
  refactoring of Ceph RBD driver, move to Suggests of python-cinder.
  (LP: #1190791). 

[ Adam Gandelman ]
* debian/patches/avoid_paramiko_vers_depends.patch: Dropped, no longer
  required.
* Add minimum requirement python-greenlet (>= 0.3.2).
* Add minimum requirement python-eventlet (>= 0.12.0).
* Add minimum requirement python-paramiko (>= 1.8).

[ Chuck Short ]
* New upstream release.
* debian/patches/skip-sqlachemy-failures.patch: Skip testfailures
  with sqlalchemy 0.8 until they are fixed upstream.
* debian/control: Add python-babel to build-depends.
* debian/control: Add python-novaclient to build-depends.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright (c) 2012 NetApp, Inc.
 
4
# All Rights Reserved.
 
5
#
 
6
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
7
#    not use this file except in compliance with the License. You may obtain
 
8
#    a copy of the License at
 
9
#
 
10
#         http://www.apache.org/licenses/LICENSE-2.0
 
11
#
 
12
#    Unless required by applicable law or agreed to in writing, software
 
13
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
14
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
15
#    License for the specific language governing permissions and limitations
 
16
#    under the License.
 
17
"""Unit tests for the NetApp-specific ssc module."""
 
18
 
 
19
import BaseHTTPServer
 
20
import copy
 
21
import httplib
 
22
from lxml import etree
 
23
import mox
 
24
from mox import IgnoreArg
 
25
from mox import IsA
 
26
from mox import MockObject
 
27
import StringIO
 
28
 
 
29
from cinder import context
 
30
from cinder import exception
 
31
from cinder import test
 
32
from cinder.volume import configuration as conf
 
33
from cinder.volume.drivers.netapp import api
 
34
from cinder.volume.drivers.netapp import ssc_utils
 
35
 
 
36
 
 
37
class FakeHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
 
38
    """HTTP handler that doesn't spam the log."""
 
39
 
 
40
    def log_message(self, format, *args):
 
41
        pass
 
42
 
 
43
 
 
44
class FakeHttplibSocket(object):
 
45
    """A fake socket implementation for httplib.HTTPResponse."""
 
46
    def __init__(self, value):
 
47
        self._rbuffer = StringIO.StringIO(value)
 
48
        self._wbuffer = StringIO.StringIO('')
 
49
        oldclose = self._wbuffer.close
 
50
 
 
51
        def newclose():
 
52
            self.result = self._wbuffer.getvalue()
 
53
            oldclose()
 
54
        self._wbuffer.close = newclose
 
55
 
 
56
    def makefile(self, mode, _other):
 
57
        """Returns the socket's internal buffer"""
 
58
        if mode == 'r' or mode == 'rb':
 
59
            return self._rbuffer
 
60
        if mode == 'w' or mode == 'wb':
 
61
            return self._wbuffer
 
62
 
 
63
 
 
64
RESPONSE_PREFIX_DIRECT_CMODE = """<?xml version='1.0' encoding='UTF-8' ?>
 
65
<!DOCTYPE netapp SYSTEM 'file:/etc/netapp_gx.dtd'>"""
 
66
 
 
67
RESPONSE_PREFIX_DIRECT = """
 
68
<netapp version='1.15' xmlns='http://www.netapp.com/filer/admin'>"""
 
69
 
 
70
RESPONSE_SUFFIX_DIRECT = """</netapp>"""
 
71
 
 
72
 
 
73
class FakeDirectCMODEServerHandler(FakeHTTPRequestHandler):
 
74
    """HTTP handler that fakes enough stuff to allow the driver to run."""
 
75
 
 
76
    def do_GET(s):
 
77
        """Respond to a GET request."""
 
78
        if '/servlets/netapp.servlets.admin.XMLrequest_filer' != s.path:
 
79
            s.send_response(404)
 
80
            s.end_headers
 
81
            return
 
82
        s.send_response(200)
 
83
        s.send_header("Content-Type", "text/xml; charset=utf-8")
 
84
        s.end_headers()
 
85
        out = s.wfile
 
86
        out.write('<netapp version="1.15">'
 
87
                  '<results reason="Not supported method type"'
 
88
                  ' status="failed" errno="Not_Allowed"/></netapp>')
 
89
 
 
90
    def do_POST(s):
 
91
        """Respond to a POST request."""
 
92
        if '/servlets/netapp.servlets.admin.XMLrequest_filer' != s.path:
 
93
            s.send_response(404)
 
94
            s.end_headers
 
95
            return
 
96
        request_xml = s.rfile.read(int(s.headers['Content-Length']))
 
97
        root = etree.fromstring(request_xml)
 
98
        body = [x for x in root.iterchildren()]
 
99
        request = body[0]
 
100
        tag = request.tag
 
101
        localname = etree.QName(tag).localname or tag
 
102
        if 'volume-get-iter' == localname:
 
103
            body = """<results status="passed"><attributes-list>
 
104
                <volume-attributes>
 
105
                <volume-id-attributes>
 
106
                    <name>iscsi</name>
 
107
                    <owning-vserver-name>Openstack</owning-vserver-name>
 
108
                    <containing-aggregate-name>aggr0
 
109
                    </containing-aggregate-name>
 
110
                    <junction-path>/iscsi</junction-path>
 
111
                    <type>rw</type>
 
112
                </volume-id-attributes>
 
113
                <volume-space-attributes>
 
114
                    <size-available>214748364</size-available>
 
115
                    <size-total>224748364</size-total>
 
116
                    <space-guarantee-enabled>enabled</space-guarantee-enabled>
 
117
                    <space-guarantee>file</space-guarantee>
 
118
                </volume-space-attributes>
 
119
                <volume-state-attributes>
 
120
                    <is-cluster-volume>true
 
121
                    </is-cluster-volume>
 
122
                    <is-vserver-root>false</is-vserver-root>
 
123
                    <state>online</state>
 
124
                    <is-inconsistent>false</is-inconsistent>
 
125
                    <is-invalid>false</is-invalid>
 
126
                    <is-junction-active>true</is-junction-active>
 
127
                </volume-state-attributes>
 
128
                </volume-attributes>
 
129
                <volume-attributes>
 
130
                <volume-id-attributes>
 
131
                    <name>nfsvol</name>
 
132
                    <owning-vserver-name>Openstack
 
133
                    </owning-vserver-name>
 
134
                    <containing-aggregate-name>aggr0
 
135
                    </containing-aggregate-name>
 
136
                    <junction-path>/nfs</junction-path>
 
137
                    <type>rw</type>
 
138
                </volume-id-attributes>
 
139
                <volume-space-attributes>
 
140
                    <size-available>14748364</size-available>
 
141
                    <size-total>24748364</size-total>
 
142
                    <space-guarantee-enabled>enabled
 
143
                    </space-guarantee-enabled>
 
144
                    <space-guarantee>volume</space-guarantee>
 
145
                </volume-space-attributes>
 
146
                <volume-state-attributes>
 
147
                    <is-cluster-volume>true
 
148
                    </is-cluster-volume>
 
149
                    <is-vserver-root>false</is-vserver-root>
 
150
                    <state>online</state>
 
151
                    <is-inconsistent>false</is-inconsistent>
 
152
                    <is-invalid>false</is-invalid>
 
153
                    <is-junction-active>true</is-junction-active>
 
154
                </volume-state-attributes>
 
155
                </volume-attributes>
 
156
                <volume-attributes>
 
157
                <volume-id-attributes>
 
158
                    <name>nfsvol2</name>
 
159
                    <owning-vserver-name>Openstack
 
160
                    </owning-vserver-name>
 
161
                    <containing-aggregate-name>aggr0
 
162
                    </containing-aggregate-name>
 
163
                    <junction-path>/nfs2</junction-path>
 
164
                    <type>rw</type>
 
165
                </volume-id-attributes>
 
166
                <volume-space-attributes>
 
167
                    <size-available>14748364</size-available>
 
168
                    <size-total>24748364</size-total>
 
169
                    <space-guarantee-enabled>enabled
 
170
                    </space-guarantee-enabled>
 
171
                    <space-guarantee>volume</space-guarantee>
 
172
                </volume-space-attributes>
 
173
                <volume-state-attributes>
 
174
                    <is-cluster-volume>true
 
175
                    </is-cluster-volume>
 
176
                    <is-vserver-root>false</is-vserver-root>
 
177
                    <state>online</state>
 
178
                    <is-inconsistent>true</is-inconsistent>
 
179
                    <is-invalid>true</is-invalid>
 
180
                    <is-junction-active>true</is-junction-active>
 
181
                </volume-state-attributes>
 
182
                </volume-attributes>
 
183
                <volume-attributes>
 
184
                <volume-id-attributes>
 
185
                    <name>nfsvol3</name>
 
186
                    <owning-vserver-name>Openstack
 
187
                    </owning-vserver-name>
 
188
                    <containing-aggregate-name>aggr0
 
189
                    </containing-aggregate-name>
 
190
                    <junction-path>/nfs3</junction-path>
 
191
                    <type>rw</type>
 
192
                </volume-id-attributes>
 
193
                <volume-space-attributes>
 
194
                    <space-guarantee-enabled>enabled
 
195
                    </space-guarantee-enabled>
 
196
                    <space-guarantee>volume
 
197
                    </space-guarantee>
 
198
                </volume-space-attributes>
 
199
                <volume-state-attributes>
 
200
                    <is-cluster-volume>true
 
201
                    </is-cluster-volume>
 
202
                    <is-vserver-root>false</is-vserver-root>
 
203
                    <state>online</state>
 
204
                    <is-inconsistent>false</is-inconsistent>
 
205
                    <is-invalid>false</is-invalid>
 
206
                    <is-junction-active>true</is-junction-active>
 
207
                </volume-state-attributes>
 
208
                </volume-attributes>
 
209
                </attributes-list>
 
210
                <num-records>4</num-records></results>"""
 
211
        elif 'aggr-options-list-info' == localname:
 
212
                body = """<results status="passed">
 
213
                             <options>
 
214
                             <aggr-option-info>
 
215
                             <name>ha_policy</name>
 
216
                             <value>cfo</value>
 
217
                             </aggr-option-info>
 
218
                             <aggr-option-info>
 
219
                             <name>raidtype</name>
 
220
                             <value>raid_dp</value>
 
221
                             </aggr-option-info>
 
222
                             </options>
 
223
                             </results>"""
 
224
        elif 'sis-get-iter' == localname:
 
225
                body = """<results status="passed">
 
226
                             <attributes-list>
 
227
                             <sis-status-info>
 
228
                             <path>/vol/iscsi</path>
 
229
                             <is-compression-enabled>
 
230
                             true
 
231
                             </is-compression-enabled>
 
232
                             <state>enabled</state>
 
233
                             </sis-status-info>
 
234
                             </attributes-list>
 
235
                             </results>"""
 
236
        elif 'storage-disk-get-iter' == localname:
 
237
            body = """<results status="passed">
 
238
                             <attributes-list>
 
239
                             <storage-disk-info>
 
240
                             <disk-raid-info>
 
241
            <effective-disk-type>SATA</effective-disk-type>
 
242
                             </disk-raid-info>
 
243
                             </storage-disk-info>
 
244
                             </attributes-list>
 
245
                             </results>"""
 
246
        else:
 
247
                # Unknown API
 
248
                s.send_response(500)
 
249
                s.end_headers
 
250
                return
 
251
        s.send_response(200)
 
252
        s.send_header("Content-Type", "text/xml; charset=utf-8")
 
253
        s.end_headers()
 
254
        s.wfile.write(RESPONSE_PREFIX_DIRECT_CMODE)
 
255
        s.wfile.write(RESPONSE_PREFIX_DIRECT)
 
256
        s.wfile.write(body)
 
257
        s.wfile.write(RESPONSE_SUFFIX_DIRECT)
 
258
 
 
259
 
 
260
class FakeDirectCmodeHTTPConnection(object):
 
261
    """A fake httplib.HTTPConnection for netapp tests.
 
262
 
 
263
    Requests made via this connection actually get translated and routed into
 
264
    the fake direct handler above, we then turn the response into
 
265
    the httplib.HTTPResponse that the caller expects.
 
266
    """
 
267
    def __init__(self, host, timeout=None):
 
268
        self.host = host
 
269
 
 
270
    def request(self, method, path, data=None, headers=None):
 
271
        if not headers:
 
272
            headers = {}
 
273
        req_str = '%s %s HTTP/1.1\r\n' % (method, path)
 
274
        for key, value in headers.iteritems():
 
275
            req_str += "%s: %s\r\n" % (key, value)
 
276
        if data:
 
277
            req_str += '\r\n%s' % data
 
278
 
 
279
        # NOTE(vish): normally the http transport normailizes from unicode
 
280
        sock = FakeHttplibSocket(req_str.decode("latin-1").encode("utf-8"))
 
281
        # NOTE(vish): stop the server from trying to look up address from
 
282
        #             the fake socket
 
283
        FakeDirectCMODEServerHandler.address_string = lambda x: '127.0.0.1'
 
284
        self.app = FakeDirectCMODEServerHandler(sock, '127.0.0.1:80', None)
 
285
 
 
286
        self.sock = FakeHttplibSocket(sock.result)
 
287
        self.http_response = httplib.HTTPResponse(self.sock)
 
288
 
 
289
    def set_debuglevel(self, level):
 
290
        pass
 
291
 
 
292
    def getresponse(self):
 
293
        self.http_response.begin()
 
294
        return self.http_response
 
295
 
 
296
    def getresponsebody(self):
 
297
        return self.sock.result
 
298
 
 
299
 
 
300
def createNetAppVolume(**kwargs):
 
301
    vol = ssc_utils.NetAppVolume(kwargs['name'], kwargs['vs'])
 
302
    vol.state['vserver_root'] = kwargs.get('vs_root')
 
303
    vol.state['status'] = kwargs.get('status')
 
304
    vol.state['junction_active'] = kwargs.get('junc_active')
 
305
    vol.space['size_avl_bytes'] = kwargs.get('avl_byt')
 
306
    vol.space['size_total_bytes'] = kwargs.get('total_byt')
 
307
    vol.space['space-guarantee-enabled'] = kwargs.get('sg_enabled')
 
308
    vol.space['space-guarantee'] = kwargs.get('sg')
 
309
    vol.space['thin_provisioned'] = kwargs.get('thin')
 
310
    vol.mirror['mirrored'] = kwargs.get('mirrored')
 
311
    vol.qos['qos_policy_group'] = kwargs.get('qos')
 
312
    vol.aggr['name'] = kwargs.get('aggr_name')
 
313
    vol.aggr['junction'] = kwargs.get('junction')
 
314
    vol.sis['dedup'] = kwargs.get('dedup')
 
315
    vol.sis['compression'] = kwargs.get('compression')
 
316
    vol.aggr['raid_type'] = kwargs.get('raid')
 
317
    vol.aggr['ha_policy'] = kwargs.get('ha')
 
318
    vol.aggr['disk_type'] = kwargs.get('disk')
 
319
    return vol
 
320
 
 
321
 
 
322
class SscUtilsTestCase(test.TestCase):
 
323
    """Test ssc utis."""
 
324
    vol1 = createNetAppVolume(name='vola', vs='openstack',
 
325
                              vs_root=False, status='online', junc_active=True,
 
326
                              avl_byt='1000', total_byt='1500',
 
327
                              sg_enabled=False,
 
328
                              sg='file', thin=False, mirrored=False,
 
329
                              qos=None, aggr_name='aggr1', junction='/vola',
 
330
                              dedup=False, compression=False,
 
331
                              raid='raiddp', ha='cfo', disk='SSD')
 
332
 
 
333
    vol2 = createNetAppVolume(name='volb', vs='openstack',
 
334
                              vs_root=False, status='online', junc_active=True,
 
335
                              avl_byt='2000', total_byt='2500',
 
336
                              sg_enabled=True,
 
337
                              sg='file', thin=True, mirrored=False,
 
338
                              qos=None, aggr_name='aggr2', junction='/volb',
 
339
                              dedup=True, compression=False,
 
340
                              raid='raid4', ha='cfo', disk='SSD')
 
341
 
 
342
    vol3 = createNetAppVolume(name='volc', vs='openstack',
 
343
                              vs_root=False, status='online', junc_active=True,
 
344
                              avl_byt='3000', total_byt='3500',
 
345
                              sg_enabled=True,
 
346
                              sg='volume', thin=True, mirrored=False,
 
347
                              qos=None, aggr_name='aggr1', junction='/volc',
 
348
                              dedup=True, compression=True,
 
349
                              raid='raiddp', ha='cfo', disk='SAS')
 
350
 
 
351
    vol4 = createNetAppVolume(name='vold', vs='openstack',
 
352
                              vs_root=False, status='online', junc_active=True,
 
353
                              avl_byt='4000', total_byt='4500',
 
354
                              sg_enabled=False,
 
355
                              sg='none', thin=False, mirrored=False,
 
356
                              qos=None, aggr_name='aggr1', junction='/vold',
 
357
                              dedup=False, compression=False,
 
358
                              raid='raiddp', ha='cfo', disk='SSD')
 
359
 
 
360
    vol5 = createNetAppVolume(name='vole', vs='openstack',
 
361
                              vs_root=False, status='online', junc_active=True,
 
362
                              avl_byt='5000', total_byt='5500',
 
363
                              sg_enabled=True,
 
364
                              sg='none', thin=False, mirrored=True,
 
365
                              qos=None, aggr_name='aggr2', junction='/vole',
 
366
                              dedup=True, compression=False,
 
367
                              raid='raid4', ha='cfo', disk='SAS')
 
368
 
 
369
    def setUp(self):
 
370
        super(SscUtilsTestCase, self).setUp()
 
371
        self.stubs.Set(httplib, 'HTTPConnection',
 
372
                       FakeDirectCmodeHTTPConnection)
 
373
 
 
374
    def test_cl_vols_ssc_all(self):
 
375
        """Test cluster ssc for all vols."""
 
376
        na_server = api.NaServer('127.0.0.1')
 
377
        vserver = 'openstack'
 
378
        test_vols = set([copy.deepcopy(self.vol1),
 
379
                         copy.deepcopy(self.vol2), copy.deepcopy(self.vol3)])
 
380
        sis = {'vola': {'dedup': False, 'compression': False},
 
381
               'volb': {'dedup': True, 'compression': False}}
 
382
 
 
383
        self.mox.StubOutWithMock(ssc_utils, 'query_cluster_vols_for_ssc')
 
384
        self.mox.StubOutWithMock(ssc_utils, 'get_sis_vol_dict')
 
385
        self.mox.StubOutWithMock(ssc_utils, 'query_aggr_options')
 
386
        self.mox.StubOutWithMock(ssc_utils, 'query_aggr_storage_disk')
 
387
        ssc_utils.query_cluster_vols_for_ssc(
 
388
            na_server, vserver, None).AndReturn(test_vols)
 
389
        ssc_utils.get_sis_vol_dict(na_server, vserver, None).AndReturn(sis)
 
390
        raiddp = {'ha_policy': 'cfo', 'raid_type': 'raiddp'}
 
391
        ssc_utils.query_aggr_options(
 
392
            na_server, IgnoreArg()).AndReturn(raiddp)
 
393
        ssc_utils.query_aggr_storage_disk(
 
394
            na_server, IgnoreArg()).AndReturn('SSD')
 
395
        raid4 = {'ha_policy': 'cfo', 'raid_type': 'raid4'}
 
396
        ssc_utils.query_aggr_options(
 
397
            na_server, IgnoreArg()).AndReturn(raid4)
 
398
        ssc_utils.query_aggr_storage_disk(
 
399
            na_server, IgnoreArg()).AndReturn('SAS')
 
400
        self.mox.ReplayAll()
 
401
 
 
402
        res_vols = ssc_utils.get_cluster_vols_with_ssc(
 
403
            na_server, vserver, volume=None)
 
404
 
 
405
        self.mox.VerifyAll()
 
406
        for vol in res_vols:
 
407
            if vol.id['name'] == 'volc':
 
408
                self.assertEqual(vol.sis['compression'], False)
 
409
                self.assertEqual(vol.sis['dedup'], False)
 
410
            else:
 
411
                pass
 
412
 
 
413
    def test_cl_vols_ssc_single(self):
 
414
        """Test cluster ssc for single vol."""
 
415
        na_server = api.NaServer('127.0.0.1')
 
416
        vserver = 'openstack'
 
417
        test_vols = set([copy.deepcopy(self.vol1)])
 
418
        sis = {'vola': {'dedup': False, 'compression': False}}
 
419
 
 
420
        self.mox.StubOutWithMock(ssc_utils, 'query_cluster_vols_for_ssc')
 
421
        self.mox.StubOutWithMock(ssc_utils, 'get_sis_vol_dict')
 
422
        self.mox.StubOutWithMock(ssc_utils, 'query_aggr_options')
 
423
        self.mox.StubOutWithMock(ssc_utils, 'query_aggr_storage_disk')
 
424
        ssc_utils.query_cluster_vols_for_ssc(
 
425
            na_server, vserver, 'vola').AndReturn(test_vols)
 
426
        ssc_utils.get_sis_vol_dict(
 
427
            na_server, vserver, 'vola').AndReturn(sis)
 
428
        raiddp = {'ha_policy': 'cfo', 'raid_type': 'raiddp'}
 
429
        ssc_utils.query_aggr_options(
 
430
            na_server, 'aggr1').AndReturn(raiddp)
 
431
        ssc_utils.query_aggr_storage_disk(na_server, 'aggr1').AndReturn('SSD')
 
432
        self.mox.ReplayAll()
 
433
 
 
434
        res_vols = ssc_utils.get_cluster_vols_with_ssc(
 
435
            na_server, vserver, volume='vola')
 
436
 
 
437
        self.mox.VerifyAll()
 
438
        self.assertEqual(len(res_vols), 1)
 
439
 
 
440
    def test_get_cluster_ssc(self):
 
441
        """Test get cluster ssc map."""
 
442
        na_server = api.NaServer('127.0.0.1')
 
443
        vserver = 'openstack'
 
444
        test_vols = set(
 
445
            [self.vol1, self.vol2, self.vol3, self.vol4, self.vol5])
 
446
 
 
447
        self.mox.StubOutWithMock(ssc_utils, 'get_cluster_vols_with_ssc')
 
448
        ssc_utils.get_cluster_vols_with_ssc(
 
449
            na_server, vserver).AndReturn(test_vols)
 
450
        self.mox.ReplayAll()
 
451
 
 
452
        res_map = ssc_utils.get_cluster_ssc(na_server, vserver)
 
453
 
 
454
        self.mox.VerifyAll()
 
455
        self.assertEqual(len(res_map['mirrored']), 1)
 
456
        self.assertEqual(len(res_map['dedup']), 3)
 
457
        self.assertEqual(len(res_map['compression']), 1)
 
458
        self.assertEqual(len(res_map['thin']), 2)
 
459
        self.assertEqual(len(res_map['all']), 5)
 
460
 
 
461
    def test_vols_for_boolean_specs(self):
 
462
        """Test ssc for boolean specs."""
 
463
        test_vols = set(
 
464
            [self.vol1, self.vol2, self.vol3, self.vol4, self.vol5])
 
465
        ssc_map = {'mirrored': set([self.vol1]),
 
466
                   'dedup': set([self.vol1, self.vol2, self.vol3]),
 
467
                   'compression': set([self.vol3, self.vol4]),
 
468
                   'thin': set([self.vol5, self.vol2]), 'all': test_vols}
 
469
        test_map = {'mirrored': ('netapp_mirrored', 'netapp_unmirrored'),
 
470
                    'dedup': ('netapp_dedup', 'netapp_nodedup'),
 
471
                    'compression': ('netapp_compression',
 
472
                                    'netapp_nocompression'),
 
473
                    'thin': ('netapp_thin_provisioned',
 
474
                             'netapp_thick_provisioned')}
 
475
        for type in test_map.keys():
 
476
            # type
 
477
            extra_specs = {test_map[type][0]: 'true'}
 
478
            res = ssc_utils.get_volumes_for_specs(ssc_map, extra_specs)
 
479
            self.assertEqual(len(res), len(ssc_map[type]))
 
480
            # opposite type
 
481
            extra_specs = {test_map[type][1]: 'true'}
 
482
            res = ssc_utils.get_volumes_for_specs(ssc_map, extra_specs)
 
483
            self.assertEqual(len(res), len(ssc_map['all'] - ssc_map[type]))
 
484
            # both types
 
485
            extra_specs =\
 
486
                {test_map[type][0]: 'true', test_map[type][1]: 'true'}
 
487
            res = ssc_utils.get_volumes_for_specs(ssc_map, extra_specs)
 
488
            self.assertEqual(len(res), len(ssc_map['all']))
 
489
 
 
490
    def test_vols_for_optional_specs(self):
 
491
        """Test ssc for optional specs."""
 
492
        test_vols =\
 
493
            set([self.vol1, self.vol2, self.vol3, self.vol4, self.vol5])
 
494
        ssc_map = {'mirrored': set([self.vol1]),
 
495
                   'dedup': set([self.vol1, self.vol2, self.vol3]),
 
496
                   'compression': set([self.vol3, self.vol4]),
 
497
                   'thin': set([self.vol5, self.vol2]), 'all': test_vols}
 
498
        extra_specs =\
 
499
            {'netapp_dedup': 'true',
 
500
             'netapp:raid_type': 'raid4', 'netapp:disk_type': 'SSD'}
 
501
        res = ssc_utils.get_volumes_for_specs(ssc_map, extra_specs)
 
502
        self.assertEqual(len(res), 1)
 
503
 
 
504
    def test_query_cl_vols_for_ssc(self):
 
505
        na_server = api.NaServer('127.0.0.1')
 
506
        na_server.set_api_version(1, 15)
 
507
        vols = ssc_utils.query_cluster_vols_for_ssc(na_server, 'Openstack')
 
508
        self.assertEqual(len(vols), 2)
 
509
        for vol in vols:
 
510
            if vol.id['name'] != 'iscsi' or vol.id['name'] != 'nfsvol':
 
511
                pass
 
512
            else:
 
513
                raise exception.InvalidVolume('Invalid volume returned.')
 
514
 
 
515
    def test_query_aggr_options(self):
 
516
        na_server = api.NaServer('127.0.0.1')
 
517
        aggr_attribs = ssc_utils.query_aggr_options(na_server, 'aggr0')
 
518
        if aggr_attribs:
 
519
            self.assertEqual(aggr_attribs['ha_policy'], 'cfo')
 
520
            self.assertEqual(aggr_attribs['raid_type'], 'raid_dp')
 
521
        else:
 
522
            raise exception.InvalidParameterValue("Incorrect aggr options")
 
523
 
 
524
    def test_query_aggr_storage_disk(self):
 
525
        na_server = api.NaServer('127.0.0.1')
 
526
        eff_disk_type = ssc_utils.query_aggr_storage_disk(na_server, 'aggr0')
 
527
        self.assertEqual(eff_disk_type, 'SATA')