Implemet framework of flexvolume driver

Change-Id: I95b1905811f2b640aadecd3ab5bd95f499831992
reference: https://review.openstack.org/#/c/474038/
This commit is contained in:
zengchen 2017-06-07 16:55:43 +08:00
parent 0678ee4ada
commit 42fcf4640f
18 changed files with 417 additions and 1 deletions

View File

View File

@ -0,0 +1,31 @@
# 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

@ -0,0 +1,17 @@
# 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"""
def main():
raise NotImplemented()

View File

View File

@ -0,0 +1,65 @@
# 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_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
) = (
"kubernetes.io/fsType",
"kubernetes.io/readwrite",
"kubernetes.io/secret",
"kubernetes.io/fsGroup",
"kubernetes.io/mountsDir",
)
VOLUME_DRIVER_CMD_RESULT_STATUS = (
STATUS_SUCCESS,
STATUS_FAILURE,
STATUS_NOT_SUPPORT
) = (
'Success',
'Failed',
'Not supported',
)

View File

@ -0,0 +1,21 @@
# 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)

View File

@ -0,0 +1,153 @@
# 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
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):
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, device_path, 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 __call__(self, argv):
if not argv:
return self.default_result
cmd = argv[0]
if cmd not in constants.VOLUME_DRIVER_CMD:
return self.default_result
argv = argv[1:]
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

@ -0,0 +1,20 @@
# 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.flex_volume_drivers.drivers import base
class DriverCinder(base.BaseVolumeDriver):
# TODO(zengchen): implement it.
def __init__(self):
raise NotImplemented()

View File

@ -0,0 +1,53 @@
#!/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 <mount device> <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
out=$(fuxi-k8s-volume-driver-cinder "$@")
code=$?
if [ $code -eq 0 ]; then
log "$out"
else
err "$out"
fi
exit $code

View File

@ -0,0 +1,15 @@
# 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"""
# TODO(zengchen): implement it.

View File

@ -0,0 +1,35 @@
# 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(['attach', 'abc', 'abc'])
self.assertEqual(constants.STATUS_FAILURE, r.status)
self.assertIn('can not load json parameter', r.message)

View File

@ -3,3 +3,4 @@
# 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

View File

@ -20,7 +20,12 @@ classifier =
[files]
packages =
fuxi-kubernetes
fuxi_kubernetes
[entry_points]
console_scripts =
fuxi-k8s-volume-driver-cinder = fuxi_kubernetes.cmd.cinder:main
fuxi-k8s-volume-driver-server = fuxi_kubernetes.cmd.driver_server:main
[build_sphinx]
source-dir = doc/source