summaryrefslogtreecommitdiffstats
path: root/nova/tests/test_netapp.py
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2012-10-23 19:30:48 -0700
committerVishvananda Ishaya <vishvananda@gmail.com>2012-10-28 11:34:05 -0700
commit7e2b93acc59dea81d52684f7f659fcff32507e14 (patch)
tree11bf7e96a3835d0002f133742dd9e1702c7cc6c6 /nova/tests/test_netapp.py
parent4e449c0843150b785bc61e87599d05ff242a8f4a (diff)
downloadnova-7e2b93acc59dea81d52684f7f659fcff32507e14.tar.gz
nova-7e2b93acc59dea81d52684f7f659fcff32507e14.tar.xz
nova-7e2b93acc59dea81d52684f7f659fcff32507e14.zip
removes the nova-volume code from nova
This removes the majority of the nova-volume code from the codebase. It updates relevent config options to default to cinder. It updates a number of existing tests that were depending on code that was removed. A few things still need to be removed: * volume/driver.py & volume/iscsi.py These files are used by the libvirt volume driver tests. These tests should be updated to mock the relevant calls. * scheduler/simple.py & scheduler/multi.py These files should no longer be necessary so they can be removed in a subsequent patch * exception.py cleanup Once the above files are removed there are a number of unused exceptions which can be removed * database calls and database tables The database calls have not been removed and the tables have not been dropped. This can be done in a separate migration * additional config options and nova.conf.sample There may be a few extra config options that can be removed and the conf sample can be regenerated Implements bp delete-nova-volume Change-Id: I0b540e54dbabd26901a7530035a38583bb521fda
Diffstat (limited to 'nova/tests/test_netapp.py')
-rw-r--r--nova/tests/test_netapp.py1380
1 files changed, 0 insertions, 1380 deletions
diff --git a/nova/tests/test_netapp.py b/nova/tests/test_netapp.py
deleted file mode 100644
index 79a8526ee..000000000
--- a/nova/tests/test_netapp.py
+++ /dev/null
@@ -1,1380 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2012 NetApp, Inc.
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-"""
-Tests for NetApp volume driver
-
-"""
-
-import BaseHTTPServer
-import httplib
-import StringIO
-
-from lxml import etree
-
-from nova.openstack.common import log as logging
-from nova import test
-from nova.volume import netapp
-
-
-LOG = logging.getLogger(__name__)
-
-
-WSDL_HEADER = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
- xmlns:na="http://www.netapp.com/management/v1"
- xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NetAppDfm"
- targetNamespace="http://www.netapp.com/management/v1">"""
-
-WSDL_TYPES = """<types>
-<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
- targetNamespace="http://www.netapp.com/management/v1">
-<xsd:element name="ApiProxy">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Request" type="na:Request"/>
- <xsd:element name="Target" type="xsd:string"/>
- <xsd:element minOccurs="0" name="Timeout" type="xsd:integer"/>
- <xsd:element minOccurs="0" name="Username" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="ApiProxyResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Response" type="na:Response"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditBegin">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetNameOrId" type="na:ObjNameOrId"/>
- <xsd:element minOccurs="0" name="Force" type="xsd:boolean"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditBeginResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditCommit">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="AssumeConfirmation"
- type="xsd:boolean"/>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditCommitResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="IsProvisioningFailure"
- type="xsd:boolean"/>
- <xsd:element minOccurs="0" name="JobIds" type="na:ArrayOfJobInfo"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditRollback">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetEditRollbackResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Datasets" type="na:ArrayOfDatasetInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ObjectNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetMembers"
- type="na:ArrayOfDatasetMemberInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetNameOrId" type="na:ObjNameOrId"/>
- <xsd:element minOccurs="0" name="IncludeExportsInfo"
- type="xsd:boolean"/>
- <xsd:element minOccurs="0" name="IncludeIndirect"
- type="xsd:boolean"/>
- <xsd:element minOccurs="0" name="MemberType" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetMemberListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetProvisionMember">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- <xsd:element name="ProvisionMemberRequestInfo"
- type="na:ProvisionMemberRequestInfo"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetProvisionMemberResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DatasetRemoveMember">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="DatasetMemberParameters"
- type="na:ArrayOfDatasetMemberParameter"/>
- <xsd:element minOccurs="0" name="Destroy" type="xsd:boolean"/>
- <xsd:element name="EditLockId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DatasetRemoveMemberResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="ProgressEvents"
- type="na:ArrayOfDpJobProgressEventInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="JobId" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DpJobProgressEventListIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DfmAbout">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="IncludeDirectorySizeInfo"
- type="xsd:boolean"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="DfmAboutResult">
- <xsd:complexType>
- <xsd:all/>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="HostListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Hosts" type="na:ArrayOfHostInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ObjectNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="HostListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterEnd">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterEndResult">
- <xsd:complexType/>
-</xsd:element>
-<xsd:element name="LunListInfoIterNext">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Maximum" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterNextResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Luns" type="na:ArrayOfLunInfo"/>
- <xsd:element name="Records" type="xsd:integer"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterStart">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ObjectNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="LunListInfoIterStartResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="Records" type="xsd:integer"/>
- <xsd:element name="Tag" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="StorageServiceDatasetProvision">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="AssumeConfirmation"
- type="xsd:boolean"/>
- <xsd:element name="DatasetName" type="na:ObjName"/>
- <xsd:element name="StorageServiceNameOrId" type="na:ObjNameOrId"/>
- <xsd:element minOccurs="0" name="StorageSetDetails"
- type="na:ArrayOfStorageSetInfo"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:element name="StorageServiceDatasetProvisionResult">
- <xsd:complexType>
- <xsd:all>
- <xsd:element minOccurs="0" name="ConformanceAlerts"
- type="na:ArrayOfConformanceAlert"/>
- <xsd:element name="DatasetId" type="na:ObjId"/>
- <xsd:element minOccurs="0" name="DryRunResults"
- type="na:ArrayOfDryRunResult"/>
- </xsd:all>
- </xsd:complexType>
-</xsd:element>
-<xsd:complexType name="ArrayOfDatasetInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DatasetInfo"
- type="na:DatasetInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDatasetMemberInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DatasetMemberInfo"
- type="na:DatasetMemberInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDatasetMemberParameter">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DatasetMemberParameter"
- type="na:DatasetMemberParameter"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDfmMetadataField">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DfmMetadataField"
- type="na:DfmMetadataField"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfDpJobProgressEventInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="DpJobProgressEventInfo"
- type="na:DpJobProgressEventInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfHostInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="HostInfo" type="na:HostInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfJobInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="JobInfo" type="na:JobInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfLunInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="LunInfo" type="na:LunInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="ArrayOfStorageSetInfo">
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="StorageSetInfo"
- type="na:StorageSetInfo"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="DatasetExportInfo">
- <xsd:all>
- <xsd:element minOccurs="0" name="DatasetExportProtocol"
- type="na:DatasetExportProtocol"/>
- <xsd:element minOccurs="0" name="DatasetLunMappingInfo"
- type="na:DatasetLunMappingInfo"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:simpleType name="DatasetExportProtocol">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:complexType name="DatasetInfo">
- <xsd:all>
- <xsd:element name="DatasetId" type="na:ObjId"/>
- <xsd:element name="DatasetName" type="na:ObjName"/>
- <xsd:element name="DatasetMetadata" type="na:ArrayOfDfmMetadataField"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DatasetLunMappingInfo">
- <xsd:all>
- <xsd:element name="IgroupOsType" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DatasetMemberInfo">
- <xsd:all>
- <xsd:element name="MemberId" type="na:ObjId"/>
- <xsd:element name="MemberName" type="na:ObjName"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DatasetMemberParameter">
- <xsd:all>
- <xsd:element name="ObjectNameOrId" type="na:ObjNameOrId"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DfmMetadataField">
- <xsd:all>
- <xsd:element name="FieldName" type="xsd:string"/>
- <xsd:element name="FieldValue" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="DpJobProgressEventInfo">
- <xsd:all>
- <xsd:element name="EventStatus" type="na:ObjStatus"/>
- <xsd:element name="EventType" type="xsd:string"/>
- <xsd:element minOccurs="0" name="ProgressLunInfo"
- type="na:ProgressLunInfo"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:simpleType name="DpPolicyNodeName">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:simpleType name="HostId">
- <xsd:restriction base="xsd:integer"/>
-</xsd:simpleType>
-<xsd:complexType name="HostInfo">
- <xsd:all>
- <xsd:element name="HostAddress" type="xsd:string"/>
- <xsd:element name="HostId" type="na:HostId"/>
- <xsd:element name="HostName" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="JobInfo">
- <xsd:all>
- <xsd:element name="JobId" type="xsd:integer"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="LunInfo">
- <xsd:all>
- <xsd:element name="HostId" type="na:ObjId"/>
- <xsd:element name="LunPath" type="na:ObjName"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:simpleType name="ObjId">
- <xsd:restriction base="xsd:integer"/>
-</xsd:simpleType>
-<xsd:simpleType name="ObjName">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:simpleType name="ObjNameOrId">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:simpleType name="ObjStatus">
- <xsd:restriction base="xsd:string"/>
-</xsd:simpleType>
-<xsd:complexType name="ProgressLunInfo">
- <xsd:all>
- <xsd:element name="LunPathId" type="na:ObjId"/>
- <xsd:element name="LunName" type="na:ObjName"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="ProvisionMemberRequestInfo">
- <xsd:all>
- <xsd:element minOccurs="0" name="Description" type="xsd:string"/>
- <xsd:element minOccurs="0" name="MaximumSnapshotSpace"
- type="xsd:integer"/>
- <xsd:element name="Name" type="xsd:string"/>
- <xsd:element name="Size" type="xsd:integer"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="Request">
- <xsd:all>
- <xsd:element minOccurs="0" name="Args">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:any maxOccurs="unbounded" minOccurs="0"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Name" type="xsd:string">
- </xsd:element>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="Response">
- <xsd:all>
- <xsd:element minOccurs="0" name="Errno" type="xsd:integer"/>
- <xsd:element minOccurs="0" name="Reason" type="xsd:string"/>
- <xsd:element minOccurs="0" name="Results">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:any maxOccurs="unbounded" minOccurs="0"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Status" type="xsd:string"/>
- </xsd:all>
-</xsd:complexType>
-<xsd:complexType name="StorageSetInfo">
- <xsd:all>
- <xsd:element minOccurs="0" name="DatasetExportInfo"
- type="na:DatasetExportInfo"/>
- <xsd:element minOccurs="0" name="DpNodeName"
- type="na:DpPolicyNodeName"/>
- <xsd:element minOccurs="0" name="ServerNameOrId"
- type="na:ObjNameOrId"/>
- </xsd:all>
-</xsd:complexType>
-</xsd:schema></types>"""
-
-WSDL_TRAILER = """<service name="DfmService">
-<port binding="na:DfmBinding" name="DfmPort">
-<soap:address location="https://HOST_NAME:8488/apis/soap/v1"/>
-</port></service></definitions>"""
-
-RESPONSE_PREFIX = """<?xml version="1.0" encoding="UTF-8"?>
-<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
- xmlns:na="http://www.netapp.com/management/v1"><env:Header/><env:Body>"""
-
-RESPONSE_SUFFIX = """</env:Body></env:Envelope>"""
-
-APIS = ['ApiProxy', 'DatasetListInfoIterStart', 'DatasetListInfoIterNext',
- 'DatasetListInfoIterEnd', 'DatasetEditBegin', 'DatasetEditCommit',
- 'DatasetProvisionMember', 'DatasetRemoveMember', 'DfmAbout',
- 'DpJobProgressEventListIterStart', 'DpJobProgressEventListIterNext',
- 'DpJobProgressEventListIterEnd', 'DatasetMemberListInfoIterStart',
- 'DatasetMemberListInfoIterNext', 'DatasetMemberListInfoIterEnd',
- 'HostListInfoIterStart', 'HostListInfoIterNext', 'HostListInfoIterEnd',
- 'LunListInfoIterStart', 'LunListInfoIterNext', 'LunListInfoIterEnd',
- 'StorageServiceDatasetProvision']
-
-iter_count = 0
-iter_table = {}
-
-
-class FakeDfmServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- """HTTP handler that fakes enough stuff to allow the driver to run"""
-
- def do_GET(s):
- """Respond to a GET request."""
- if '/dfm.wsdl' != s.path:
- s.send_response(404)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "application/wsdl+xml")
- s.end_headers()
- out = s.wfile
- out.write(WSDL_HEADER)
- out.write(WSDL_TYPES)
- for api in APIS:
- out.write('<message name="%sRequest">' % api)
- out.write('<part element="na:%s" name="parameters"/>' % api)
- out.write('</message>')
- out.write('<message name="%sResponse">' % api)
- out.write('<part element="na:%sResult" name="results"/>' % api)
- out.write('</message>')
- out.write('<portType name="DfmInterface">')
- for api in APIS:
- out.write('<operation name="%s">' % api)
- out.write('<input message="na:%sRequest"/>' % api)
- out.write('<output message="na:%sResponse"/>' % api)
- out.write('</operation>')
- out.write('</portType>')
- out.write('<binding name="DfmBinding" type="na:DfmInterface">')
- out.write('<soap:binding style="document" ' +
- 'transport="http://schemas.xmlsoap.org/soap/http"/>')
- for api in APIS:
- out.write('<operation name="%s">' % api)
- out.write('<soap:operation soapAction="urn:%s"/>' % api)
- out.write('<input><soap:body use="literal"/></input>')
- out.write('<output><soap:body use="literal"/></output>')
- out.write('</operation>')
- out.write('</binding>')
- out.write(WSDL_TRAILER)
-
- def do_POST(s):
- """Respond to a POST request."""
- if '/apis/soap/v1' != s.path:
- s.send_response(404)
- s.end_headers
- return
- request_xml = s.rfile.read(int(s.headers['Content-Length']))
- ntap_ns = 'http://www.netapp.com/management/v1'
- nsmap = {'env': 'http://schemas.xmlsoap.org/soap/envelope/',
- 'na': ntap_ns}
- root = etree.fromstring(request_xml)
-
- body = root.xpath('/env:Envelope/env:Body', namespaces=nsmap)[0]
- request = body.getchildren()[0]
- tag = request.tag
- if not tag.startswith('{' + ntap_ns + '}'):
- s.send_response(500)
- s.end_headers
- return
- api = tag[(2 + len(ntap_ns)):]
- global iter_count
- global iter_table
- if 'DatasetListInfoIterStart' == api:
- iter_name = 'dataset_%s' % iter_count
- iter_count = iter_count + 1
- iter_table[iter_name] = 0
- body = """<na:DatasetListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>%s</na:Tag>
- </na:DatasetListInfoIterStartResult>""" % iter_name
- elif 'DatasetListInfoIterNext' == api:
- tags = body.xpath('na:DatasetListInfoIterNext/na:Tag',
- namespaces=nsmap)
- iter_name = tags[0].text
- if iter_table[iter_name]:
- body = """<na:DatasetListInfoIterNextResult>
- <na:Datasets></na:Datasets>
- <na:Records>0</na:Records>
- </na:DatasetListInfoIterNextResult>"""
- else:
- iter_table[iter_name] = 1
- body = """<na:DatasetListInfoIterNextResult>
- <na:Datasets>
- <na:DatasetInfo>
- <na:DatasetId>0</na:DatasetId>
- <na:DatasetMetadata>
- <na:DfmMetadataField>
- <na:FieldName>OpenStackProject</na:FieldName>
- <na:FieldValue>testproj</na:FieldValue>
- </na:DfmMetadataField>
- <na:DfmMetadataField>
- <na:FieldName>OpenStackVolType</na:FieldName>
- <na:FieldValue></na:FieldValue>
- </na:DfmMetadataField>
- </na:DatasetMetadata>
- <na:DatasetName>OpenStack_testproj</na:DatasetName>
- </na:DatasetInfo>
- </na:Datasets>
- <na:Records>1</na:Records>
- </na:DatasetListInfoIterNextResult>"""
- elif 'DatasetListInfoIterEnd' == api:
- body = """<na:DatasetListInfoIterEndResult/>"""
- elif 'DatasetEditBegin' == api:
- body = """<na:DatasetEditBeginResult>
- <na:EditLockId>0</na:EditLockId>
- </na:DatasetEditBeginResult>"""
- elif 'DatasetEditCommit' == api:
- body = """<na:DatasetEditCommitResult>
- <na:IsProvisioningFailure>false</na:IsProvisioningFailure>
- <na:JobIds>
- <na:JobInfo>
- <na:JobId>0</na:JobId>
- </na:JobInfo>
- </na:JobIds>
- </na:DatasetEditCommitResult>"""
- elif 'DatasetProvisionMember' == api:
- body = """<na:DatasetProvisionMemberResult/>"""
- elif 'DatasetRemoveMember' == api:
- body = """<na:DatasetRemoveMemberResult/>"""
- elif 'DfmAbout' == api:
- body = """<na:DfmAboutResult/>"""
- elif 'DpJobProgressEventListIterStart' == api:
- iter_name = 'dpjobprogress_%s' % iter_count
- iter_count = iter_count + 1
- iter_table[iter_name] = 0
- body = """<na:DpJobProgressEventListIterStartResult>
- <na:Records>2</na:Records>
- <na:Tag>%s</na:Tag>
- </na:DpJobProgressEventListIterStartResult>""" % iter_name
- elif 'DpJobProgressEventListIterNext' == api:
- tags = body.xpath('na:DpJobProgressEventListIterNext/na:Tag',
- namespaces=nsmap)
- iter_name = tags[0].text
- if iter_table[iter_name]:
- body = """<na:DpJobProgressEventListIterNextResult/>"""
- else:
- iter_table[iter_name] = 1
- name = ('filer:/OpenStack_testproj/volume-00000001/'
- 'volume-00000001')
- body = """<na:DpJobProgressEventListIterNextResult>
- <na:ProgressEvents>
- <na:DpJobProgressEventInfo>
- <na:EventStatus>normal</na:EventStatus>
- <na:EventType>lun-create</na:EventType>
- <na:ProgressLunInfo>
- <na:LunPathId>0</na:LunPathId>
- <na:LunName>%s</na:LunName>
- </na:ProgressLunInfo>
- </na:DpJobProgressEventInfo>
- <na:DpJobProgressEventInfo>
- <na:EventStatus>normal</na:EventStatus>
- <na:EventType>job-end</na:EventType>
- </na:DpJobProgressEventInfo>
- </na:ProgressEvents>
- <na:Records>2</na:Records>
- </na:DpJobProgressEventListIterNextResult>""" % name
- elif 'DpJobProgressEventListIterEnd' == api:
- body = """<na:DpJobProgressEventListIterEndResult/>"""
- elif 'DatasetMemberListInfoIterStart' == api:
- iter_name = 'datasetmember_%s' % iter_count
- iter_count = iter_count + 1
- iter_table[iter_name] = 0
- body = """<na:DatasetMemberListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>%s</na:Tag>
- </na:DatasetMemberListInfoIterStartResult>""" % iter_name
- elif 'DatasetMemberListInfoIterNext' == api:
- tags = body.xpath('na:DatasetMemberListInfoIterNext/na:Tag',
- namespaces=nsmap)
- iter_name = tags[0].text
- if iter_table[iter_name]:
- body = """<na:DatasetMemberListInfoIterNextResult>
- <na:DatasetMembers></na:DatasetMembers>
- <na:Records>0</na:Records>
- </na:DatasetMemberListInfoIterNextResult>"""
- else:
- iter_table[iter_name] = 1
- name = ('filer:/OpenStack_testproj/volume-00000001/'
- 'volume-00000001')
- body = """<na:DatasetMemberListInfoIterNextResult>
- <na:DatasetMembers>
- <na:DatasetMemberInfo>
- <na:MemberId>0</na:MemberId>
- <na:MemberName>%s</na:MemberName>
- </na:DatasetMemberInfo>
- </na:DatasetMembers>
- <na:Records>1</na:Records>
- </na:DatasetMemberListInfoIterNextResult>""" % name
- elif 'DatasetMemberListInfoIterEnd' == api:
- body = """<na:DatasetMemberListInfoIterEndResult/>"""
- elif 'HostListInfoIterStart' == api:
- body = """<na:HostListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>host</na:Tag>
- </na:HostListInfoIterStartResult>"""
- elif 'HostListInfoIterNext' == api:
- body = """<na:HostListInfoIterNextResult>
- <na:Hosts>
- <na:HostInfo>
- <na:HostAddress>1.2.3.4</na:HostAddress>
- <na:HostId>0</na:HostId>
- <na:HostName>filer</na:HostName>
- </na:HostInfo>
- </na:Hosts>
- <na:Records>1</na:Records>
- </na:HostListInfoIterNextResult>"""
- elif 'HostListInfoIterEnd' == api:
- body = """<na:HostListInfoIterEndResult/>"""
- elif 'LunListInfoIterStart' == api:
- body = """<na:LunListInfoIterStartResult>
- <na:Records>1</na:Records>
- <na:Tag>lun</na:Tag>
- </na:LunListInfoIterStartResult>"""
- elif 'LunListInfoIterNext' == api:
- path = 'OpenStack_testproj/volume-00000001/volume-00000001'
- body = """<na:LunListInfoIterNextResult>
- <na:Luns>
- <na:LunInfo>
- <na:HostId>0</na:HostId>
- <na:LunPath>%s</na:LunPath>
- </na:LunInfo>
- </na:Luns>
- <na:Records>1</na:Records>
- </na:LunListInfoIterNextResult>""" % path
- elif 'LunListInfoIterEnd' == api:
- body = """<na:LunListInfoIterEndResult/>"""
- elif 'ApiProxy' == api:
- names = body.xpath('na:ApiProxy/na:Request/na:Name',
- namespaces=nsmap)
- proxy = names[0].text
- if 'igroup-list-info' == proxy:
- igroup = 'openstack-iqn.1993-08.org.debian:01:23456789'
- initiator = 'iqn.1993-08.org.debian:01:23456789'
- proxy_body = """<initiator-groups>
- <initiator-group-info>
- <initiator-group-name>%s</initiator-group-name>
- <initiator-group-type>iscsi</initiator-group-type>
- <initiator-group-os-type>linux</initiator-group-os-type>
- <initiators>
- <initiator-info>
- <initiator-name>%s</initiator-name>
- </initiator-info>
- </initiators>
- </initiator-group-info>
- </initiator-groups>""" % (igroup, initiator)
- elif 'igroup-create' == proxy:
- proxy_body = ''
- elif 'igroup-add' == proxy:
- proxy_body = ''
- elif 'lun-map-list-info' == proxy:
- proxy_body = '<initiator-groups/>'
- elif 'lun-map' == proxy:
- proxy_body = '<lun-id-assigned>0</lun-id-assigned>'
- elif 'lun-unmap' == proxy:
- proxy_body = ''
- elif 'iscsi-portal-list-info' == proxy:
- proxy_body = """<iscsi-portal-list-entries>
- <iscsi-portal-list-entry-info>
- <ip-address>1.2.3.4</ip-address>
- <ip-port>3260</ip-port>
- <tpgroup-tag>1000</tpgroup-tag>
- </iscsi-portal-list-entry-info>
- </iscsi-portal-list-entries>"""
- elif 'iscsi-node-get-name' == proxy:
- target = 'iqn.1992-08.com.netapp:sn.111111111'
- proxy_body = '<node-name>%s</node-name>' % target
- else:
- # Unknown proxy API
- s.send_response(500)
- s.end_headers
- return
- api = api + ':' + proxy
- proxy_header = '<na:ApiProxyResult><na:Response><na:Results>'
- proxy_trailer = """</na:Results><na:Status>passed</na:Status>
- </na:Response></na:ApiProxyResult>"""
- body = proxy_header + proxy_body + proxy_trailer
- else:
- # Unknown API
- s.send_response(500)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "text/xml; charset=utf-8")
- s.end_headers()
- s.wfile.write(RESPONSE_PREFIX)
- s.wfile.write(body)
- s.wfile.write(RESPONSE_SUFFIX)
-
-
-class FakeHttplibSocket(object):
- """A fake socket implementation for httplib.HTTPResponse"""
- def __init__(self, value):
- self._rbuffer = StringIO.StringIO(value)
- self._wbuffer = StringIO.StringIO('')
- oldclose = self._wbuffer.close
-
- def newclose():
- self.result = self._wbuffer.getvalue()
- oldclose()
- self._wbuffer.close = newclose
-
- def makefile(self, mode, _other):
- """Returns the socket's internal buffer"""
- if mode == 'r' or mode == 'rb':
- return self._rbuffer
- if mode == 'w' or mode == 'wb':
- return self._wbuffer
-
-
-class FakeHTTPConnection(object):
- """A fake httplib.HTTPConnection for netapp tests
-
- Requests made via this connection actually get translated and routed into
- the fake Dfm handler above, we then turn the response into
- the httplib.HTTPResponse that the caller expects.
- """
- def __init__(self, host, timeout=None):
- self.host = host
-
- def request(self, method, path, data=None, headers=None):
- if not headers:
- headers = {}
- req_str = '%s %s HTTP/1.1\r\n' % (method, path)
- for key, value in headers.iteritems():
- req_str += "%s: %s\r\n" % (key, value)
- if data:
- req_str += '\r\n%s' % data
-
- # NOTE(vish): normally the http transport normailizes from unicode
- sock = FakeHttplibSocket(req_str.decode("latin-1").encode("utf-8"))
- # NOTE(vish): stop the server from trying to look up address from
- # the fake socket
- FakeDfmServerHandler.address_string = lambda x: '127.0.0.1'
- self.app = FakeDfmServerHandler(sock, '127.0.0.1:8088', None)
-
- self.sock = FakeHttplibSocket(sock.result)
- self.http_response = httplib.HTTPResponse(self.sock)
-
- def set_debuglevel(self, level):
- pass
-
- def getresponse(self):
- self.http_response.begin()
- return self.http_response
-
- def getresponsebody(self):
- return self.sock.result
-
-
-class NetAppDriverTestCase(test.TestCase):
- """Test case for NetAppISCSIDriver"""
- STORAGE_SERVICE = 'Openstack Service'
- STORAGE_SERVICE_PREFIX = 'Openstack Service-'
- PROJECT_ID = 'testproj'
- VOLUME_NAME = 'volume-00000001'
- VOLUME_TYPE = ''
- VOLUME_SIZE = 2147483648L # 2 GB
- INITIATOR = 'iqn.1993-08.org.debian:01:23456789'
-
- def setUp(self):
- super(NetAppDriverTestCase, self).setUp()
- driver = netapp.NetAppISCSIDriver()
- self.stubs.Set(httplib, 'HTTPConnection', FakeHTTPConnection)
- driver._create_client(wsdl_url='http://localhost:8088/dfm.wsdl',
- login='root', password='password',
- hostname='localhost', port=8088, cache=False)
- driver._set_storage_service(self.STORAGE_SERVICE)
- driver._set_storage_service_prefix(self.STORAGE_SERVICE_PREFIX)
- driver._set_vfiler('')
- self.driver = driver
-
- def test_connect(self):
- self.driver.check_for_setup_error()
-
- def test_create_destroy(self):
- self.driver._discover_luns()
- self.driver._provision(self.VOLUME_NAME, None, self.PROJECT_ID,
- self.VOLUME_TYPE, self.VOLUME_SIZE)
- self.driver._remove_destroy(self.VOLUME_NAME, self.PROJECT_ID)
-
- def test_map_unmap(self):
- self.driver._discover_luns()
- self.driver._provision(self.VOLUME_NAME, None, self.PROJECT_ID,
- self.VOLUME_TYPE, self.VOLUME_SIZE)
- volume = {'name': self.VOLUME_NAME, 'project_id': self.PROJECT_ID,
- 'id': 0, 'provider_auth': None}
- updates = self.driver._get_export(volume)
- self.assertTrue(updates['provider_location'])
- volume['provider_location'] = updates['provider_location']
- connector = {'initiator': self.INITIATOR}
- connection_info = self.driver.initialize_connection(volume, connector)
- self.assertEqual(connection_info['driver_volume_type'], 'iscsi')
- properties = connection_info['data']
- self.driver.terminate_connection(volume, connector)
- self.driver._remove_destroy(self.VOLUME_NAME, self.PROJECT_ID)
-
-
-WSDL_HEADER_CMODE = """<?xml version="1.0" encoding="UTF-8"?>
-<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
- xmlns:na="http://cloud.netapp.com/"
-xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-xmlns="http://schemas.xmlsoap.org/wsdl/"
-targetNamespace="http://cloud.netapp.com/" name="CloudStorageService">
-"""
-
-WSDL_TYPES_CMODE = """<types>
-<xs:schema xmlns:na="http://cloud.netapp.com/"
-xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"
-targetNamespace="http://cloud.netapp.com/">
-
- <xs:element name="ProvisionLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Name" type="xs:string"/>
- <xs:element name="Size" type="xsd:long"/>
- <xs:element name="Metadata" type="na:Metadata" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="ProvisionLunResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="Lun" type="na:Lun"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="DestroyLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="DestroyLunResult">
- <xs:complexType>
- <xs:all/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="CloneLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="NewName" type="xsd:string"/>
- <xs:element name="Metadata" type="na:Metadata" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="CloneLunResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="Lun" type="na:Lun"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="MapLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="InitiatorType" type="xsd:string"/>
- <xs:element name="InitiatorName" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="MapLunResult">
- <xs:complexType>
- <xs:all/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="UnmapLun">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="InitiatorType" type="xsd:string"/>
- <xs:element name="InitiatorName" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="UnmapLunResult">
- <xs:complexType>
- <xs:all/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="ListLuns">
- <xs:complexType>
- <xs:all>
- <xs:element name="NameFilter" type="xsd:string" minOccurs="0"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="ListLunsResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="Lun" type="na:Lun" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="GetLunTargetDetails">
- <xs:complexType>
- <xs:all>
- <xs:element name="Handle" type="xsd:string"/>
- <xs:element name="InitiatorType" type="xsd:string"/>
- <xs:element name="InitiatorName" type="xsd:string"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:element name="GetLunTargetDetailsResult">
- <xs:complexType>
- <xs:all>
- <xs:element name="TargetDetails" type="na:TargetDetails"
- minOccurs="0" maxOccurs="unbounded"/>
- </xs:all>
- </xs:complexType>
- </xs:element>
-
- <xs:complexType name="Metadata">
- <xs:sequence>
- <xs:element name="Key" type="xs:string"/>
- <xs:element name="Value" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
-
- <xs:complexType name="Lun">
- <xs:sequence>
- <xs:element name="Name" type="xs:string"/>
- <xs:element name="Size" type="xs:long"/>
- <xs:element name="Handle" type="xs:string"/>
- <xs:element name="Metadata" type="na:Metadata" minOccurs="0"
- maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:complexType>
-
- <xs:complexType name="TargetDetails">
- <xs:sequence>
- <xs:element name="Address" type="xs:string"/>
- <xs:element name="Port" type="xs:int"/>
- <xs:element name="Portal" type="xs:int"/>
- <xs:element name="Iqn" type="xs:string"/>
- <xs:element name="LunNumber" type="xs:int"/>
- </xs:sequence>
- </xs:complexType>
-
- </xs:schema></types>"""
-
-WSDL_TRAILER_CMODE = """<service name="CloudStorageService">
- <port name="CloudStoragePort" binding="na:CloudStorageBinding">
- <soap:address location="http://hostname:8080/ws/ntapcloud"/>
- </port>
- </service>
-</definitions>"""
-
-RESPONSE_PREFIX_CMODE = """<?xml version='1.0' encoding='UTF-8'?>
-<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
-<soapenv:Body>"""
-
-RESPONSE_SUFFIX_CMODE = """</soapenv:Body></soapenv:Envelope>"""
-
-CMODE_APIS = ['ProvisionLun', 'DestroyLun', 'CloneLun', 'MapLun', 'UnmapLun',
- 'ListLuns', 'GetLunTargetDetails']
-
-
-class FakeCMODEServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- """HTTP handler that fakes enough stuff to allow the driver to run"""
-
- def do_GET(s):
- """Respond to a GET request."""
- if '/ntap_cloud.wsdl' != s.path:
- s.send_response(404)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "application/wsdl+xml")
- s.end_headers()
- out = s.wfile
- out.write(WSDL_HEADER_CMODE)
- out.write(WSDL_TYPES_CMODE)
- for api in CMODE_APIS:
- out.write('<message name="%sRequest">' % api)
- out.write('<part element="na:%s" name="req"/>' % api)
- out.write('</message>')
- out.write('<message name="%sResponse">' % api)
- out.write('<part element="na:%sResult" name="res"/>' % api)
- out.write('</message>')
- out.write('<portType name="CloudStorage">')
- for api in CMODE_APIS:
- out.write('<operation name="%s">' % api)
- out.write('<input message="na:%sRequest"/>' % api)
- out.write('<output message="na:%sResponse"/>' % api)
- out.write('</operation>')
- out.write('</portType>')
- out.write('<binding name="CloudStorageBinding" '
- 'type="na:CloudStorage">')
- out.write('<soap:binding style="document" ' +
- 'transport="http://schemas.xmlsoap.org/soap/http"/>')
- for api in CMODE_APIS:
- out.write('<operation name="%s">' % api)
- out.write('<soap:operation soapAction=""/>')
- out.write('<input><soap:body use="literal"/></input>')
- out.write('<output><soap:body use="literal"/></output>')
- out.write('</operation>')
- out.write('</binding>')
- out.write(WSDL_TRAILER_CMODE)
-
- def do_POST(s):
- """Respond to a POST request."""
- if '/ws/ntapcloud' != s.path:
- s.send_response(404)
- s.end_headers
- return
- request_xml = s.rfile.read(int(s.headers['Content-Length']))
- ntap_ns = 'http://cloud.netapp.com/'
- nsmap = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
- 'na': ntap_ns}
- root = etree.fromstring(request_xml)
-
- body = root.xpath('/soapenv:Envelope/soapenv:Body',
- namespaces=nsmap)[0]
- request = body.getchildren()[0]
- tag = request.tag
- if not tag.startswith('{' + ntap_ns + '}'):
- s.send_response(500)
- s.end_headers
- return
- api = tag[(2 + len(ntap_ns)):]
- if 'ProvisionLun' == api:
- body = """<ns:ProvisionLunResult xmlns:ns=
- "http://cloud.netapp.com/">
- <Lun><Name>lun1</Name><Size>20</Size>
- <Handle>1d9c006c-a406-42f6-a23f-5ed7a6dc33e3</Handle>
- <Metadata><Key>OsType</Key>
- <Value>linux</Value></Metadata></Lun>
- </ns:ProvisionLunResult>"""
- elif 'DestroyLun' == api:
- body = """<ns:DestroyLunResult xmlns:ns="http://cloud.netapp.com/"
- />"""
- elif 'CloneLun' == api:
- body = """<ns:CloneLunResult xmlns:ns="http://cloud.netapp.com/">
- <Lun><Name>lun2</Name><Size>2</Size>
- <Handle>98ea1791d228453899d422b4611642c3</Handle>
- <Metadata><Key>OsType</Key>
- <Value>linux</Value></Metadata>
- </Lun></ns:CloneLunResult>"""
- elif 'MapLun' == api:
- body = """<ns1:MapLunResult xmlns:ns="http://cloud.netapp.com/"
- />"""
- elif 'Unmap' == api:
- body = """<ns1:UnmapLunResult xmlns:ns="http://cloud.netapp.com/"
- />"""
- elif 'ListLuns' == api:
- body = """<ns:ListLunsResult xmlns:ns="http://cloud.netapp.com/">
- <Lun>
- <Name>lun1</Name>
- <Size>20</Size>
- <Handle>asdjdnsd</Handle>
- </Lun>
- </ns:ListLunsResult>"""
- elif 'GetLunTargetDetails' == api:
- body = """<ns:GetLunTargetDetailsResult
- xmlns:ns="http://cloud.netapp.com/">
- <TargetDetail>
- <Address>1.2.3.4</Address>
- <Port>3260</Port>
- <Portal>1000</Portal>
- <Iqn>iqn.199208.com.netapp:sn.123456789</Iqn>
- <LunNumber>0</LunNumber>
- </TargetDetail>
- </ns:GetLunTargetDetailsResult>"""
- else:
- # Unknown API
- s.send_response(500)
- s.end_headers
- return
- s.send_response(200)
- s.send_header("Content-Type", "text/xml; charset=utf-8")
- s.end_headers()
- s.wfile.write(RESPONSE_PREFIX_CMODE)
- s.wfile.write(body)
- s.wfile.write(RESPONSE_SUFFIX_CMODE)
-
-
-class FakeCmodeHTTPConnection(object):
- """A fake httplib.HTTPConnection for netapp tests
-
- Requests made via this connection actually get translated and routed into
- the fake Dfm handler above, we then turn the response into
- the httplib.HTTPResponse that the caller expects.
- """
- def __init__(self, host, timeout=None):
- self.host = host
-
- def request(self, method, path, data=None, headers=None):
- if not headers:
- headers = {}
- req_str = '%s %s HTTP/1.1\r\n' % (method, path)
- for key, value in headers.iteritems():
- req_str += "%s: %s\r\n" % (key, value)
- if data:
- req_str += '\r\n%s' % data
-
- # NOTE(vish): normally the http transport normailizes from unicode
- sock = FakeHttplibSocket(req_str.decode("latin-1").encode("utf-8"))
- # NOTE(vish): stop the server from trying to look up address from
- # the fake socket
- FakeCMODEServerHandler.address_string = lambda x: '127.0.0.1'
- self.app = FakeCMODEServerHandler(sock, '127.0.0.1:8080', None)
-
- self.sock = FakeHttplibSocket(sock.result)
- self.http_response = httplib.HTTPResponse(self.sock)
-
- def set_debuglevel(self, level):
- pass
-
- def getresponse(self):
- self.http_response.begin()
- return self.http_response
-
- def getresponsebody(self):
- return self.sock.result
-
-
-class NetAppCmodeISCSIDriverTestCase(test.TestCase):
- """Test case for NetAppISCSIDriver"""
- volume = {
- 'name': 'lun1', 'size': 1, 'volume_name': 'lun1',
- 'os_type': 'linux', 'provider_location': 'lun1',
- 'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
- 'display_name': None, 'display_description': 'lun1',
- 'volume_type_id': None
- }
- snapshot = {
- 'name': 'lun2', 'size': 1, 'volume_name': 'lun1',
- 'volume_size': 1, 'project_id': 'project'
- }
- volume_sec = {
- 'name': 'vol_snapshot', 'size': 1, 'volume_name': 'lun1',
- 'os_type': 'linux', 'provider_location': 'lun1',
- 'id': 'lun1', 'provider_auth': None, 'project_id': 'project',
- 'display_name': None, 'display_description': 'lun1',
- 'volume_type_id': None
- }
-
- def setUp(self):
- super(NetAppCmodeISCSIDriverTestCase, self).setUp()
- driver = netapp.NetAppCmodeISCSIDriver()
- self.stubs.Set(httplib, 'HTTPConnection', FakeCmodeHTTPConnection)
- driver._create_client(wsdl_url='http://localhost:8080/ntap_cloud.wsdl',
- login='root', password='password',
- hostname='localhost', port=8080, cache=False)
- self.driver = driver
-
- def test_connect(self):
- self.driver.check_for_setup_error()
-
- def test_create_destroy(self):
- self.driver.create_volume(self.volume)
- self.driver.delete_volume(self.volume)
-
- def test_create_vol_snapshot_destroy(self):
- self.driver.create_volume(self.volume)
- self.driver.create_snapshot(self.snapshot)
- self.driver.create_volume_from_snapshot(self.volume_sec, self.snapshot)
- self.driver.delete_snapshot(self.snapshot)
- self.driver.delete_volume(self.volume)
-
- def test_map_unmap(self):
- self.driver.create_volume(self.volume)
- updates = self.driver.create_export(None, self.volume)
- self.assertTrue(updates['provider_location'])
- self.volume['provider_location'] = updates['provider_location']
- connector = {'initiator': 'init1'}
- connection_info = self.driver.initialize_connection(self.volume,
- connector)
- self.assertEqual(connection_info['driver_volume_type'], 'iscsi')
- properties = connection_info['data']
- self.driver.terminate_connection(self.volume, connector)
- self.driver.delete_volume(self.volume)