578
578
RESPONSE_SUFFIX = """</env:Body></env:Envelope>"""
580
580
APIS = ['ApiProxy', 'DatasetListInfoIterStart', 'DatasetListInfoIterNext',
581
'DatasetListInfoIterEnd', 'DatasetEditBegin', 'DatasetEditCommit',
582
'DatasetProvisionMember', 'DatasetRemoveMember', 'DfmAbout',
583
'DpJobProgressEventListIterStart', 'DpJobProgressEventListIterNext',
584
'DpJobProgressEventListIterEnd', 'DatasetMemberListInfoIterStart',
585
'DatasetMemberListInfoIterNext', 'DatasetMemberListInfoIterEnd',
586
'HostListInfoIterStart', 'HostListInfoIterNext', 'HostListInfoIterEnd',
587
'LunListInfoIterStart', 'LunListInfoIterNext', 'LunListInfoIterEnd',
588
'StorageServiceDatasetProvision']
581
'DatasetListInfoIterEnd', 'DatasetEditBegin', 'DatasetEditCommit',
582
'DatasetProvisionMember', 'DatasetRemoveMember', 'DfmAbout',
583
'DpJobProgressEventListIterStart', 'DpJobProgressEventListIterNext',
584
'DpJobProgressEventListIterEnd', 'DatasetMemberListInfoIterStart',
585
'DatasetMemberListInfoIterNext', 'DatasetMemberListInfoIterEnd',
586
'HostListInfoIterStart', 'HostListInfoIterNext', 'HostListInfoIterEnd',
587
'LunListInfoIterStart', 'LunListInfoIterNext', 'LunListInfoIterEnd',
588
'StorageServiceDatasetProvision']
594
594
class FakeDfmServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
595
"""HTTP handler that fakes enough stuff to allow the driver to run"""
595
"""HTTP handler that fakes enough stuff to allow the driver to run."""
598
598
"""Respond to a GET request."""
622
622
out.write('</portType>')
623
623
out.write('<binding name="DfmBinding" type="na:DfmInterface">')
624
624
out.write('<soap:binding style="document" ' +
625
'transport="http://schemas.xmlsoap.org/soap/http"/>')
625
'transport="http://schemas.xmlsoap.org/soap/http"/>')
627
627
out.write('<operation name="%s">' % api)
628
628
out.write('<soap:operation soapAction="urn:%s"/>' % api)
641
641
request_xml = s.rfile.read(int(s.headers['Content-Length']))
642
642
ntap_ns = 'http://www.netapp.com/management/v1'
643
643
nsmap = {'env': 'http://schemas.xmlsoap.org/soap/envelope/',
645
645
root = etree.fromstring(request_xml)
647
647
body = root.xpath('/env:Envelope/env:Body', namespaces=nsmap)[0]
822
822
names = body.xpath('na:ApiProxy/na:Request/na:Name',
823
823
namespaces=nsmap)
824
824
proxy = names[0].text
825
if 'igroup-list-info' == proxy:
825
if 'clone-list-status' == proxy:
826
op_elem = body.xpath('na:ApiProxy/na:Request/na:Args/'
827
'clone-id/clone-id-info/clone-op-id',
829
proxy_body = """<status>
831
<clone-state>completed</clone-state>
834
if '0' == op_elem[0].text:
836
elif 'clone-start' == proxy:
837
proxy_body = """<clone-id>
839
<clone-op-id>1</clone-op-id>
840
<volume-uuid>xxx</volume-uuid>
843
elif 'igroup-list-info' == proxy:
826
844
igroup = 'openstack-iqn.1993-08.org.debian:01:23456789'
827
845
initiator = 'iqn.1993-08.org.debian:01:23456789'
828
846
proxy_body = """<initiator-groups>
977
995
self.driver._provision(self.VOLUME_NAME, None, self.PROJECT_ID,
978
996
self.VOLUME_TYPE, self.VOLUME_SIZE)
979
997
volume = {'name': self.VOLUME_NAME, 'project_id': self.PROJECT_ID,
980
'id': 0, 'provider_auth': None}
998
'id': 0, 'provider_auth': None}
981
999
updates = self.driver._get_export(volume)
982
1000
self.assertTrue(updates['provider_location'])
983
1001
volume['provider_location'] = updates['provider_location']
988
1006
self.driver.terminate_connection(volume, connector)
989
1007
self.driver._remove_destroy(self.VOLUME_NAME, self.PROJECT_ID)
1009
def test_clone(self):
1010
self.driver._discover_luns()
1011
self.driver._clone_lun(0, '/vol/vol/qtree/src', '/vol/vol/qtree/dst',
1014
def test_clone_fail(self):
1015
self.driver._discover_luns()
1016
self.driver._is_clone_done(0, '0', 'xxx')
992
1019
WSDL_HEADER_CMODE = """<?xml version="1.0" encoding="UTF-8"?>
993
1020
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
1193
1220
out.write('<binding name="CloudStorageBinding" '
1194
1221
'type="na:CloudStorage">')
1195
1222
out.write('<soap:binding style="document" ' +
1196
'transport="http://schemas.xmlsoap.org/soap/http"/>')
1223
'transport="http://schemas.xmlsoap.org/soap/http"/>')
1197
1224
for api in CMODE_APIS:
1198
1225
out.write('<operation name="%s">' % api)
1199
1226
out.write('<soap:operation soapAction=""/>')
1212
1239
request_xml = s.rfile.read(int(s.headers['Content-Length']))
1213
1240
ntap_ns = 'http://cloud.netapp.com/'
1214
1241
nsmap = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
1216
1243
root = etree.fromstring(request_xml)
1218
1245
body = root.xpath('/soapenv:Envelope/soapenv:Body',
1323
1350
class NetAppCmodeISCSIDriverTestCase(test.TestCase):
1324
1351
"""Test case for NetAppISCSIDriver"""
1326
'name': 'lun1', 'size': 1, 'volume_name': 'lun1',
1327
'os_type': 'linux', 'provider_location': 'lun1',
1328
'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
1329
'display_name': None, 'display_description': 'lun1',
1330
'volume_type_id': None
1333
'name': 'lun2', 'size': 1, 'volume_name': 'lun1',
1334
'volume_size': 1, 'project_id': 'project'
1337
'name': 'vol_snapshot', 'size': 1, 'volume_name': 'lun1',
1338
'os_type': 'linux', 'provider_location': 'lun1',
1339
'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
1340
'display_name': None, 'display_description': 'lun1',
1341
'volume_type_id': None
1352
volume = {'name': 'lun1', 'size': 1, 'volume_name': 'lun1',
1353
'os_type': 'linux', 'provider_location': 'lun1',
1354
'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
1355
'display_name': None, 'display_description': 'lun1',
1356
'volume_type_id': None}
1357
snapshot = {'name': 'lun2', 'size': 1, 'volume_name': 'lun1',
1358
'volume_size': 1, 'project_id': 'project'}
1359
volume_sec = {'name': 'vol_snapshot', 'size': 1, 'volume_name': 'lun1',
1360
'os_type': 'linux', 'provider_location': 'lun1',
1361
'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
1362
'display_name': None, 'display_description': 'lun1',
1363
'volume_type_id': None}
1344
1365
def setUp(self):
1345
1366
super(NetAppCmodeISCSIDriverTestCase, self).setUp()
1371
1392
self.volume['provider_location'] = updates['provider_location']
1372
1393
connector = {'initiator': 'init1'}
1373
1394
connection_info = self.driver.initialize_connection(self.volume,
1375
1396
self.assertEqual(connection_info['driver_volume_type'], 'iscsi')
1376
1397
properties = connection_info['data']
1377
1398
self.driver.terminate_connection(self.volume, connector)