Implements: Hedvig Fuel Cinder Plugin
Change-Id: I72b7311a3ad156cc43ce56eff91090d61000a49d
This commit is contained in:
parent
1eabe89f91
commit
1328ec6e28
|
@ -0,0 +1,3 @@
|
|||
.tox
|
||||
.build
|
||||
*.pyc
|
|
@ -0,0 +1,202 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
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.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
fuel-plugin-hedvig-cinder
|
||||
============
|
||||
|
||||
Plugin description
|
|
@ -0,0 +1,5 @@
|
|||
$plugin_settings = hiera('fuel-plugin-hedvig-cinder')
|
||||
$services = ['cinder-volume']
|
||||
$metadata_server = $plugin_settings['hedvig_metadata_server']
|
||||
$volume_type = "hedvig"
|
||||
class {'plugin_hedvig_cinder': }
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,133 @@
|
|||
from eventlet.green import threading
|
||||
import socket
|
||||
import os
|
||||
import hedvigpyc as hc
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
TO_MEGABYTES = 1024 * 1024
|
||||
TO_GIGABYTES = TO_MEGABYTES * 1024
|
||||
|
||||
class ReplicationPolicy:
|
||||
Agnostic = 0
|
||||
RackAware = 1
|
||||
DataCenterAware = 2
|
||||
|
||||
_VALUES_TO_NAMES = {
|
||||
0: "Agnostic",
|
||||
1: "RackAware",
|
||||
2: "DataCenterAware",
|
||||
}
|
||||
|
||||
_NAMES_TO_VALUES = {
|
||||
"Agnostic": 0,
|
||||
"RackAware": 1,
|
||||
"DataCenterAware": 2,
|
||||
}
|
||||
|
||||
class DiskResidence:
|
||||
Flash = 0
|
||||
HDD = 1
|
||||
|
||||
_VALUES_TO_NAMES = {
|
||||
0: "Flash",
|
||||
1: "HDD",
|
||||
}
|
||||
|
||||
_NAMES_TO_VALUES = {
|
||||
"Flash": 0,
|
||||
"HDD": 1,
|
||||
}
|
||||
|
||||
class HedvigConfig():
|
||||
lock_ = threading.RLock()
|
||||
instance_ = None
|
||||
|
||||
# Default Port Configuration
|
||||
defaultHControllerPort_ = 50000
|
||||
|
||||
# Default Cinder Configuration
|
||||
defaultCinderReplicationFactor_ = 3
|
||||
defaultCinderDedupEnable_ = False
|
||||
defaultCinderCompressEnable_ = False
|
||||
defaultCinderCacheEnable_ = False
|
||||
defaultCinderDiskResidence_ = DiskResidence.HDD
|
||||
defaultCinderReplicationPolicy_ = ReplicationPolicy.Agnostic
|
||||
|
||||
def __init__(self):
|
||||
self.hcontrollerPort_ = HedvigConfig.defaultHControllerPort_
|
||||
|
||||
self.cinderReplicationFactor_ = HedvigConfig.defaultCinderReplicationFactor_
|
||||
self.cinderReplicationPolicy_ = HedvigConfig.defaultCinderReplicationPolicy_
|
||||
self.cinderDedupEnable_ = HedvigConfig.defaultCinderDedupEnable_
|
||||
self.cinderCompressEnable_ = HedvigConfig.defaultCinderCompressEnable_
|
||||
self.cinderCacheEnable_ = HedvigConfig.defaultCinderCacheEnable_
|
||||
self.cinderDiskResidence_ = HedvigConfig.defaultCinderDiskResidence_
|
||||
|
||||
@classmethod
|
||||
def parseAndGetBooleanEntry(cls, entry):
|
||||
entry = entry.strip(" \t\n").lower()
|
||||
if entry == "true":
|
||||
return True
|
||||
elif entry == "false":
|
||||
return False
|
||||
else:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def parseAndGetReplicationPolicy(cls, strReplicationPolicy):
|
||||
strReplicationPolicy = strReplicationPolicy.strip(" \n\t").lower()
|
||||
if strReplicationPolicy == ReplicationPolicy._VALUES_TO_NAMES[ReplicationPolicy.Agnostic].lower():
|
||||
return ReplicationPolicy.Agnostic
|
||||
elif strReplicationPolicy == ReplicationPolicy._VALUES_TO_NAMES[ReplicationPolicy.RackAware].lower():
|
||||
return ReplicationPolicy.RackAware
|
||||
elif strReplicationPolicy == ReplicationPolicy._VALUES_TO_NAMES[ReplicationPolicy.DataCenterAware].lower():
|
||||
return ReplicationPolicy.DataCenterAware
|
||||
else:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def parseAndGetDiskResidence(cls, strDiskResidence):
|
||||
strDiskResidence = strDiskResidence.strip(" \n\t").lower()
|
||||
if strDiskResidence == DiskResidence._VALUES_TO_NAMES[DiskResidence.HDD].lower():
|
||||
return DiskResidence.HDD
|
||||
elif strDiskResidence == DiskResidence._VALUES_TO_NAMES[DiskResidence.Flash].lower():
|
||||
return DiskResidence.Flash
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if not HedvigConfig.instance_:
|
||||
with HedvigConfig.lock_:
|
||||
if not HedvigConfig.instance_:
|
||||
try:
|
||||
HedvigConfig.instance_ = HedvigConfig()
|
||||
LOG.info(_LI('HedvigConfig initialized'))
|
||||
except Exception:
|
||||
LOG.error(_LE('Failed to initialize HedvigConfig'))
|
||||
raise
|
||||
return HedvigConfig.instance_
|
||||
|
||||
def getHedvigControllerPort(self):
|
||||
return self.hcontrollerPort_;
|
||||
|
||||
def getCinderReplicationFactor(self):
|
||||
return self.cinderReplicationFactor_
|
||||
|
||||
def getCinderReplicationPolicy(self):
|
||||
return self.cinderReplicationPolicy_
|
||||
|
||||
def isCinderDedupEnabled(self):
|
||||
return self.cinderDedupEnable_
|
||||
|
||||
def isCinderCacheEnabled(self):
|
||||
return self.cinderCacheEnable_
|
||||
|
||||
def isCinderCompressEnabled(self):
|
||||
return self.cinderCompressEnable_
|
||||
|
||||
def getCinderDiskResidence(self):
|
||||
return self.cinderDiskResidence_
|
|
@ -0,0 +1,383 @@
|
|||
from eventlet.green import os
|
||||
import eventlet
|
||||
import eventlet.queue
|
||||
import os, fcntl
|
||||
import hedvigpyc as hc
|
||||
import time
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
class HedvigPipe():
|
||||
|
||||
pipeQ_ = eventlet.queue.Queue()
|
||||
|
||||
def __init__(self):
|
||||
rfd, wfd = os.pipe()
|
||||
self.rfd_ = rfd
|
||||
self.wfd_ = wfd
|
||||
|
||||
def __del__(self):
|
||||
fds = [self.wfd_, self.rfd_]
|
||||
for fd in fds:
|
||||
try:
|
||||
os.close(fd)
|
||||
except:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def get(cls):
|
||||
try:
|
||||
entry = HedvigPipe.pipeQ_.get(False)
|
||||
HedvigPipe.pipeQ_.task_done()
|
||||
except:
|
||||
entry = HedvigPipe()
|
||||
return entry
|
||||
|
||||
@classmethod
|
||||
def put(cls, hedvigPipe):
|
||||
HedvigPipe.pipeQ_.put(hedvigPipe)
|
||||
|
||||
class HedvigOpCb():
|
||||
def __init__(self):
|
||||
self.startTime_ = time.time()
|
||||
self.hedvigPipe_ = HedvigPipe.get()
|
||||
self.rfd_ = self.hedvigPipe_.rfd_
|
||||
self.wfd_ = self.hedvigPipe_.wfd_
|
||||
fcntl.fcntl(self.rfd_, fcntl.F_SETFL, os.O_NONBLOCK)
|
||||
self.id_ = Helper.getId()
|
||||
self.pyCallback_ = hc.ObjWithPyCallback()
|
||||
self.pyCallback_.setCallback(self)
|
||||
self.pyCallback_.wfd_ = self.wfd_
|
||||
|
||||
def __str__(self):
|
||||
return (("HedvigBaseCb:id:%s:rfd:%s:wfd:%s") %(self.id_, self.rfd_, self.wfd_))
|
||||
|
||||
def __call__(self, x):
|
||||
LOG.debug("Callback received: %s", self)
|
||||
|
||||
def closeFds(self):
|
||||
if not (self.wfd_ or self.rfd_):
|
||||
return
|
||||
fds = [self.wfd_, self.rfd_]
|
||||
self.wfd_ = None
|
||||
self.rfd_ = None
|
||||
for fd in fds:
|
||||
if fd:
|
||||
try:
|
||||
os.close(fd)
|
||||
except:
|
||||
pass
|
||||
LOG.debug("Closed Fds: %s", self)
|
||||
|
||||
def waitForResult(self, instance):
|
||||
LOG.debug("Waiting for result: %s", self)
|
||||
eventlet.hubs.trampoline(self.rfd_, read= True)
|
||||
LOG.debug("Received notification for result: %s", self)
|
||||
os.read(self.rfd_, 1024)
|
||||
HedvigPipe.pipeQ_.put(self.hedvigPipe_)
|
||||
self.endTime_ = time.time()
|
||||
|
||||
def __del__(self, instance):
|
||||
LOG.debug("Deleting object: %s", self)
|
||||
|
||||
@classmethod
|
||||
def hedvigpycInit(cls, pagesSeedMap, workerThreadCount):
|
||||
hc.hedvigpycInit(pagesSeedMap, workerThreadCount)
|
||||
|
||||
@classmethod
|
||||
def hedvigpycShutdown(cls):
|
||||
hc.hedvigpycShutdown()
|
||||
|
||||
class HGetTgtInstanceOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,host):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HGetTgtInstanceOp()
|
||||
self.op_.host_ = str(host)
|
||||
|
||||
def getTgtInstance(self):
|
||||
self.pyCallback_.getTgtInstance(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.tgtMap_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HDescribeVirtualDiskOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,vDiskName):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HDescribeVirtualDiskOp()
|
||||
self.op_.vDiskName_ = str(vDiskName)
|
||||
|
||||
def describeVirtualDisk(self):
|
||||
self.pyCallback_.describeVirtualDisk(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.vDiskInfo_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HGetLunCinderOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,tgtHost,tgtPort,vDiskName):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HGetLunCinderOp()
|
||||
self.op_.tgtHost_ = str(tgtHost)
|
||||
self.op_.tgtPort_ = tgtPort
|
||||
self.op_.vDiskName_ = str(vDiskName)
|
||||
|
||||
def getLunCinder(self):
|
||||
self.pyCallback_.getLunCinder(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.lunNumber_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HAddLunOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,tgtHost,tgtPort,vDiskInfo):
|
||||
HedvigOpCb.__init__(self)
|
||||
LOG.debug("Addlun for virtual disk: %s", vDiskInfo.vDiskName)
|
||||
self.op_ = hc.HAddLunOp()
|
||||
self.op_.tgtHost_ = str(tgtHost)
|
||||
self.op_.tgtPort_ = tgtPort
|
||||
self.op_.vDiskInfo_ = hc.VDiskInfo()
|
||||
self.op_.vDiskInfo_.dedup = vDiskInfo.dedup
|
||||
self.op_.vDiskInfo_.vDiskName = str(vDiskInfo.vDiskName)
|
||||
self.op_.vDiskInfo_.createdBy = str(vDiskInfo.createdBy)
|
||||
self.op_.vDiskInfo_.size = vDiskInfo.size
|
||||
self.op_.vDiskInfo_.replicationFactor = vDiskInfo.replicationFactor
|
||||
self.op_.vDiskInfo_.blockSize = vDiskInfo.blockSize
|
||||
self.op_.vDiskInfo_.exportedBlockSize = vDiskInfo.exportedBlockSize
|
||||
self.op_.vDiskInfo_.isClone = vDiskInfo.isClone
|
||||
#self.op_.vDiskInfo_.generationNbr = vDiskInfo.generationNbr
|
||||
self.op_.vDiskInfo_.cloudEnabled = vDiskInfo.cloudEnabled
|
||||
self.op_.vDiskInfo_.dedupBuckets = str(vDiskInfo.dedupBuckets)
|
||||
self.op_.vDiskInfo_.masterVDiskName = str(vDiskInfo.masterVDiskName)
|
||||
self.op_.vDiskInfo_.dedup = vDiskInfo.dedup
|
||||
self.op_.vDiskInfo_.compressed = vDiskInfo.compressed
|
||||
self.op_.vDiskInfo_.immutable = vDiskInfo.immutable
|
||||
self.op_.vDiskInfo_.cacheEnable = vDiskInfo.cacheEnable
|
||||
self.op_.vDiskInfo_.scsisn = vDiskInfo.scsisn
|
||||
self.op_.vDiskInfo_.vTreeBuffer = str(vDiskInfo.vTreeBuffer)
|
||||
#self.op_.vDiskInfo_.versionCounter = vDiskInfo.versionCounter
|
||||
self.op_.vDiskInfo_.clusteredfilesystem = vDiskInfo.clusteredfilesystem
|
||||
self.op_.vDiskInfo_.description = str(vDiskInfo.description)
|
||||
self.op_.vDiskInfo_.mntLocation = str(vDiskInfo.mntLocation)
|
||||
self.op_.vDiskInfo_.residence = vDiskInfo.residence
|
||||
self.op_.vDiskInfo_.diskType = vDiskInfo.diskType
|
||||
self.op_.vDiskInfo_.cloudProvider = vDiskInfo.cloudProvider
|
||||
self.op_.vDiskInfo_.replicationPolicy = vDiskInfo.replicationPolicy
|
||||
#self.op_.vDiskInfo_.targetLocations = hc.set_string()
|
||||
#for location in vDiskInfo.targetLocations:
|
||||
# self.op_.vDiskInfo_.targetLocations.append(location)
|
||||
#self.op_.vDiskInfo_.cloneInfo = hc.CloneInfo()
|
||||
#self.op_.vDiskInfo_.cloneInfo.baseDisk = str(vDiskInfo.cloneInfo.baseDisk)
|
||||
#self.op_.vDiskInfo_.cloneInfo.snapshot = str(vDiskInfo.cloneInfo.snapshot)
|
||||
#self.op_.vDiskInfo_.cloneInfo.baseVersion = vDiskInfo.cloneInfo.baseVersion
|
||||
#self.op_.vDiskInfo_.cloneInfo.typeOfClone = vDiskInfo.cloneInfo.typeOfClone
|
||||
#self.op_.vDiskInfo_.replicationPolicyInfo = hc.ReplicationPolicyInfo()
|
||||
#self.op_.vDiskInfo_.replicationPolicyInfo.dataCenterNames = hc.buffer_vector()
|
||||
#for dataCenterName in vDiskInfo.replicationPolicyInfo.dataCenterNames:
|
||||
# self.op_.vDiskInfo_.replicationPolicyInfo.dataCenterNames.append(dataCenterName)
|
||||
|
||||
def addLun(self):
|
||||
self.pyCallback_.addLun(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.lunNumber_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HDeleteLunOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,tgtHost,tgtPort,vDiskName,lun):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HDeleteLunOp()
|
||||
self.op_.tgtHost_ = str(tgtHost)
|
||||
self.op_.tgtPort_ = tgtPort
|
||||
self.op_.vDiskName_ = str(vDiskName)
|
||||
self.op_.lunNumber_ = lun
|
||||
|
||||
def deleteLun(self):
|
||||
self.pyCallback_.deleteLun(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.result_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HAddAccessOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,tgtHost,tgtPort,lun,ip):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HAddAccessOp()
|
||||
self.op_.tgtHost_ = str(tgtHost)
|
||||
self.op_.tgtPort_ = tgtPort
|
||||
self.op_.lunNumber_ = lun
|
||||
self.op_.Ip_ = ip
|
||||
|
||||
def addAccess(self):
|
||||
self.pyCallback_.addAccess(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.result_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HSnapshotFromTgtOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,tgtHost,tgtPort,vDiskName):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HSnapshotFromTgtOp()
|
||||
self.op_.tgtHost_ = str(tgtHost)
|
||||
self.op_.tgtPort_ = tgtPort
|
||||
self.op_.vDiskName_ = vDiskName
|
||||
|
||||
def snapshotFromTgt(self):
|
||||
self.pyCallback_.snapshotFromTgt(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.snapshot_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HSnapshotOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,vDiskName):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HSnapshotOp()
|
||||
self.op_.vDiskName_ = str(vDiskName)
|
||||
|
||||
def snapshot(self):
|
||||
self.pyCallback_.snapshot(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.snapshotInfo_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HDeleteSnapshotOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self,snapshotName):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HDeleteSnapshotOp()
|
||||
self.op_.snapshotName_ = str(snapshotName)
|
||||
|
||||
def deleteSnapshot(self):
|
||||
self.pyCallback_.deleteSnapshot(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HCreateVirtualDiskOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self, vDiskInfo):
|
||||
HedvigOpCb.__init__(self)
|
||||
LOG.debug("Creating virtual disk: %s", vDiskInfo.vDiskName)
|
||||
self.op_ = hc.HCreateVirtualDiskOp()
|
||||
self.op_.vDiskInfo_ = hc.VDiskInfo()
|
||||
self.op_.vDiskInfo_.dedup = vDiskInfo.dedup
|
||||
self.op_.vDiskInfo_.vDiskName = str(vDiskInfo.vDiskName)
|
||||
self.op_.vDiskInfo_.createdBy = vDiskInfo.createdBy
|
||||
self.op_.vDiskInfo_.size = vDiskInfo.size
|
||||
self.op_.vDiskInfo_.replicationFactor = vDiskInfo.replicationFactor
|
||||
self.op_.vDiskInfo_.blockSize = vDiskInfo.blockSize
|
||||
self.op_.vDiskInfo_.exportedBlockSize = vDiskInfo.exportedBlockSize
|
||||
self.op_.vDiskInfo_.isClone = vDiskInfo.isClone
|
||||
self.op_.vDiskInfo_.cloudEnabled = vDiskInfo.cloudEnabled
|
||||
self.op_.vDiskInfo_.dedupBuckets = str(vDiskInfo.dedupBuckets)
|
||||
self.op_.vDiskInfo_.masterVDiskName = str(vDiskInfo.masterVDiskName)
|
||||
self.op_.vDiskInfo_.dedup = vDiskInfo.dedup
|
||||
self.op_.vDiskInfo_.compressed = vDiskInfo.compressed
|
||||
self.op_.vDiskInfo_.immutable = vDiskInfo.immutable
|
||||
self.op_.vDiskInfo_.cacheEnable = vDiskInfo.cacheEnable
|
||||
self.op_.vDiskInfo_.vTreeBuffer = str(vDiskInfo.vTreeBuffer)
|
||||
self.op_.vDiskInfo_.clusteredfilesystem = vDiskInfo.clusteredfilesystem
|
||||
self.op_.vDiskInfo_.description = str(vDiskInfo.description)
|
||||
self.op_.vDiskInfo_.mntLocation = str(vDiskInfo.mntLocation)
|
||||
self.op_.vDiskInfo_.residence = vDiskInfo.residence
|
||||
self.op_.vDiskInfo_.diskType = vDiskInfo.diskType
|
||||
self.op_.vDiskInfo_.cloudProvider = vDiskInfo.cloudProvider
|
||||
self.op_.vDiskInfo_.replicationPolicy = vDiskInfo.replicationPolicy
|
||||
|
||||
def createVirtualDisk(self):
|
||||
self.pyCallback_.createVirtualDisk(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HResizeVirtualDiskOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self, vDiskInfo):
|
||||
HedvigOpCb.__init__(self)
|
||||
LOG.debug("Resizing virtual disk: %s", vDiskInfo.vDiskName)
|
||||
self.op_ = hc.HResizeVirtualDiskOp()
|
||||
self.op_.vDiskInfo_ = hc.VDiskInfo()
|
||||
self.op_.vDiskInfo_.dedup = vDiskInfo.dedup
|
||||
self.op_.vDiskInfo_.vDiskName = str(vDiskInfo.vDiskName)
|
||||
self.op_.vDiskInfo_.createdBy = vDiskInfo.createdBy
|
||||
self.op_.vDiskInfo_.size = vDiskInfo.size
|
||||
self.op_.vDiskInfo_.replicationFactor = vDiskInfo.replicationFactor
|
||||
self.op_.vDiskInfo_.blockSize = vDiskInfo.blockSize
|
||||
self.op_.vDiskInfo_.exportedBlockSize = vDiskInfo.exportedBlockSize
|
||||
self.op_.vDiskInfo_.isClone = vDiskInfo.isClone
|
||||
self.op_.vDiskInfo_.cloudEnabled = vDiskInfo.cloudEnabled
|
||||
self.op_.vDiskInfo_.dedupBuckets = str(vDiskInfo.dedupBuckets)
|
||||
self.op_.vDiskInfo_.masterVDiskName = str(vDiskInfo.masterVDiskName)
|
||||
self.op_.vDiskInfo_.dedup = vDiskInfo.dedup
|
||||
self.op_.vDiskInfo_.compressed = vDiskInfo.compressed
|
||||
self.op_.vDiskInfo_.immutable = vDiskInfo.immutable
|
||||
self.op_.vDiskInfo_.cacheEnable = vDiskInfo.cacheEnable
|
||||
self.op_.vDiskInfo_.vTreeBuffer = str(vDiskInfo.vTreeBuffer)
|
||||
self.op_.vDiskInfo_.clusteredfilesystem = vDiskInfo.clusteredfilesystem
|
||||
self.op_.vDiskInfo_.description = str(vDiskInfo.description)
|
||||
self.op_.vDiskInfo_.mntLocation = str(vDiskInfo.mntLocation)
|
||||
self.op_.vDiskInfo_.residence = vDiskInfo.residence
|
||||
self.op_.vDiskInfo_.diskType = vDiskInfo.diskType
|
||||
self.op_.vDiskInfo_.cloudProvider = vDiskInfo.cloudProvider
|
||||
self.op_.vDiskInfo_.replicationPolicy = vDiskInfo.replicationPolicy
|
||||
|
||||
def resizeVirtualDisk(self):
|
||||
self.pyCallback_.resizeVirtualDisk(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HDeleteVirtualDiskOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self, vDiskName):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HDeleteVirtualDiskOp()
|
||||
self.op_.vDiskName_ = str(vDiskName)
|
||||
|
||||
def deleteVirtualDisk(self):
|
||||
self.pyCallback_.deleteVirtualDisk(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
class HGetIqnOpCb(HedvigOpCb):
|
||||
|
||||
def __init__(self, hostname):
|
||||
HedvigOpCb.__init__(self)
|
||||
self.op_ = hc.HGetIqnOp()
|
||||
self.op_.hostname_ = str(hostname)
|
||||
|
||||
def getIqn(self):
|
||||
self.pyCallback_.getIqn(self.op_)
|
||||
self.waitForResult(self.__class__.__name__)
|
||||
return self.op_.iqn_
|
||||
|
||||
def __del__(self):
|
||||
HedvigOpCb.__del__(self)
|
||||
|
||||
from Helper import Helper
|
|
@ -0,0 +1,19 @@
|
|||
from email.Utils import formatdate
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime
|
||||
import rfc822
|
||||
from dateutil import parser
|
||||
from dateutil import tz
|
||||
import time
|
||||
import datetime
|
||||
from eventlet import getcurrent
|
||||
|
||||
class Helper(object):
|
||||
def __init__(self, params):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def getId():
|
||||
return id(getcurrent())
|
||||
|
||||
from HedvigOpCb import *
|
|
@ -0,0 +1,584 @@
|
|||
#!/usr/bin/python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
# Copyright (c) 2012 Hedvig, Inc.
|
||||
# Copyright (c) 2012 OpenStack LLC.
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Volume driver for Hedvig Block Storage.
|
||||
"""
|
||||
|
||||
import netifaces
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
from cinder import exception
|
||||
from cinder import context
|
||||
from cinder import utils
|
||||
from cinder.db.sqlalchemy import api
|
||||
from cinder.i18n import _, _LE, _LI, _LW
|
||||
from cinder.volume import driver
|
||||
from cinder.volume import volume_types
|
||||
|
||||
from oslo.config import cfg
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_log import log as logging
|
||||
|
||||
from urlparse import urlparse
|
||||
from cinder.volume.drivers.hedvig.HedvigConfig import HedvigConfig
|
||||
from cinder.volume.drivers.hedvig.HedvigOpCb import *
|
||||
import hedvigpyc as hc
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
hedvig_opts = [
|
||||
cfg.StrOpt('hedvig_metadata_server',
|
||||
help='The hostname (or IP address) of a hedvig metadata node in the cluster'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(hedvig_opts)
|
||||
|
||||
class HedvigISCSIDriver(driver.ISCSIDriver):
|
||||
"""Hedvig iSCSI volume driver."""
|
||||
defaultVolumeSizeInGB_ = 1
|
||||
defaultVolumeBlkSize_ = 4096
|
||||
toGB_ = 1024 * 1024 * 1024
|
||||
defaultCreatedBy_ = "OpenStack Cinder"
|
||||
defaultExportedBlkSize_ = 512
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HedvigISCSIDriver, self).__init__(*args, **kwargs)
|
||||
self.group_stats = {}
|
||||
self.configuration.append_config_values(hedvig_opts)
|
||||
|
||||
def check_for_setup_error(self):
|
||||
pass
|
||||
|
||||
def do_setup(self, context):
|
||||
self.context_ = context
|
||||
LOG.debug('Context: %s', context)
|
||||
self.hedvig_metadata_server = getattr(self.configuration, 'hedvig_metadata_server')
|
||||
LOG.info(_LI('Initializing hedvig cinder driver with server - %s'), self.hedvig_metadata_server)
|
||||
HedvigOpCb.hedvigpycInit(self.hedvig_metadata_server, 8)
|
||||
|
||||
def get_volume_stats(self, refresh=False):
|
||||
# we need to get get stats for server.
|
||||
total_capacity = float(1024)
|
||||
used_capacity = float(0)
|
||||
free_capacity = total_capacity - used_capacity
|
||||
self.group_stats = {"volume_backend_name": "hedvig",
|
||||
"vendor_name" : "Hedvig Inc",
|
||||
"driver_version" : "0.99",
|
||||
"storage_protocol" : "ISCSI",
|
||||
"total_capacity_gb": total_capacity,
|
||||
"free_capacity_gb": free_capacity,
|
||||
"reserverd_percentage": 0,
|
||||
"QoS_support": False}
|
||||
return self.group_stats
|
||||
|
||||
def hedvigGetVolumeDetails(self, volume):
|
||||
volName = volume['name']
|
||||
project = volume['project_id']
|
||||
displayName = volume['display_name']
|
||||
displayDescription = volume['display_description']
|
||||
if project == None:
|
||||
project = ""
|
||||
if displayName == None:
|
||||
displayName = ""
|
||||
if displayDescription == None:
|
||||
displayDescription = ""
|
||||
description = project + "\n" + displayName + "\n" + displayDescription
|
||||
size = long(volume['size'])
|
||||
if size == 0:
|
||||
size = HedvigISCSIDriver.defaultVolumeSizeInGB_
|
||||
size = size * HedvigISCSIDriver.toGB_
|
||||
return volName, description, size
|
||||
|
||||
def create_volume(self, volume):
|
||||
"""
|
||||
Driver entry point for creating a new volume.
|
||||
"""
|
||||
LOG.debug("Creating new volume: %s", volume)
|
||||
name, description, size = self.hedvigGetVolumeDetails(volume)
|
||||
volumeTypeId = volume["volume_type_id"]
|
||||
volumeType = None
|
||||
try:
|
||||
LOG.debug("Retrieving volume type details for id: %s", volumeTypeId)
|
||||
volumeType = api.volume_type_get(self.context_, volumeTypeId)
|
||||
LOG.debug("Volume type is: %s", volumeType)
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to retrieve volume type details for id: %s'), volumeTypeId)
|
||||
raise exception.HedvigDriverException()
|
||||
try:
|
||||
LOG.debug("Volume name: %s, description: %s, size: %s", name, description, size)
|
||||
self.hedvigCreateVirtualDisk(name, description, size, volumeType)
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to create volume. name: %s, description: %s, size: %s'), name, description, size)
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def delete_volume(self, volume):
|
||||
"""
|
||||
Driver entry point for deleting volume.
|
||||
"""
|
||||
LOG.debug("Deleting volume: %s", volume)
|
||||
name = volume['name']
|
||||
try:
|
||||
self.hedvigDeleteVirtualDisk(name)
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to delete volume. volume: %s'), volume)
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def get_export(self, volume):
|
||||
"""
|
||||
Get the iSCSI export details for a volume.
|
||||
"""
|
||||
LOG.debug("volume: %s", volume)
|
||||
pass
|
||||
|
||||
def ensure_export(self, context, volume):
|
||||
"""
|
||||
Driver entry point to get the export info for an existing volume.
|
||||
Irrelevant for Hedvig. Export is created during attachment to instance.
|
||||
"""
|
||||
LOG.debug("context: %s, volume: %s", context, volume)
|
||||
pass
|
||||
|
||||
def create_export(self, context, volume):
|
||||
"""
|
||||
Driver entry point to get the export info for a new volume.
|
||||
Irrelevant for Hedvig. Export is created during attachment to instance.
|
||||
"""
|
||||
LOG.debug("context: %s, volume: %s", context, volume)
|
||||
pass
|
||||
|
||||
def remove_export(self, context, volume):
|
||||
"""
|
||||
Driver entry point to remove an export for a volume.
|
||||
Irrelevant for Hedvig. Export should be deleted on detachment.
|
||||
"""
|
||||
LOG.debug("context: %s, volume: %s", context, volume)
|
||||
pass
|
||||
|
||||
def initialize_connection(self, volume, connector):
|
||||
"""
|
||||
Driver entry point to attach a volume to an instance.
|
||||
|
||||
Assign any created volume to a compute node/controllerVM so that it can be
|
||||
attached to a instance.
|
||||
This driver returns a driver_volume_type of 'iscsi'.
|
||||
The format of the driver data is defined as follows -- similar to _get_iscsi_properties.
|
||||
Example return value:
|
||||
|
||||
{
|
||||
'driver_volume_type': 'iscsi'
|
||||
'data': {
|
||||
'target_discovered': True,
|
||||
'target_iqn': 'iqn.2010-10.com.hedvig:target',
|
||||
'target_portal': '192.168.108.143:3260',
|
||||
'target_lun': '1',
|
||||
'volume_id': 2,
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
LOG.info(_LI('Initializing connection. volume: %(volume)s, connector: %(connector)s'), {'volume': volume, 'connector': connector})
|
||||
try:
|
||||
computeHost = socket.getfqdn(connector['host'])
|
||||
volName = volume['name']
|
||||
tgtHost = self.hedvigLookupTgt(computeHost)
|
||||
lunnum = self.hedvigGetLun(tgtHost, volName)
|
||||
if lunnum == -1:
|
||||
LOG.error(_LE('Failed to get lun for volume: %(volume)s, hedvig controller: %(tgtHost)s'), {'volume': volume, 'tgtHost': tgtHost})
|
||||
raise Exception("Failed to add lun")
|
||||
|
||||
# Addaccess to the mgmt interface addr and iqn of the compute host
|
||||
compute_host_iqn = self.hedvigGetIqn(computeHost)
|
||||
self.hedvigAddAccess(tgtHost, lunnum, compute_host_iqn)
|
||||
compute_mgmt_addr = socket.gethostbyname(socket.getfqdn(computeHost))
|
||||
self.hedvigAddAccess(tgtHost, lunnum, socket.gethostbyname(socket.getfqdn(computeHost)))
|
||||
|
||||
# Addaccess to both storage and mgmt interface addrs for
|
||||
# iscsi discovery to succeed
|
||||
interfaces = netifaces.interfaces()
|
||||
storage_addr = None
|
||||
mgmt_addr = None
|
||||
if 'br-storage' in interfaces and netifaces.AF_INET in netifaces.ifaddresses('br-storage'):
|
||||
storage_interface = netifaces.ifaddresses('br-storage')[netifaces.AF_INET]
|
||||
if storage_interface and 'addr' in storage_interface[0]:
|
||||
storage_addr = storage_interface[0]['addr']
|
||||
if 'br-mgmt' in interfaces and netifaces.AF_INET in netifaces.ifaddresses('br-mgmt'):
|
||||
mgmt_interface = netifaces.ifaddresses('br-mgmt')[netifaces.AF_INET]
|
||||
if mgmt_interface and 'addr' in mgmt_interface[0]:
|
||||
mgmt_addr = mgmt_interface[0]['addr']
|
||||
if mgmt_addr and (compute_mgmt_addr != mgmt_addr):
|
||||
self.hedvigAddAccess(tgtHost, lunnum, mgmt_addr)
|
||||
if storage_addr and mgmt_addr and (storage_addr != mgmt_addr):
|
||||
self.hedvigAddAccess(tgtHost, lunnum, storage_addr)
|
||||
|
||||
targetName, portal = self.hedvigDoIscsiDiscovery(tgtHost, lunnum)
|
||||
iscsi_properties = ({'target_discovered': True,
|
||||
'target_iqn': targetName,
|
||||
'target_portal': portal,
|
||||
'target_lun': lunnum })
|
||||
LOG.debug("volName: %s, connector: %s, iscsi_properties: %s", volName, connector, iscsi_properties)
|
||||
return {'driver_volume_type': 'iscsi', 'data': iscsi_properties}
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Volume assignment to connect failed. volume: %(volume)s, connector: %(connector)s'), {'volume': volume, 'connector': connector})
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def terminate_connection(self, volume, connector, **kwargs):
|
||||
"""
|
||||
Driver entry point to detach volume from instance.
|
||||
"""
|
||||
LOG.debug("Terminating connection. volume: %s, connector: %s", volume, connector)
|
||||
try:
|
||||
computeHost = socket.getfqdn(connector['host']) #connector['host']
|
||||
volName = volume['name']
|
||||
tgtHost = self.hedvigLookupTgt(computeHost)
|
||||
if tgtHost == '':
|
||||
LOG.error(_LE('Failed to get hedvig controller for compute host: %s'), computeHost)
|
||||
raise Exception("Failed to get hedvig controller for compute host: %s" % (computeHost))
|
||||
lunnum = self.hedvigGetLun(tgtHost, volName)
|
||||
if lunnum == -1:
|
||||
LOG.error(_LE('Failed to get lun for volume: %s'), volume)
|
||||
raise Exception("Failed to get lun for volume: %s" % (volume))
|
||||
self.hedvigDeleteLun(tgtHost, volName, lunnum)
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to terminate connection. volume: %(volume)s, connector: %(connector)s'), {'volume': volume, 'connector': connector})
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def hedvigLookupTgt(self, host):
|
||||
"""
|
||||
Get the tgt instance associated with the compute host.
|
||||
"""
|
||||
try:
|
||||
LOG.debug("Looking up hedvig controller for compute host: %s", host)
|
||||
hedvigGetTgtInstanceOp = HGetTgtInstanceOpCb(host)
|
||||
tgtMap = hedvigGetTgtInstanceOp.getTgtInstance()
|
||||
tgt = None
|
||||
if "block" in tgtMap:
|
||||
tgtList = tgtMap["block"]
|
||||
if len(tgtList) > 0:
|
||||
tgt = tgtList[0]
|
||||
if not tgt:
|
||||
raise exception.NotFound(name=host)
|
||||
LOG.debug("Found hedvig controller: %s, for host: %s", tgt, host)
|
||||
return tgt
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to get hedvig controller for compute host: %s'), host)
|
||||
raise e
|
||||
|
||||
def hedvigDoIscsiLogout(self, targetName, portal, toThrow=False):
|
||||
try:
|
||||
(retOut, retErr) = utils.execute("iscsiadm", "--mode", "node", "--targetname", targetName, "--portal", portal, "--logout", run_as_root=True)
|
||||
if retErr != None and len(retErr) > 0:
|
||||
LOG.error(_LE('Failed iscsi logout. targetName: %(targetName)s, portal: %(portal)s'), {'targetName': targetName, 'portal': portal})
|
||||
except processutils.ProcessExecutionError as e:
|
||||
LOG.error(_LE('Error occurred during iscsi logout. targetName: %(targetName)s, portal: %(portal)s, stdout: %(stdout)s, stderr: %(stderr)s, exit_code: %(exit_code)s'), {'targetName': targetName, 'portal': portal, 'stdout': e.stdout, 'stderr': e.stderr, 'exit_code': e.exit_code})
|
||||
if toThrow:
|
||||
raise e
|
||||
|
||||
def hedvigDoIscsiDiscovery(self, tgtHost, lunNum):
|
||||
LOG.debug("Do iscsi discovery, hedvig controller: %s, lun: %s", tgtHost, lunNum)
|
||||
try:
|
||||
(retOut , retErr) = utils.execute("iscsiadm", "-m" , "discovery", "-t", "sendtargets", "-p", tgtHost, run_as_root=True)
|
||||
LOG.debug("Done iscsi discovery, hedvig controller: %s, lun: %s, output: %s, error: %s", tgtHost, lunNum, retOut, retErr)
|
||||
if retErr != None and len(retErr) > 0:
|
||||
# logout not in use targets
|
||||
for line in retErr.rstrip(" ").split("\n"):
|
||||
if "target:" not in line:
|
||||
continue
|
||||
line = line[line.find("target:") + len("target:") :]
|
||||
line = line[:line.find("],")]
|
||||
targetName, portal = line.split("portal:")
|
||||
targetName = targetName.strip(" ").strip(",")
|
||||
portal = portal.strip(" ").strip(",")
|
||||
self.hedvigDoIscsiLogout(targetName, portal)
|
||||
targetName = None
|
||||
portal = None
|
||||
if retOut != None and len(retOut) > 0:
|
||||
expectedTarget = tgtHost + "-" + str(lunNum)
|
||||
for line in retOut.strip(" ").split("\n"):
|
||||
if expectedTarget in line:
|
||||
portal, targetName = line.strip(" ").split(" ")
|
||||
portal = portal.strip(" ").split(",")[0]
|
||||
targetName = targetName.strip(" ")
|
||||
break
|
||||
except processutils.ProcessExecutionError as e:
|
||||
LOG.error(_LE('Error occurred during iscsi discovery. stdout: %(stdout)s, stderr: %(stderr)s, exit_code: %(exit_code)s'), {'stdout': e.stdout, 'stderr': e.stderr, 'exit_code': e.exit_code})
|
||||
raise e
|
||||
if targetName == None or portal == None:
|
||||
raise Exception("Failed iscsi discovery. hedvig controller: %s, lun: %s" % (tgtHost, lunNum))
|
||||
return targetName, portal
|
||||
|
||||
def hedvigDeleteLun(self, tgtHost, vDiskName, lunnum):
|
||||
LOG.debug("Deleting lun. hedvig controller: %s, vDiskName: %s, lun: %s", tgtHost, vDiskName, lunnum)
|
||||
tgtPort = HedvigConfig.getInstance().getHedvigControllerPort()
|
||||
hedvigDeleteLunOp = HDeleteLunOpCb(tgtHost, tgtPort, vDiskName, lunnum)
|
||||
result = hedvigDeleteLunOp.deleteLun()
|
||||
return result
|
||||
|
||||
def hedvigGetLun(self, tgtHost, vDiskName):
|
||||
"""
|
||||
Looks up lun based on tgthost and vDiskName.
|
||||
If lun does not exist then call addLun and return the lun number.
|
||||
If lun exists, just return the lun number.
|
||||
"""
|
||||
LOG.debug("Getting lun. hedvig controller: %s, vDiskName: %s", tgtHost, vDiskName)
|
||||
tgtPort = HedvigConfig.getInstance().getHedvigControllerPort()
|
||||
hedvigGetLunOp = HGetLunCinderOpCb(tgtHost, tgtPort, vDiskName)
|
||||
lunNo = hedvigGetLunOp.getLunCinder()
|
||||
if lunNo > -1:
|
||||
LOG.debug("Found lun: %s", str(lunNo))
|
||||
return lunNo
|
||||
|
||||
# If the lun is not found, add lun for the vdisk
|
||||
hedvigDescribeVirtualDiskOp = HDescribeVirtualDiskOpCb(vDiskName)
|
||||
vDiskInfo = hedvigDescribeVirtualDiskOp.describeVirtualDisk()
|
||||
tgtPort = HedvigConfig.getInstance().getHedvigControllerPort()
|
||||
hedvigAddLunOp = HAddLunOpCb(tgtHost, tgtPort, vDiskInfo)
|
||||
lunNo = hedvigAddLunOp.addLun()
|
||||
LOG.debug("Found lun: %s", str(lunNo))
|
||||
return lunNo
|
||||
|
||||
def hedvigGetIqn(self, hostname):
|
||||
"""
|
||||
Looks up the iqn for the given host.
|
||||
"""
|
||||
LOG.debug("Getting IQN for hostname: %s", hostname)
|
||||
hedvigGetIqnOp = HGetIqnOpCb(hostname)
|
||||
iqn = hedvigGetIqnOp.getIqn()
|
||||
LOG.debug("Got IQN: %s, for hostname: %s", iqn, hostname)
|
||||
return iqn
|
||||
|
||||
def hedvigAddAccess(self, tgtHost, lun, initiator):
|
||||
"""
|
||||
Adds access to LUN for initiator's ip/iqn
|
||||
"""
|
||||
LOG.debug("Adding access. hedvig controller: %s, lun: %s, initiator: %s", tgtHost, lun, initiator)
|
||||
try:
|
||||
tgtPort = HedvigConfig.getInstance().getHedvigControllerPort()
|
||||
hedvigAddAccessOp = HAddAccessOpCb(tgtHost, tgtPort, lun, initiator)
|
||||
result = hedvigAddAccessOp.addAccess()
|
||||
return result
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to add access. hedvig controller: %(controller)s, lun: %(lun)s, initiator: %(initiator)s'), {'controller': tgtHost, 'lun': lun, 'initiator': initiator})
|
||||
raise e
|
||||
|
||||
def create_snapshot(self, snapshot):
|
||||
"""
|
||||
Driver entry point for creating a snapshot.
|
||||
"""
|
||||
try:
|
||||
ctxt = context.get_admin_context()
|
||||
volName = snapshot['volume_name']
|
||||
snapshotName = snapshot['name']
|
||||
project = snapshot['project_id']
|
||||
snapshotId = snapshot['id']
|
||||
LOG.debug("Creating snapshot. volName: %s, snapshotName: %s, project: %s, snapshotId: %s", volName, snapshotName, project, snapshotId)
|
||||
hedvigSnapshotName = self.hedvigCreateSnapshot(volName)
|
||||
# Set the snapshot name to ret value.
|
||||
LOG.debug("Updating snapshot name. snapshotId: %s, snapshotName: %s, newName: %s", snapshotId, snapshotName, hedvigSnapshotName)
|
||||
self.db.snapshot_update(ctxt, snapshotId, {'display_name': str(hedvigSnapshotName)})
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to create snapshot. volName: %(volName)s, snapshotName: %(snapshotName)s, project: %(project)s, snapshotId: %(snapshotId)s'), {'volName': volName, 'snapshotName': snapshotName, 'project': project, 'snapshotId': snapshotId})
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def detach_volume(self, context, volume, attachment):
|
||||
LOG.info(_LI('Detaching volume. context: %(context)s, volume: %(volume)s, attachment: %(attachment)s'), {'context': context, 'volume': volume, 'attachment': attachment})
|
||||
return
|
||||
|
||||
def hedvigCreateSnapshot(self, vDiskName):
|
||||
"""
|
||||
Hedvig call to create snapshot of vdisk.
|
||||
"""
|
||||
hedvigDescribeVirtualDiskOp = HDescribeVirtualDiskOpCb(vDiskName)
|
||||
vDiskInfo = hedvigDescribeVirtualDiskOp.describeVirtualDisk()
|
||||
snapshotName = None
|
||||
LOG.debug("Creating snapshot. mount location: %s", vDiskInfo.mntLocation)
|
||||
if vDiskInfo.mntLocation == "":
|
||||
LOG.debug("vDisk: %s is not mounted", vDiskName)
|
||||
hedvigSnapshotOp = HSnapshotOpCb(vDiskName)
|
||||
snapInfo = hedvigSnapshotOp.snapshot()
|
||||
snapshotName = snapInfo.snapshot
|
||||
else:
|
||||
tgtPort = HedvigConfig.getInstance().getHedvigControllerPort()
|
||||
hedvigSnapshotFromTgtOp = HSnapshotFromTgtOpCb(tgtHost, tgtPort, vDiskName)
|
||||
tgtHost = vDiskInfo.mntLocation.split(":")[0]
|
||||
LOG.debug("vDisk: %s is mounted on tgtHost: %s", vDiskName, tgtHost)
|
||||
snapshotName = hedvigSnapshotFromTgtOp.snapshotFromtgt()
|
||||
return snapshotName
|
||||
|
||||
def delete_snapshot(self, snapshot):
|
||||
"""
|
||||
Driver entry point for deleting a snapshot.
|
||||
"""
|
||||
volName = snapshot['volume_name']
|
||||
snapshotName = snapshot['display_name']
|
||||
project = snapshot['project_id']
|
||||
LOG.debug("Deleting snapshot. volName: %s, snapshotName: %s, project: %s", volName, snapshotName, project)
|
||||
try:
|
||||
hedvigDeleteSnapshotOp = HDeleteSnapshotOpCb(snapshotName)
|
||||
hedvigDeleteSnapshotOp.deleteSnapshot()
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to delete snapshot. volName: %(volName)s, snapshotName: %(snapshotName)s, project: %(project)s'), {'volName': volName, 'snapshotName': snapshotName, 'project': project})
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def create_volume_from_snapshot(self, volume, snapshot):
|
||||
"""
|
||||
Driver entry point for creating a new volume from a snapshot.
|
||||
This is the same as cloning.
|
||||
"""
|
||||
name, description, size = self.hedvigGetVolumeDetails(volume)
|
||||
snapshotname = snapshot['display_name']
|
||||
try:
|
||||
LOG.debug("Creating volume from snapshot. snapshotName: %s, name: %s, description: %s, size: %s", snapshotname, name, description, size)
|
||||
self.hedvigCloneSnapshot(snapshotname, name, description, size)
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Failed to create volume from snapshot. snapshotName: %(snapshotName)s, name: %(name)s, description: %(description)s, size: %(size)s'), {'snapshotName': snapshotName, 'name': name, 'description': description, 'size': size})
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def check_for_export(self, context, volume_id):
|
||||
"""
|
||||
Not relevant to Hedvig
|
||||
"""
|
||||
pass
|
||||
|
||||
def extend_volume(self, volume, newSize):
|
||||
"""
|
||||
Resizes virtual disk.
|
||||
newSize should be greater than current size.
|
||||
"""
|
||||
name, description, size = self.hedvigGetVolumeDetails(volume)
|
||||
newSize = int(newSize) * HedvigISCSIDriver.toGB_
|
||||
LOG.info(_LI('Resizing virtual disk. name: %(name)s, newSize: %(newSize)s'), {'name': name, 'newSize': newSize})
|
||||
try:
|
||||
hedvigDescribeVirtualDiskOp = HDescribeVirtualDiskOpCb(name)
|
||||
vDiskInfo = hedvigDescribeVirtualDiskOp.describeVirtualDisk()
|
||||
if vDiskInfo.size > newSize:
|
||||
LOG.error(_LE('Cannot reduce virtual disk size. currentSize: %(currentSize)s, newSize: %(newSize)s'), {'currentSize': vDiskInfo.size, 'newSize': newSize})
|
||||
raise Exception("Cannot reduce virtual disk size. currentSize: %s, newSize: %s" % (vDiskInfo.size, newSize))
|
||||
size = vDiskInfo.size
|
||||
vDiskInfo.size = newSize
|
||||
hedvigResizeVirtualDiskOp = HResizeVirtualDiskOpCb(vDiskInfo)
|
||||
hedvigResizeVirtualDiskOp.resizeVirtualDisk()
|
||||
except Exception as e:
|
||||
LOG.error(_LE('Cannot reduce virtual disk size. currentSize: %(currentSize)s, newSize: %(newSize)s'), {'currentSize': size, 'newSize': newSize})
|
||||
raise exception.HedvigDriverException()
|
||||
|
||||
def hedvigCreateVirtualDisk(self, name, description, size, volumeType):
|
||||
LOG.info(_LI('Creating virtual disk. name: %(name)s, description: %(description)s, size: %(size)s'), {'name': name, 'description': description, 'size': size})
|
||||
vDiskInfo = hc.VDiskInfo()
|
||||
vDiskInfo.vDiskName = str(name)
|
||||
vDiskInfo.blockSize = HedvigISCSIDriver.defaultVolumeBlkSize_
|
||||
vDiskInfo.size = size
|
||||
vDiskInfo.createdBy = str(HedvigISCSIDriver.defaultCreatedBy_)
|
||||
vDiskInfo.description = str(description)
|
||||
vDiskInfo.residence = HedvigConfig.getInstance().getCinderDiskResidence()
|
||||
vDiskInfo.replicationFactor = HedvigConfig.getInstance().getCinderReplicationFactor()
|
||||
vDiskInfo.replicationPolicy = HedvigConfig.getInstance().getCinderReplicationPolicy()
|
||||
vDiskInfo.clusteredfilesystem = False
|
||||
vDiskInfo.exportedBlockSize = HedvigISCSIDriver.defaultExportedBlkSize_
|
||||
vDiskInfo.cacheEnable = HedvigConfig.getInstance().isCinderCacheEnabled()
|
||||
vDiskInfo.diskType = hc.DiskType.BLOCK
|
||||
vDiskInfo.immutable = False
|
||||
vDiskInfo.dedup = HedvigConfig.getInstance().isCinderDedupEnabled()
|
||||
vDiskInfo.compressed = HedvigConfig.getInstance().isCinderCompressEnabled()
|
||||
vDiskInfo.cloudEnabled = False
|
||||
vDiskInfo.cloudProvider = 0
|
||||
vDiskInfo.isClone = False
|
||||
vDiskInfo.consistency = hc.Consistency.STRONG
|
||||
if "extra_specs" in volumeType:
|
||||
key = volumeType["extra_specs"]
|
||||
if "qos:dedup_enable" in key:
|
||||
entry = key["qos:dedup_enable"]
|
||||
val = HedvigConfig.parseAndGetBooleanEntry(entry)
|
||||
if val != None:
|
||||
vDiskInfo.dedup = val
|
||||
if "qos:compress_enable" in key:
|
||||
entry = key["qos:compress_enable"]
|
||||
val = HedvigConfig.parseAndGetBooleanEntry(entry)
|
||||
if val != None:
|
||||
vDiskInfo.compressed = val
|
||||
if "qos:cache_enable" in key:
|
||||
entry = key["qos:cache_enable"]
|
||||
val = HedvigConfig.parseAndGetBooleanEntry(entry)
|
||||
if val != None:
|
||||
vDiskInfo.cacheEnable = val
|
||||
if "qos:replication_factor" in key:
|
||||
val = key["qos:replication_factor"]
|
||||
val = int(val)
|
||||
if val > 0:
|
||||
vDiskInfo.replicationFactor = val
|
||||
if "qos:replication_policy" in key:
|
||||
entry = key["qos:replication_policy"]
|
||||
val = HedvigConfig.parseAndGetReplicationPolicy(entry)
|
||||
if val != None:
|
||||
vDiskInfo.replicationPolicy = val
|
||||
if "qos:disk_residence" in key:
|
||||
entry = key["qos:disk_residence"]
|
||||
val = HedvigConfig.parseAndGetDiskResidence(entry)
|
||||
if val != None:
|
||||
vDiskInfo.residence = val
|
||||
hedvigCreateVirtualDiskOp = HCreateVirtualDiskOpCb(vDiskInfo)
|
||||
hedvigCreateVirtualDiskOp.createVirtualDisk()
|
||||
|
||||
def hedvigDeleteVirtualDisk(self, name):
|
||||
LOG.info(_LI('Deleting virtual disk. name - %s'), name)
|
||||
hedvigDeleteVirtualDiskOp = HDeleteVirtualDiskOpCb(name)
|
||||
hedvigDeleteVirtualDiskOp.deleteVirtualDisk()
|
||||
|
||||
def hedvigCloneSnapshot(self, snapshotname, name, description, size):
|
||||
LOG.debug("Cloning a snapshot. snapshotName: %s, name: %s, description: %s, size: %s", snapshotname, name, description, size)
|
||||
LOG.info(_LI('Cloning a snapshot. snapshotName: %(snapshotName)s, name: %(name)s, description: %(description)s, size: %(size)s'), {'snapshotName': snapshotName, 'name': name, 'description': description, 'size': size})
|
||||
vDiskInfo = hc.VDiskInfo()
|
||||
cloneInfo = hc.CloneInfo()
|
||||
baseDisk = snapshotname.split("$")[0]
|
||||
baseVersion = snapshotname.split("$")[2]
|
||||
hedvigDescribeVirtualDiskOp = HDescribeVirtualDiskOpCb(vDiskName)
|
||||
parentVDiskInfo = hedvigDescribeVirtualDiskOp.describeVirtualDisk()
|
||||
vDiskInfo.vDiskName = name
|
||||
cloneInfo.typeOfClone = TypeOfClone.Shallow
|
||||
vDiskInfo.clusteredfilesystem = parentVDiskInfo.clusteredfilesystem
|
||||
vDiskInfo.blockSize = parentVDiskInfo.blockSize
|
||||
vDiskInfo.exportedBlockSize = parentVDiskInfo.exportedBlockSize
|
||||
if parentVDiskInfo.size > size:
|
||||
LOG.error(_LE('Failed to clone snapshot. Size of the clone: %(cloneSize)s is less than the parent virtual disk size: %(parentSize)s'), {'cloneSize': size, 'parentSize': parentVDiskInfo.size})
|
||||
raise Exception("Specified size: %s is less than parent virtual disk size: %s" % (size, parentVDiskInfo.size))
|
||||
vDiskInfo.size = size
|
||||
vDiskInfo.createdBy = parentVDiskInfo.createdBy
|
||||
vDiskInfo.description = description
|
||||
vDiskInfo.residence = parentVDiskInfo.residence
|
||||
vDiskInfo.replicationFactor = parentVDiskInfo.replicationFactor
|
||||
vDiskInfo.replicationPolicy = parentVDiskInfo.replicationPolicy
|
||||
cloneInfo.snapshot = snapshotname
|
||||
cloneInfo.baseVersion = int(baseVersion)
|
||||
cloneInfo.baseDisk = baseDisk
|
||||
vDiskInfo.cloneInfo = cloneInfo
|
||||
vDiskInfo.isClone = True
|
||||
vDiskInfo.scsisn = 0
|
||||
vDiskInfo.cacheEnable = parentVDiskInfo.cacheEnable
|
||||
vDiskInfo.diskType = parentVDiskInfo.diskType
|
||||
vDiskInfo.cloudProvider = parentVDiskInfo.cloudProvider
|
||||
vDiskInfo.cloudEnabled = parentVDiskInfo.cloudEnabled
|
||||
vDiskInfo.dedup = parentVDiskInfo.dedup
|
||||
vDiskInfo.consistency = Consistency.STRONG
|
||||
hedvigCreateVirtualDiskOp = HCreateVirtualDiskOpCb(vDiskInfo)
|
||||
hedvigCreateVirtualDiskOp.createVirtualDisk()
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
class plugin_hedvig_cinder
|
||||
{
|
||||
if($::operatingsystem == 'Ubuntu') {
|
||||
include plugin_hedvig_cinder::ubuntu
|
||||
}else {
|
||||
include plugin_hedvig_cinder::centos
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
class plugin_hedvig_cinder::ubuntu
|
||||
{
|
||||
file { "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/hedvig/":
|
||||
ensure => directory,
|
||||
}
|
||||
|
||||
file { "/usr/lib/python2.7/dist-packages/_hedvigpyc.so":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/pythonlibs/_hedvigpyc.so',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/local/lib/libhedvig.so":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/libs/libhedvig.so',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/local/lib/libcrcutil.so":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/libs/libcrcutil.so',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/local/lib/libthrift-0.9.0.so":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/libs/libthrift-0.9.0.so',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/local/lib/libthriftnb-0.9.0.so":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/libs/libthriftnb-0.9.0.so',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/local/lib/libunwind.so.8":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/libs/libunwind.so.8',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/hedvig/hedvig-cinder.py":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/python/hedvig-cinder.py',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/hedvig/hedvigpyc.py":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/python/hedvigpyc.py',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/hedvig/__init__.py":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/python/__init__.py',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/hedvig/HedvigConfig.py":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/python/HedvigConfig.py',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/hedvig/Helper.py":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/python/Helper.py',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
file { "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/hedvig/HedvigOpCb.py":
|
||||
source => 'puppet:///modules/plugin_hedvig_cinder/python/HedvigOpCb.py',
|
||||
mode => '644',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
}
|
||||
|
||||
package {'libboost-all-dev':
|
||||
ensure => installed ,
|
||||
}->
|
||||
|
||||
package {'libsnappy-dev':
|
||||
ensure => installed ,
|
||||
}->
|
||||
|
||||
package {'libgoogle-glog-dev':
|
||||
ensure => installed ,
|
||||
}->
|
||||
|
||||
ini_setting { 'cinder_conf_enabled_backends':
|
||||
ensure => present,
|
||||
path => '/etc/cinder/cinder.conf',
|
||||
section => 'DEFAULT',
|
||||
setting => 'enabled_backends',
|
||||
value => 'hedvig',
|
||||
before => Ini_setting['cinder_conf_volume_driver'],
|
||||
} ->
|
||||
|
||||
ini_setting { 'cinder_conf_volume_driver':
|
||||
ensure => present,
|
||||
path => '/etc/cinder/cinder.conf',
|
||||
section => 'hedvig',
|
||||
setting => 'volume_driver',
|
||||
value => 'cinder.volume.drivers.hedvig.hedvig-cinder.HedvigISCSIDriver',
|
||||
before => Ini_setting['cinder_conf_hedvig_metadata_server'],
|
||||
} ->
|
||||
|
||||
ini_setting { 'cinder_conf_hedvig_metadata_server':
|
||||
ensure => present,
|
||||
path => '/etc/cinder/cinder.conf',
|
||||
section => 'hedvig',
|
||||
setting => 'hedvig_metadata_server',
|
||||
value => $metadata_server,
|
||||
} ->
|
||||
|
||||
service { $services:
|
||||
ensure => running,
|
||||
}->
|
||||
exec { "Create Cinder volume type \'${volume_type}\'":
|
||||
command => "bash -c 'source /root/openrc; cinder type-create ${volume_type}'",
|
||||
path => ['/usr/bin', '/bin'],
|
||||
unless => "bash -c 'source /root/openrc; cinder type-list |grep -q \" ${volume_type} \"'",
|
||||
}
|
||||
|
||||
exec { "ldconfig /usr/local/lib":
|
||||
command => 'ldconfig /usr/local/lib',
|
||||
path => ['/usr/local/sbin','/usr/local/bin','/usr/sbin','/usr/bin','/sbin','/bin'],
|
||||
} ->
|
||||
|
||||
exec { "ReStart Cinder volume ":
|
||||
command => 'service cinder-volume restart',
|
||||
path => ['/usr/local/sbin','/usr/local/bin','/usr/sbin','/usr/bin','/sbin','/bin'],
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
attributes:
|
||||
multibackend:
|
||||
value: 'true'
|
||||
label: 'Multi-backend enabled'
|
||||
description: 'Hedvig will be used in a multi-backend environment'
|
||||
weight: 10
|
||||
type: "checkbox"
|
||||
hedvig_metadata_server:
|
||||
value: ''
|
||||
label: 'Hedvig cluster node(s)'
|
||||
description: 'Comma separated list of hostname (or IP address) for Hedvig cluster node(s)'
|
||||
weight: 20
|
||||
type: "text"
|
||||
regex:
|
||||
source: '\S'
|
||||
error: "This field cannot be empty"
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
# Plugin name
|
||||
name: fuel-plugin-hedvig-cinder
|
||||
# Human-readable name for your plugin
|
||||
title: Fuel plugin for Hedvig cinder driver
|
||||
# Plugin version
|
||||
version: '1.0.0'
|
||||
# Description
|
||||
description: Enable to use Hedvig as a cinder backend
|
||||
# Required fuel version
|
||||
fuel_version: ['7.0']
|
||||
# Specify license of your plugin
|
||||
licenses: ['Apache License Version 2.0']
|
||||
# Specify author or company name
|
||||
authors: ['abhjith shenoy(ashenoy@hedviginc.com), suhani gupta(suhani@hedviginc.com)']
|
||||
# A link to the plugin's page
|
||||
homepage: 'https://github.com/openstack/fuel-plugin-hedvig-cinder'
|
||||
# Specify a group which your plugin implements, possible options:
|
||||
# network, storage, storage::cinder, storage::glance, hypervisor
|
||||
groups: ['storage::cinder']
|
||||
|
||||
# The plugin is compatible with releases in the list
|
||||
releases:
|
||||
- os: ubuntu
|
||||
version: 2015.1.0-7.0
|
||||
mode: ['ha']
|
||||
deployment_scripts_path: deployment_scripts/
|
||||
repository_path: repositories/ubuntu
|
||||
|
||||
# Version of plugin package
|
||||
package_version: '1.0.0'
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Add here any the actions which are required before plugin build
|
||||
# like packages building, packages downloading from mirrors and so on.
|
||||
# The script should return 0 if there were no errors.
|
|
@ -0,0 +1,11 @@
|
|||
# These tasks will be merged into deployment graph. Here you
|
||||
# can specify new tasks for any roles, even built-in ones.
|
||||
|
||||
- id: hedvig-cinder
|
||||
type: puppet
|
||||
role: ['cinder']
|
||||
stage: post_deployment
|
||||
parameters:
|
||||
puppet_manifest: puppet/manifests/controller.pp
|
||||
puppet_modules: "puppet/modules/:/etc/puppet/modules/"
|
||||
timeout: 360
|
Loading…
Reference in New Issue