Retire fuxi-kubernetes

This repo is not used anymore, retire it following
https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project

Depends-On: https://review.openstack.org/602574
Change-Id: I4186612dbc50b2cc759f7a0f3993dcf1716d123e
This commit is contained in:
Andreas Jaeger 2018-09-22 15:53:23 +02:00
parent 18e01ab9d8
commit f147757059
54 changed files with 8 additions and 2107 deletions

52
.gitignore vendored
View File

@ -1,52 +0,0 @@
*.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
dist
build
.eggs
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
.testrepository
.venv
.log
*.cover
*.sample
# Translations
*.mo
# Complexity
output/*.html
output/*/index.html
# Sphinx
doc/build
# pbr generates these
AUTHORS
ChangeLog
# Editors
*~
.*sw?
releasenotes/build

View File

@ -1,7 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./fuxi-kubernetes/tests/unit} $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1,17 +0,0 @@
If you would like to contribute to the development of OpenStack, you must
follow the steps in this page:
http://docs.openstack.org/infra/manual/developers.html
If you already have a good understanding of how the system works and your
OpenStack accounts are set up, you can skip to the development workflow
section of this documentation to learn how changes to OpenStack should be
submitted for review via the Gerrit tool:
http://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/fuxi-kubernetes

View File

@ -1,4 +0,0 @@
fuxi-kubernetes Style Commandments
===============================================
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

175
LICENSE
View File

@ -1,175 +0,0 @@
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.

View File

@ -1,20 +1,10 @@
========================
Team and repository tags
========================
This project is no longer maintained.
.. image:: http://governance.openstack.org/badges/fuxi-kubernetes.svg
:target: http://governance.openstack.org/reference/tags/index.html
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".
.. Change things from this point on
===============
fuxi-kubernetes
===============
Make Kubernetes integration with OpenStack storage
* Free software: Apache license
* Documentation:
* Source: http://git.openstack.org/cgit/openstack/fuxi-kubernetes
* Bugs: http://bugs.launchpad.net/fuxi-kubernetes
* Blueprints: https://blueprints.launchpad.net/fuxi-kubernetes
For any further questions, please email
openstack-dev@lists.openstack.org or join #openstack-dev on
Freenode.

View File

@ -1,2 +0,0 @@
[python: **.py]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,74 +0,0 @@
# 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.
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
'oslosphinx',
'reno.sphinxext'
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'fuxi-kubernetes'
copyright = u'2013, OpenStack Foundation'
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
# intersphinx_mapping = {'http://docs.python.org/': None}

View File

@ -1,4 +0,0 @@
============
Contributing
============
.. include:: ../../CONTRIBUTING.rst

View File

@ -1,46 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
FlexVolume Driver
=================
As the spec `[1]`_ introduced, FlexVolume `[2]`_ driver will implement the driver
interfaces of FlexVolume plugin to enable Kubelet to consume persistent
volumes. Each driver will be loaded when Kubelet starts and be used as
the standalone FlexVolume plugin, which means that Kubelet may start
several FlexVolume plugins and each plugin binds one driver.
In Fuxi-kubernetes, FlexVolume driver consists of four components.
.. figure:: ../../images/flex_volume_driver.png
:alt: FlexVolume Driver
:align: center
1. **Driver**:
FlexVolume plugin will communicate with driver by 'call-out'. So, for plguin,
the driver should be an executable file which receives each command and
returns corresponding results. For Cinder and Manila, there is a shell
file for each of them to do this work respectively.
2. **Server**:
The real driver runs as a service and locates at the work node. It
calls Cinder and Manila to supply volume for Pod.
3. **Client**:
'Driver' will pass the commands to 'Service' via 'Client'.
4. **Host**:
The driver runs on the node which may be baremetal or vitual machine.
It needs to know the informations of work node to supply volume for Pod. 'Host'
stands for the work node and supply relevant informations, such as host name,
connector which is used to connect volumes.
References
----------
_`[1]`: https://docs.openstack.org/developer/kuryr-kubernetes/specs/pike/fuxi_kubernetes.html
_`[2]`: https://github.com/kubernetes/community/blob/master/contributors/devel/flexvolume.md

View File

@ -1,17 +0,0 @@
Developer Guide
===============
Flex Volume Driver
------------------
.. toctree::
:maxdepth: 2
flex_volume_driver
Indices and tables
------------------
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -1,32 +0,0 @@
===============
Fuxi-kubernetes
===============
Introduction
============
Fuxi-kubernetes focuses on making Kubernetes integration with OpenStack storage.
Using
=====
.. toctree::
:maxdepth: 1
readme
installation
usage
contributing
Developer Guide
===============
.. toctree::
:maxdepth: 1
devref/index
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -1,3 +0,0 @@
============
Installation
============

View File

@ -1 +0,0 @@
.. include:: ../../README.rst

View File

@ -1,3 +0,0 @@
=====
Usage
=====

View File

@ -1,4 +0,0 @@
[DEFAULT]
output_file = etc/fuxi_kubernetes.conf.sample
wrap_width = 79
namespace = fuxi-kubernetes

View File

@ -1,27 +0,0 @@
# Configuration for fuxi-k8s-rootwrap
# This file should be owned by (and only-writable by) the root user
[DEFAULT]
# List of directories to load filter definitions from (separated by ',').
# These directories MUST all be only writable by root !
filters_path=/etc/fuxi-kubernetes/rootwrap.d
# List of directories to search executables in, in case filters do not
# explicitely specify a full path (separated by ',')
# If not specified, defaults to system PATH environment variable.
# These directories MUST all be only writable by root !
exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin,/usr/local/bin,/usr/local/sbin
# Enable logging to syslog
# Default value is False
use_syslog=False
# Which syslog facility to use.
# Valid values include auth, authpriv, syslog, local0, local1...
# Default value is 'syslog'
syslog_log_facility=syslog
# Which messages to log.
# INFO means log all usage
# ERROR means only log unsuccessful attempts
syslog_log_level=ERROR

View File

@ -1,23 +0,0 @@
# fuxi-kubernetes-rootwrap command filters
# This file should be owned by (and only-writeable by) the root user
[Filters]
# os-brick library commands
# os_brick.privileged.run_as_root oslo.privsep context
# This line ties the superuser privs with the config files, context name,
# and (implicitly) the actual python code invoked.
privsep-rootwrap: RegExpFilter, privsep-helper, root, privsep-helper, --config-file, /etc/(?!\.\.).*, --privsep_context, os_brick.privileged.default, --privsep_sock_path, /tmp/.*
# The following and any cinder/brick/* entries should all be obsoleted
# by privsep, and may be removed once the os-brick version requirement
# is updated appropriately.
scsi_id: CommandFilter, /lib/udev/scsi_id, root
drbdadm: CommandFilter, drbdadm, root
iscsiadm: CommandFilter, iscsiadm, root
sg_scan: CommandFilter, sg_scan, root
systool: CommandFilter, systool, root
cat: CommandFilter, cat, root
# server/cinder/bare_metal_host.py
rm: CommandFilter, rm, root
ln: CommandFilter, ln, root

View File

@ -1,19 +0,0 @@
# 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.
import pbr.version
from fuxi_kubernetes.common import constants
__version__ = pbr.version.VersionInfo(
constants.PROJECT_NAME).version_string()

View File

@ -1,31 +0,0 @@
# 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.
"""Start FlexVolume driver of Cinder"""
from oslo_serialization import jsonutils
import sys
from fuxi_kubernetes.common import constants
from fuxi_kubernetes.flex_volume_drivers.drivers.cinder import cinder
def main():
"""Entry of FlexVolume driver for Cinder
/fuxi_kubernetes/flex_volume_drivers/driver/cinder/cinder.sh will
call this function, then read the output and send it to Kubernetes.
"""
result = cinder.DriverCinder()(sys.argv[1:])
print(jsonutils.dumps(result()))
sys.exit((0 if result.status == constants.STATUS_SUCCESS else 1))

View File

@ -1,31 +0,0 @@
# 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.
"""Start server of FlexVolume driver"""
from oslo_log import log as logging
import sys
from fuxi_kubernetes.common import config
from fuxi_kubernetes.common import constants
from fuxi_kubernetes.flex_volume_drivers.server import controller
def main():
config.init(sys.argv[1:])
logging.setup(config.CONF, 'fuxi-kubernetes')
controller.init_volume_drivers()
controller.start(
constants.LOCAL_HOST,
config.CONF[config.flexvolume_driver_group.name].driver_server_port,
debug=config.CONF.debug, threaded=True)

View File

@ -1,72 +0,0 @@
# 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.
from kuryr.lib import config as kuryr_config
import os
from oslo_config import cfg
from oslo_log import log as logging
from fuxi_kubernetes.common import constants
from fuxi_kubernetes.i18n import _
from fuxi_kubernetes.version import version_info
flexvolume_driver_group = cfg.OptGroup(
'flexvolume_driver',
title='FlexVolume driver Options',
help=_('Configuration options for FlexVolume driver'))
flexvolume_driver_opts = [
cfg.HostnameOpt('hostname',
help=_('Hostname of machine '
'on which FlexVolume driver runs.')),
cfg.HostAddressOpt('node_ip',
help=_('IP address of machine '
'on which FlexVolume driver runs.')),
cfg.IntOpt('driver_server_port',
default=7878,
help=_('Port for the server of FlexVolume driver.')),
cfg.StrOpt('host_platform',
default='baremetal',
help=_('The platform on which FlexVolume driver runs. '
'Optional values are: baremetal')),
cfg.StrOpt('rootwrap_config',
default='/etc/fuxi-kubernetes/rootwrap.conf',
help=_('Path to the rootwrap configuration file to use for '
'running commands as root.')),
]
cinder_group = cfg.OptGroup(
'cinder',
title='Cinder Options',
help=_('Configuration options for OpenStack Cinder'))
cinder_opts = [
cfg.StrOpt('region_name',
default=os.environ.get('REGION'),
help=_('Region name of this node. This is used when picking'
' the URL in the service catalog.')),
]
CONF = cfg.CONF
logging.register_options(CONF)
CONF.register_opts(flexvolume_driver_opts, flexvolume_driver_group.name)
CONF.register_opts(cinder_opts, group=cinder_group.name)
kuryr_config.register_keystoneauth_opts(CONF, cinder_group.name)
def init(args, **kwargs):
cfg.CONF(args=args, project=constants.PROJECT_NAME,
version=version_info.release_string(), **kwargs)

View File

@ -1,109 +0,0 @@
# 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.
PROJECT_NAME = 'fuxi-kubernetes'
LOCAL_HOST = '0.0.0.0'
VOLUME_DRIVER_CMD = (
CMD_INIT,
CMD_GET_VOLUME_NAME,
CMD_IS_ATTACHED,
CMD_ATTACH,
CMD_WAIT_FOR_ATTACH,
CMD_MOUNT_DEVICE,
CMD_DETACH,
CMD_WAIT_FOR_DETACH,
CMD_UNMOUNT_DEVICE,
CMD_MOUNT,
CMD_UNMOUNT
) = (
"init",
"getvolumename",
"isattached",
"attach",
"waitforattach",
"mountdevice",
"detach",
"waitfordetach",
"unmountdevice",
"mount",
"unmount",
)
VOLUME_DRIVER_CMD_OPT_ARG = (
ARG_FSTYPE,
ARG_RW,
ARG_SECRET,
ARG_FSGROUP,
ARG_MOUNTS_DIR,
ARG_PV_OR_VOLUME_NAME,
) = (
"kubernetes.io/fsType",
"kubernetes.io/readwrite",
"kubernetes.io/secret",
"kubernetes.io/fsGroup",
"kubernetes.io/mountsDir",
"kubernetes.io/pvOrVolumeName",
)
VOLUME_DRIVER_CMD_RESULT_STATUS = (
STATUS_SUCCESS,
STATUS_FAILURE,
STATUS_NOT_SUPPORT
) = (
'Success',
'Failed',
'Not supported',
)
VOLUME_DRIVER_TYPE = (
VOLUME_DRIVER_CINDER,
VOLUME_DRIVER_MANICLA,
) = (
'Cinder',
'Manila'
)
VOLUME_DRIVER_SERVER_API = (
SERVER_API_IS_ATTACHED,
SERVER_API_ATTACH,
SERVER_API_WAIT_FOR_ATTACH,
SERVER_API_MOUNT_DEVICE,
SERVER_API_DETACH,
SERVER_API_WAIT_FOR_DETACH,
SERVER_API_UNMOUNT_DEVICE,
SERVER_API_MOUNT,
SERVER_API_UNMOUNT
) = (
'/VolumeDriver.is_attached',
'/VolumeDriver.attach',
'/VolumeDriver.wait_for_attach',
'/VolumeDriver.mount_device',
'/VolumeDriver.detach',
'/VolumeDriver.wait_for_detach',
'/VolumeDriver.unmount_device',
'/VolumeDriver.mount',
'/VolumeDriver.unmount',
)
CINDER_VOLUME_ATTR_KEY = (
CINDER_VOLUME_ATTR_VOLUME_ID,
) = (
'VolumeID',
)

View File

@ -1,60 +0,0 @@
# 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.
class FuxiKubernetesException(Exception):
"""Default Fuxi-kubernetes exception"""
class InvalidVolumeDriverCmdParameter(FuxiKubernetesException):
def __init__(self, reason):
super(InvalidVolumeDriverCmdParameter, self).__init__(
"Invalid FlexVolume driver cmd parameter, reason: %s" % reason)
class LoadVolumeDriverException(FuxiKubernetesException):
def __init__(self, reason):
super(LoadVolumeDriverException, self).__init__(
"Load volume driver failed, reason: %s" % reason)
class GetCinderVolumeException(FuxiKubernetesException):
def __init__(self, volume_id, reason):
super(GetCinderVolumeException, self).__init__(
"Get Cinder volume: (%s) failed, reason: %s" % (volume_id, reason))
class AttachCinderVolumeException(FuxiKubernetesException):
def __init__(self, volume_name, volume_id, reason):
super(AttachCinderVolumeException, self).__init__(
'Attach volume named: (%s) by Cinder volume: (%s) failed, '
'reason: %s' % (volume_name, volume_id, reason))
class DetachCinderVolumeException(FuxiKubernetesException):
def __init__(self, volume_name, volume_id, reason):
super(DetachCinderVolumeException, self).__init__(
'Detach volume nameed: (%s) which was attached from Cinder '
'volume: (%s) failed, reason: %s' % (
volume_name, volume_id, reason))
class NotSupportedCommand(FuxiKubernetesException):
def __init__(self):
super(NotSupportedCommand, self).__init__('Not supported')
class NotMatchedHost(FuxiKubernetesException):
def __init__(self, expect_host_name, actual_host_name):
super(NotMatchedHost, self).__init__(
'Expect running on: %s, but receive the host name: %s' % (
expect_host_name, actual_host_name))

View File

@ -1,189 +0,0 @@
# 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.
from oslo_serialization import jsonutils
import requests
from fuxi_kubernetes.common import constants
from fuxi_kubernetes import exceptions
class Result(object):
__slots__ = ('status', 'message', 'device', 'volumeName', 'attached')
def __init__(self, **kwargs):
for k, v in kwargs.items():
if k in self.__slots__:
setattr(self, k, v)
def __call__(self):
return {
k: getattr(self, k)
for k in self.__slots__ if hasattr(self, k)
}
class BaseVolumeDriver(object):
default_result = Result(status=constants.STATUS_NOT_SUPPORT)
def __init__(self):
self._driver_server_port = ''
self._driver_name = ''
def init(self):
return Result(status=constants.STATUS_SUCCESS)
def get_volume_name(self, **kwargs):
return self.default_result
def is_attached(self, host_name, **kwargs):
return self.default_result
def attach(self, host_name, **kwargs):
return self.default_result
def wait_for_attach(self, device_path, **kwargs):
return self.default_result
def mount_device(self, device_mount_path, device_path, **kwargs):
return self.default_result
def detach(self, pv_or_volume_name, host_name):
return self.default_result
def wait_for_detach(self, device_path):
return self.default_result
def unmount_device(self, device_mount_path):
return self.default_result
def mount(self, mount_dir, **kwargs):
return self.default_result
def unmount(self, mount_dir):
return self.default_result
def _generate_result(self, ret, info):
info['status'] = constants.STATUS_SUCCESS if ret else (
constants.STATUS_FAILURE)
return Result(**info)
def _request_server(self, api, data):
def _send_and_receive():
try:
url = 'http://%(ip)s:%(port)d%(api)s' % {
'ip': constants.LOCAL_HOST,
'port': self._driver_server_port,
'api': api}
data['driver'] = self._driver_name
response = requests.post(url, json=data)
if not response.ok:
return False, response.text
return True, response.json()
except Exception as ex:
return (False,
'During request to server, '
'threw exception:(%s)' % str(ex))
ret, info = _send_and_receive()
if ret:
return Result(**info)
return Result(status=constants.STATUS_FAILURE, message=info)
def __call__(self, argv):
if not argv or len(argv) < 2:
return self.default_result
cmd = argv[1]
if cmd not in constants.VOLUME_DRIVER_CMD:
return self.default_result
self._driver_server_port = int(argv[0])
argv = argv[2:]
cmd_info = self._get_cmd_info(cmd)
if len(argv) != cmd_info['required_params_num']:
return Result(
status=constants.STATUS_FAILURE,
message='Miss parameters, require %d parameters, '
'but receive %d' % (cmd_info['required_params_num'],
len(argv)))
try:
return cmd_info['func'](argv)
except Exception as ex:
return Result(status=constants.STATUS_FAILURE,
message=str(ex))
def _get_cmd_info(self, cmd):
def _load_json_param(data):
try:
return jsonutils.loads(data)
except Exception:
raise exceptions.InvalidVolumeDriverCmdParameter(
"can not load json parameter:(%s)" % data)
return {
constants.CMD_INIT: {
'required_params_num': 0,
'func': lambda argv: self.init()
},
constants.CMD_GET_VOLUME_NAME: {
'required_params_num': 1,
'func': lambda argv: self.get_volume_name(
**(_load_json_param(argv[0])))
},
constants.CMD_IS_ATTACHED: {
'required_params_num': 2,
'func': lambda argv: self.is_attached(
argv[1], **(_load_json_param(argv[0])))
},
constants.CMD_ATTACH: {
'required_params_num': 2,
'func': lambda argv: self.attach(
argv[1], **(_load_json_param(argv[0])))
},
constants.CMD_WAIT_FOR_ATTACH: {
'required_params_num': 2,
'func': lambda argv: self.wait_for_attach(
argv[0], **(_load_json_param(argv[1])))
},
constants.CMD_MOUNT_DEVICE: {
'required_params_num': 3,
'func': lambda argv: self.mount_device(
argv[0], argv[1], **(_load_json_param(argv[2])))
},
constants.CMD_DETACH: {
'required_params_num': 2,
'func': lambda argv: self.detach(*argv)
},
constants.CMD_WAIT_FOR_DETACH: {
'required_params_num': 1,
'func': lambda argv: self.wait_for_detach(*argv)
},
constants.CMD_UNMOUNT_DEVICE: {
'required_params_num': 1,
'func': lambda argv: self.unmount_device(*argv)
},
constants.CMD_MOUNT: {
'required_params_num': 2,
'func': lambda argv: self.mount(
argv[0], **(_load_json_param(argv[1])))
},
constants.CMD_UNMOUNT: {
'required_params_num': 1,
'func': lambda argv: self.unmount(*argv)
},
}.get(cmd)

View File

@ -1,94 +0,0 @@
# 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.
from fuxi_kubernetes.common import constants
from fuxi_kubernetes.flex_volume_drivers.drivers import base
class DriverCinder(base.BaseVolumeDriver):
def __init__(self):
super(DriverCinder, self).__init__()
self._driver_name = constants.VOLUME_DRIVER_CINDER
def get_volume_name(self, **kwargs):
name = self._volumeid(kwargs)
if name:
return self._generate_result(True, {'volumeName': name})
return self._generate_result(
False, {'message': 'Can not get volume name'})
def is_attached(self, host_name, **kwargs):
return self._request_server(
constants.SERVER_API_IS_ATTACHED,
{'host_name': host_name,
'volume_id': self._volumeid(kwargs)}
)
def attach(self, host_name, **kwargs):
return self._request_server(
constants.SERVER_API_ATTACH,
{'host_name': host_name,
'volume_id': self._volumeid(kwargs),
'pv_or_volume_name': kwargs.get(constants.ARG_PV_OR_VOLUME_NAME)}
)
def wait_for_attach(self, device_path, **kwargs):
params = {'device_path': device_path}
return self._request_server(
constants.SERVER_API_WAIT_FOR_ATTACH,
params
)
def mount_device(self, device_mount_path, device_path, **kwargs):
params = {
'device_mount_path': device_mount_path,
'device_path': device_path
}
return self._request_server(
constants.SERVER_API_MOUNT_DEVICE,
params
)
def detach(self, pv_or_volume_name, host_name):
return self._request_server(
constants.SERVER_API_DETACH,
{'pv_or_volume_name': pv_or_volume_name, 'host_name': host_name}
)
def wait_for_detach(self, device_path):
return self._request_server(
constants.SERVER_API_WAIT_FOR_DETACH,
{'device_path': device_path}
)
def unmount_device(self, device_mount_path):
return self._request_server(
constants.SERVER_API_UNMOUNT_DEVICE,
{'device_mount_path': device_mount_path}
)
def mount(self, mount_dir, **kwargs):
params = {'mount_dir': mount_dir}
return self._request_server(
constants.SERVER_API_MOUNT,
params
)
def unmount(self, mount_dir):
return self._request_server(
constants.SERVER_API_UNMOUNT,
{'mount_dir': mount_dir}
)
def _volumeid(self, params):
return params.get(constants.CINDER_VOLUME_ATTR_VOLUME_ID)

View File

@ -1,55 +0,0 @@
#!/bin/sh
# 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.
err() {
echo -ne "$@" 1>&2
}
log() {
echo -ne "$@" >&1
}
usage() {
err "Invalid usage. Usage: "
err "\t$0 init"
err "\t$0 getvolumename <json params>"
err "\t$0 isattached <json params> <nodename>"
err "\t$0 attach <json params> <nodename>"
err "\t$0 waitforattach <mount device> <json params>"
err "\t$0 mountdevice <mount dir> <mount device> <json params>"
err "\t$0 detach <pv or volume name> <nodename>"
err "\t$0 waitfordetach <mount device>"
err "\t$0 unmountdevice <mount device>"
err "\t$0 mount <mount dir> <json params>"
err "\t$0 unmount <mount dir>"
exit 1
}
if [ $# -lt 1 ]; then
usage
fi
config_file=/etc/fuxi-kubernetes/fuxi_kubernetes.conf
port=$(grep driver_server_port $config_file | awk '{print $NF}')
out=$(fuxi-k8s-volume-driver-cinder $port "$@")
code=$?
if [ $code -eq 0 ]; then
log "$out"
else
err "$out"
fi
exit $code

View File

@ -1,282 +0,0 @@
# 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.
import functools
import os
from oslo_log import log as logging
import re
from fuxi_kubernetes import exceptions
from fuxi_kubernetes.flex_volume_drivers.server import utils
LOG = logging.getLogger(__name__)
def check_host_name(f):
@functools.wraps(f)
def wrapper(self, host_name, *args, **kwargs):
if not host_name:
host_name = self.host_name
else:
host_name = host_name.lower()
if host_name != self.host_name:
raise exceptions.NotMatchedHost(self.host_name, host_name)
return f(self, host_name, *args, **kwargs)
return wrapper
def log_error(prefix, info, *args):
LOG.error('%s, %s' % (prefix, info), *args)
class BareMetalHost(object):
def __init__(self, cinder_client):
self._cinder_client = cinder_client
self._host_name = utils.get_local_hostname()
self._attached_volumes = {}
self._volume_link_dir = '/dev/disk/by-id/'
@property
def host_name(self):
return self._host_name
@check_host_name
def is_attached(self, host_name, volume):
for item in volume.attachments:
LOG.debug("Check whether the volume is attached on host:(%s), "
"check attachment:%s", host_name, str(item))
if host_name != item['host_name']:
continue
if os.path.exists(item['device']):
return True
return False
@check_host_name
def attach(self, host_name, volume, pv_or_volume_name):
_log_error = functools.partial(
log_error, 'Attach volume:(%s)' % pv_or_volume_name)
def _raise_except(reason):
raise exceptions.AttachCinderVolumeException(
pv_or_volume_name, volume_id, reason)
phase_init_connect = 0
phase_connect_volume = 1
phase_create_link = 2
phase_set_attachment = 3
def _rollback(phase):
try:
if phase >= phase_set_attachment:
utils.execute_cmd("rm", "-f", link_to_device)
if phase >= phase_create_link:
connector.disconnect_volume(conn_info['data'], None)
if phase >= phase_init_connect:
self._cinder_client.volumes.unreserve(volume)
except Exception as ex:
_log_error('try to roolback the operation of attach on phase '
'of (%d) failed, reason:%s', phase, str(ex))
volume_id = volume.id
if self._search_volume_ids(pv_or_volume_name):
_log_error('reduplicative pv/volume name:%s', pv_or_volume_name)
_raise_except(
'reduplicative pv/volume name:%s' % pv_or_volume_name)
# reserve volume
try:
self._cinder_client.volumes.reserve(volume)
except Exception as ex:
_log_error("reserve Cinder volume: (%s) failed, reason: %s",
volume_id, str(ex))
_raise_except('reserve volume failed')
# initialize connect
conn_info = None
try:
conn_info = self._cinder_client.volumes.initialize_connection(
volume_id, utils.brick_get_connector_properties())
except Exception as ex:
_rollback(phase_init_connect)
_log_error("initialize connection to Cinder volume:(%s) failed, "
"reason:%s", volume_id, str(ex))
_raise_except('initialize connection failed ')
# connect volume
connector = None
path = ''
try:
connector = utils.brick_get_connector(
conn_info['driver_volume_type'])
device_info = connector.connect_volume(conn_info['data'])
path = os.path.realpath(device_info['path'])
except Exception as ex:
_rollback(phase_connect_volume)
_log_error("connect to Cinder volume:(%s) failed, reason:%s",
volume_id, str(ex))
_raise_except('connect to Cinder volume failed')
# create soft link to device
link_to_device = self._link_to_device(volume.id, pv_or_volume_name)
try:
utils.execute_cmd('ln', '-s', path, link_to_device)
except Exception as ex:
_rollback(phase_create_link)
_log_error("create soft link:(%s) to device:(%s) failed, "
"reason:%s.", link_to_device, path, str(ex))
_raise_except("create soft link to device failed")
# set attachment
try:
self._cinder_client.volumes.attach(
volume=volume, instance_uuid=None, mountpoint=path,
host_name=host_name)
except Exception as ex:
_rollback(phase_set_attachment)
_log_error("set attachment info to Cinder volume:(%s) failed,",
volume_id)
_raise_except("set attachment info to Cinder failed,")
self._attached_volumes[pv_or_volume_name] = volume_id
return path
def wait_for_attach(self, device_path):
LOG.warn('Use Kubernetes\' default method instead')
raise exceptions.NotSupportedCommand()
def mount_device(self, device_mount_path, device_path):
LOG.warn('Use Kubernetes\' default method instead')
raise exceptions.NotSupportedCommand()
@check_host_name
def detach(self, host_name, pv_or_volume_name):
_log_error = functools.partial(
log_error, 'Detach volume:(%s)' % pv_or_volume_name)
def _raise_except(reason):
raise exceptions.DetachCinderVolumeException(
pv_or_volume_name, volume_id, reason)
volume_id = ''
volume_ids = self._search_volume_ids(pv_or_volume_name)
if not volume_ids or len(volume_ids) > 1:
info = 'can not find corresponding volume id'
_log_error(info)
_raise_except(info)
volume_id = volume_ids[0]
volume = None
try:
volume = self._cinder_client.volumes.get(volume_id)
except Exception as ex:
_log_error('get volume:(%s) from Cinder failed', volume_id)
_raise_except('get volume from Cinder failed')
# delete link to device
try:
link_to_device = self._link_to_device(volume_id, pv_or_volume_name)
if os.path.islink(link_to_device):
utils.execute_cmd('rm', '-f', link_to_device)
except Exception as ex:
_log_error("delete link:(%s) to device:(%s) failed, reason:%s",
link_to_device, os.path.realpath(link_to_device),
str(ex))
_raise_except('delete link to device failed')
# disconnect volume
conn_info = None
try:
conn_info = self._cinder_client.volumes.initialize_connection(
volume_id, utils.brick_get_connector_properties())
except Exception as ex:
_log_error("initialize connection to Cinder volume:(%s) failed, "
"reason:%s", volume_id, str(ex))
_raise_except('initialize connection failed')
try:
connector = utils.brick_get_connector(
conn_info['driver_volume_type'])
connector.disconnect_volume(conn_info['data'], None)
except Exception as ex:
_log_error("disconnect volume:(%s) failed, reason:%s",
volume_id, str(ex))
_raise_except('disconnect volume failed')
# delete attachment
attachment_id = None
for am in volume.attachments:
if am['host_name'] == host_name:
attachment_id = am['attachment_id']
break
else:
_log_error("does not find the attachment of wolume:(%s) which "
"is attached on host:(%s)", volume_id, host_name)
try:
if attachment_id:
self._cinder_client.volumes.detach(
volume_id, attachment_uuid=attachment_id)
except Exception as ex:
_log_error("delete attachment:(%s) from Cinder failed, reason:%s",
attachment_id, str(ex))
_raise_except('delete attachment info from Cinder failed,')
self._attached_volumes.pop(pv_or_volume_name, None)
def wait_for_detach(self, device_path):
LOG.warn('Use Kubernetes\' default method instead')
raise exceptions.NotSupportedCommand()
def unmount_device(self, device_mount_path):
LOG.warn('Use Kubernetes\' default method instead')
raise exceptions.NotSupportedCommand()
def mount(self, mount_dir):
LOG.warn('Use Kubernetes\' default method instead')
raise exceptions.NotSupportedCommand()
def unmount(self, mount_dir):
LOG.warn('Use Kubernetes\' default method instead')
raise exceptions.NotSupportedCommand()
def _search_volume_ids(self, pv_or_volume_name):
volume_id = self._attached_volumes.get(pv_or_volume_name)
if volume_id:
return [volume_id]
def _volume_id(f):
if f.find(flag) > 0 and os.path.islink(os.path.join(link_dir, f)):
strs = re.split(flag, f)
return strs[0] if len(strs) == 2 and strs[1] == '' else None
flag = "_%s" % pv_or_volume_name
link_dir = self._volume_link_dir
volume_ids = []
for f in os.listdir(link_dir):
volume_id = _volume_id(f)
if volume_id:
volume_ids.append(volume_id)
return volume_ids
def _link_to_device(self, volume_id, pv_or_volume_name):
return os.path.join(self._volume_link_dir,
"%s_%s" % (volume_id, pv_or_volume_name))

View File

@ -1,72 +0,0 @@
# 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.
from stevedore import driver as import_driver
from stevedore import extension
from fuxi_kubernetes import exceptions
from fuxi_kubernetes.flex_volume_drivers.server import utils
class ServerCinder(object):
def __init__(self, host_platform):
host_cls = import_driver.DriverManager(
'flex_volume_drivers.server.cinder.hosts',
host_platform).driver
self._cinder_client = utils.get_cinder_client()
self._host = host_cls(self._cinder_client)
def is_attached(self, volume_id, host_name):
volume = self._get_volume(volume_id)
if not volume.attachments:
return False
return self._host.is_attached(host_name, volume)
def attach(self, volume_id, host_name, pv_or_volume_name):
return self._host.attach(host_name, self._get_volume(volume_id),
pv_or_volume_name)
def wait_for_attach(self, device_path):
return self._host.wait_for_attach(device_path)
def mount_device(self, device_mount_path, device_path):
self._host.mount_device(device_mount_path, device_path)
def detach(self, pv_or_volume_name, host_name):
self._host.detach(host_name, pv_or_volume_name)
def wait_for_detach(self, device_path):
self._host.wait_for_detach(device_path)
def unmount_device(self, device_mount_path):
self._host.unmount_device(device_mount_path)
def mount(self, mount_dir):
self._host.mount(mount_dir)
def unmount(self, mount_dir):
self._host.unmount(mount_dir)
def _get_volume(self, volume_id):
try:
return self._cinder_client.volumes.get(volume_id)
except Exception as ex:
raise exceptions.GetCinderVolumeException(volume_id, str(ex))
@classmethod
def is_support_host_platform(cls, host_platform):
mgr = extension.ExtensionManager(
namespace='flex_volume_drivers.server.cinder.hosts',
)
return host_platform in [e.name for e in mgr]

View File

@ -1,134 +0,0 @@
# 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.
"""Server of FlexVolume driver"""
import flask
import functools
from oslo_log import log as logging
from stevedore import extension
from fuxi_kubernetes.common import config
from fuxi_kubernetes.common import constants
from fuxi_kubernetes import exceptions
from fuxi_kubernetes.flex_volume_drivers.drivers import base
LOG = logging.getLogger(__name__)
APP = flask.Flask(__name__)
def start(host=None, port=None, debug=None, **options):
APP.run(host, port, debug, **options)
def init_volume_drivers():
mgr = extension.ExtensionManager(
namespace='flex_volume_drivers.server',
)
host_platform = config.CONF[
config.flexvolume_driver_group.name].host_platform
APP.volume_drivers = {
e.name: e.plugin(host_platform)
for e in mgr
if e.plugin.is_support_host_platform(host_platform)
}
if not APP.volume_drivers:
raise exceptions.LoadVolumeDriverException('No driver is loaded')
def api_wrapper(f):
def _response(ret, info):
if ret:
info.setdefault('status', constants.STATUS_SUCCESS)
else:
info = {'status': constants.STATUS_FAILURE, 'message': info}
return flask.jsonify(base.Result(**info)())
@functools.wraps(f)
def wrapper(*args, **kwargs):
data = flask.request.get_json(force=True)
driver_name = data.pop('driver', '')
driver = APP.volume_drivers.get(driver_name)
if not driver:
return _response(
False, 'Unknow FlexVolume driver:(%s)' % driver_name)
try:
return _response(True, f(driver, data))
except exceptions.NotSupportedCommand:
return _response(True, {'status': constants.STATUS_NOT_SUPPORT})
except Exception as ex:
return _response(False, str(ex))
return wrapper
@APP.route(constants.SERVER_API_IS_ATTACHED, methods=['POST'])
@api_wrapper
def is_attached(driver=None, params=None):
return {'attached': driver.is_attached(**params)}
@APP.route(constants.SERVER_API_ATTACH, methods=['POST'])
@api_wrapper
def attach(driver=None, params=None):
return {'device': driver.attach(**params)}
@APP.route(constants.SERVER_API_WAIT_FOR_ATTACH, methods=['POST'])
@api_wrapper
def wait_for_attach(driver=None, params=None):
return {'device': driver.wait_for_attach(**params)}
@APP.route(constants.SERVER_API_MOUNT_DEVICE, methods=['POST'])
@api_wrapper
def mount_device(driver=None, params=None):
driver.mount_device(**params)
return {}
@APP.route(constants.SERVER_API_DETACH, methods=['POST'])
@api_wrapper
def detach(driver=None, params=None):
driver.detach(**params)
return {}
@APP.route(constants.SERVER_API_WAIT_FOR_DETACH, methods=['POST'])
@api_wrapper
def wait_for_detach(driver=None, params=None):
driver.wait_for_detach(**params)
return {}
@APP.route(constants.SERVER_API_UNMOUNT_DEVICE, methods=['POST'])
@api_wrapper
def unmount_device(driver=None, params=None):
driver.unmount_device(**params)
return {}
@APP.route(constants.SERVER_API_MOUNT, methods=['POST'])
@api_wrapper
def mount(driver=None, params=None):
driver.mount(**params)
return {}
@APP.route(constants.SERVER_API_UNMOUNT, methods=['POST'])
@api_wrapper
def unmount(driver=None, params=None):
driver.unmount(**params)
return {}

View File

@ -1,88 +0,0 @@
# 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.
from cinderclient import client as cinder_client
from kuryr.lib import utils as kuryr_utils
from os_brick.initiator import connector
from oslo_concurrency import processutils
import socket
from fuxi_kubernetes.common import config as local_config
def get_root_helper():
return 'sudo fuxi-k8s-rootwrap %s' % local_config.CONF[
local_config.flexvolume_driver_group.name].rootwrap_config
def brick_get_connector_properties(multipath=False, enforce_multipath=False):
"""Wrapper to automatically set root_helper in brick calls.
:param multipath: A boolean indicating whether the connector can
support multipath.
:param enforce_multipath: If True, it raises exception when multipath=True
is specified but multipathd is not running.
If False, it falls back to multipath=False
when multipathd is not running.
"""
return connector.get_connector_properties(
get_root_helper(),
local_config.CONF[local_config.flexvolume_driver_group.name].node_ip,
multipath, enforce_multipath)
def brick_get_connector(protocol, driver=None, use_multipath=False,
device_scan_attempts=3, *args, **kwargs):
"""Wrapper to get a brick connector object.
This automatically populates the required protocol as well
as the root_helper needed to execute commands.
"""
if protocol.upper() == "RBD":
kwargs['do_local_attach'] = True
return connector.InitiatorConnector.factory(
protocol, get_root_helper(),
driver=driver, use_multipath=use_multipath,
device_scan_attempts=device_scan_attempts,
*args, **kwargs)
def get_local_hostname():
host_name = local_config.CONF[
local_config.flexvolume_driver_group.name].host_name
if not host_name:
host_name = socket.gethostname()
return host_name.lower()
def execute_cmd(*cmd):
return processutils.execute(*cmd, run_as_root=True,
root_helper=get_root_helper())
def _get_keystone_session(conf_group, **kwargs):
auth_plugin = kuryr_utils.get_auth_plugin(conf_group)
session = kuryr_utils.get_keystone_session(conf_group, auth_plugin)
return session, auth_plugin
def get_cinder_client(*args, **kwargs):
session, auth_plugin = _get_keystone_session(
local_config.cinder_group.name)
return cinder_client.Client(
session=session, auth=auth_plugin,
region_name=local_config.CONF[
local_config.cinder_group.name].region_name,
version=2)

View File

@ -1,22 +0,0 @@
# 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.
import oslo_i18n
from fuxi_kubernetes.common import constants
DOMAIN = constants.PROJECT_NAME
_translators = oslo_i18n.TranslatorFactory(domain=DOMAIN)
# The primary translation function using the well-known name "_"
_ = _translators.primary

View File

@ -1,36 +0,0 @@
# 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.
__all__ = [
'list_fuxi_k8s_opts',
]
import itertools
from kuryr.lib import opts as kuryr_opts
from oslo_log import _options
from fuxi_kubernetes.common import config
def list_fuxi_k8s_opts():
auth_opts = kuryr_opts.get_keystoneauth_conf_options()
return [
('DEFAULT',
itertools.chain(_options.list_opts()[0][1],)),
(config.flexvolume_driver_group.name,
itertools.chain(config.flexvolume_driver_opts,)),
(config.cinder_group.name,
itertools.chain(config.cinder_opts, auth_opts,)),
]

View File

@ -1,18 +0,0 @@
# 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.
from oslotest import base
class TestCase(base.BaseTestCase):
"""Test case base class for all unit tests."""

View File

@ -1,35 +0,0 @@
# 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.
from fuxi_kubernetes.common import constants
from fuxi_kubernetes.flex_volume_drivers.drivers import base as base_driver
from fuxi_kubernetes.tests.unit import base
class TestBaseVolumeDriver(base.TestCase):
def setUp(self):
super(TestBaseVolumeDriver, self).setUp()
self._driver = base_driver.BaseVolumeDriver()
def test_empty_argument(self):
self.assertEqual(constants.STATUS_NOT_SUPPORT,
self._driver([]).status)
def test_invalid_cmd(self):
self.assertEqual(constants.STATUS_NOT_SUPPORT,
self._driver(['abc']).status)
def test_load_json_fail(self):
r = self._driver(['123', 'attach', 'abc', 'abc'])
self.assertEqual(constants.STATUS_FAILURE, r.status)
self.assertIn('can not load json parameter', r.message)

View File

@ -1,19 +0,0 @@
# 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.
from fuxi_kubernetes.tests.unit import base
class TestFuxiKubernetes(base.TestCase):
def test_something(self):
pass

View File

@ -1,15 +0,0 @@
# 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.
import pbr.version
version_info = pbr.version.VersionInfo('fuxi-kubernetes')

View File

@ -1,11 +0,0 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr!=2.1.0,>=2.0.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
os-brick>=1.15.2 # Apache-2.0
python-cinderclient>=3.1.0 # Apache-2.0
stevedore>=1.20.0 # Apache-2.0
Flask!=0.11,<1.0,>=0.10 # BSD
kuryr-lib>=0.5.0 # Apache-2.0

View File

@ -1,60 +0,0 @@
[metadata]
name = fuxi-kubernetes
summary = Make Kubernetes integration with OpenStack storage
description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = http://www.openstack.org/
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.5
[files]
packages =
fuxi_kubernetes
[entry_points]
oslo.config.opts =
fuxi-kubernetes = fuxi_kubernetes.opts:list_fuxi_k8s_opts
console_scripts =
fuxi-k8s-volume-driver-cinder = fuxi_kubernetes.cmd.cinder:main
fuxi-k8s-volume-driver-server = fuxi_kubernetes.cmd.driver_server:main
fuxi-k8s-rootwrap = oslo_rootwrap.cmd:main
flex_volume_drivers.server =
Cinder = fuxi_kubernetes.flex_volume_drivers.server.cinder.cinder:ServerCinder
flex_volume_drivers.server.cinder.hosts =
baremetal = fuxi_kubernetes.flex_volume_drivers.server.cinder.bare_metal_host:BareMetalHost
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all_files = 1
[upload_sphinx]
upload-dir = doc/build/html
[compile_catalog]
directory = fuxi-kubernetes/locale
domain = fuxi-kubernetes
[update_catalog]
domain = fuxi-kubernetes
output_dir = fuxi-kubernetes/locale
input_file = fuxi-kubernetes/locale/fuxi-kubernetes.pot
[extract_messages]
keywords = _ gettext ngettext l_ lazy_gettext
mapping_file = babel.cfg
output_file = fuxi-kubernetes/locale/fuxi-kubernetes.pot

View File

@ -1,27 +0,0 @@
# 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.
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
pbr=True)

View File

@ -1,14 +0,0 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
coverage!=4.4,>=4.0 # Apache-2.0
python-subunit>=0.0.18 # Apache-2.0/BSD
sphinx!=1.6.1,>=1.5.1 # BSD
oslosphinx>=4.7.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
reno!=2.3.1,>=1.8.0 # Apache-2.0

View File

@ -1,54 +0,0 @@
#!/bin/sh
#
# 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.
set -e
GEN_CMD=oslo-config-generator
SCRIPT_PATH=$(dirname "$(readlink -f "$0")")
DIST_PATH=$(dirname "$SCRIPT_PATH")
prerequisites() (
if ! command -v "$GEN_CMD" > /dev/null; then
echo "ERROR: $GEN_CMD not installed on the system."
return 1
fi
if ! [ -f "${DIST_PATH}/fuxi_kubernetes.egg-info/entry_points.txt" ]; then
curr_dir=$(pwd)
cd "${DIST_PATH}"
python setup.py egg_info # Generate entrypoints for config generation
cd "${curr_dir}"
fi
return 0
)
generate() (
curr_dir=$(pwd)
cd "${DIST_PATH}"
# Set PYTHONPATH so that it will use the generated egg-info
PYTHONPATH=. find "etc/oslo-config-generator" -type f -exec "$GEN_CMD" --config-file="{}" \;
cd "${curr_dir}"
)
prerequisites
rc=$?
if [ $rc -ne 0 ]; then
exit $rc
fi
generate
set -x

51
tox.ini
View File

@ -1,51 +0,0 @@
[tox]
minversion = 1.6
envlist = py35,py27,pep8
skipsdist = True
[testenv]
usedevelop = True
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
setenv =
VIRTUAL_ENV={envdir}
OS_TEST_PATH=./fuxi_kubernetes/tests/unit
PYTHONWARNINGS=default::DeprecationWarning
LANGUAGE=en_US
LC_ALL=en_US.utf-8
deps = -r{toxinidir}/test-requirements.txt
commands = python setup.py test --slowest --testr-args='{posargs}'
[testenv:pep8]
commands = flake8 {posargs}
[testenv:venv]
commands = {posargs}
[testenv:cover]
commands =
python setup.py test --coverage --testr-args='{posargs}'
coverage report
[testenv:docs]
commands = python setup.py build_sphinx
[testenv:debug]
commands = oslo_debug_helper {posargs}
[testenv:fullstack]
basepython = python2.7
setenv = OS_TEST_PATH=./fuxi_kubernetes/tests/fullstack
[testenv:genconfig]
commands = oslo-config-generator --config-file=etc/oslo-config-generator/fuxi-kubernetes-config-generator.conf
[testenv:releasenotes]
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
[flake8]
show-source = True
builtins = _
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,releasenotes
[hacking]
import_exceptions = fuxi-kubernetes.i18n