Add share network activate and deactivate

Add activation and deactivation requests
handling into share networks API.

Implements bp: share-network-activation-api

Change-Id: Ifadda82b279de3bcf31967a28bd8356e12c64d63
This commit is contained in:
Aleks Chirko 2014-02-06 16:29:02 +02:00 committed by vponomaryov
parent 3e290e7051
commit 90cb627f9e
8 changed files with 356 additions and 47 deletions

View File

@ -27,6 +27,11 @@
"share_network:create": [], "share_network:create": [],
"share_network:delete": [], "share_network:delete": [],
"share_network:update": [], "share_network:update": [],
"share_network:index": [],
"share_network:detail": [],
"share_network:show": [],
"share_network:add_security_service": [], "share_network:add_security_service": [],
"share_network:remove_security_service": [] "share_network:remove_security_service": [],
"share_network:activate": [],
"share_network:deactivate": []
} }

View File

@ -24,8 +24,11 @@ from manila.api import xmlutil
from manila.common import constants from manila.common import constants
from manila.db import api as db_api from manila.db import api as db_api
from manila import exception from manila import exception
from manila import network
from manila.openstack.common import importutils
from manila.openstack.common import log as logging from manila.openstack.common import log as logging
from manila import policy from manila import policy
from manila.share import rpcapi as share_rpcapi
RESOURCE_NAME = 'share_network' RESOURCE_NAME = 'share_network'
RESOURCES_NAME = 'share_networks' RESOURCES_NAME = 'share_networks'
@ -71,6 +74,10 @@ class ShareNetworkController(wsgi.Controller):
_view_builder_class = share_networks_views.ViewBuilder _view_builder_class = share_networks_views.ViewBuilder
def __init__(self):
super(ShareNetworkController, self).__init__()
self.share_rpcapi = share_rpcapi.ShareAPI()
@wsgi.serializers(xml=ShareNetworkTemplate) @wsgi.serializers(xml=ShareNetworkTemplate)
def show(self, req, id): def show(self, req, id):
"""Return data about the requested network info.""" """Return data about the requested network info."""
@ -192,6 +199,8 @@ class ShareNetworkController(wsgi.Controller):
_actions = { _actions = {
'add_security_service': self._add_security_service, 'add_security_service': self._add_security_service,
'remove_security_service': self._remove_security_service, 'remove_security_service': self._remove_security_service,
'activate': self._activate,
'deactivate': self._deactivate,
} }
for action, data in body.iteritems(): for action, data in body.iteritems():
try: try:
@ -201,6 +210,7 @@ class ShareNetworkController(wsgi.Controller):
raise exc.HTTPBadRequest(explanation=msg) raise exc.HTTPBadRequest(explanation=msg)
def _add_security_service(self, req, id, data): def _add_security_service(self, req, id, data):
"""Associate share network with a given security service."""
context = req.environ['manila.context'] context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'add_security_service') policy.check_policy(context, RESOURCE_NAME, 'add_security_service')
try: try:
@ -221,6 +231,7 @@ class ShareNetworkController(wsgi.Controller):
return self._view_builder.build_share_network(share_network) return self._view_builder.build_share_network(share_network)
def _remove_security_service(self, req, id, data): def _remove_security_service(self, req, id, data):
"""Dissociate share network from a given security service."""
context = req.environ['manila.context'] context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'remove_security_service') policy.check_policy(context, RESOURCE_NAME, 'remove_security_service')
try: try:
@ -240,6 +251,47 @@ class ShareNetworkController(wsgi.Controller):
return self._view_builder.build_share_network(share_network) return self._view_builder.build_share_network(share_network)
def _activate(self, req, id, data):
"""Activate share network."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'activate')
try:
share_network = db_api.share_network_get(context, id)
except exception.ShareNetworkNotFound as e:
msg = _("Share-network was not found. %s") % e
raise exc.HTTPNotFound(explanation=msg)
if share_network['status'] != constants.STATUS_INACTIVE:
msg = _("Share network should be 'INACTIVE'.")
raise exc.HTTPBadRequest(explanation=msg)
self.share_rpcapi.activate_network(context, id, data)
return self._view_builder.build_share_network(share_network)
def _deactivate(self, req, id, data):
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'deactivate')
try:
share_network = db_api.share_network_get(context, id)
except exception.ShareNetworkNotFound as e:
msg = _("Share-network was not found. %s") % e
raise exc.HTTPNotFound(explanation=msg)
if share_network['status'] != constants.STATUS_ACTIVE:
msg = _("Share network should be 'ACTIVE'.")
raise exc.HTTPBadRequest(explanation=msg)
if len(share_network['shares']) > 0:
msg = _("Share network is in use.")
raise exc.HTTPBadRequest(explanation=msg)
self.share_rpcapi.deactivate_network(context, id)
return self._view_builder.build_share_network(share_network)
def create_resource(): def create_resource():
return wsgi.Resource(ShareNetworkController()) return wsgi.Resource(ShareNetworkController())

View File

@ -22,6 +22,7 @@ from manila.api import common
from manila.api.openstack import wsgi from manila.api.openstack import wsgi
from manila.api.views import shares as share_views from manila.api.views import shares as share_views
from manila.api import xmlutil from manila.api import xmlutil
from manila.common import constants
from manila import exception from manila import exception
from manila.openstack.common import log as logging from manila.openstack.common import log as logging
from manila import share from manila import share
@ -201,10 +202,15 @@ class ShareController(wsgi.Controller):
share_network_id = share.get('share_network_id') share_network_id = share.get('share_network_id')
if share_network_id: if share_network_id:
try: try:
self.share_api.db.share_network_get(context, share_network_id) share_network = self.share_api.db.share_network_get(
context,
share_network_id)
except exception.ShareNetworkNotFound as e: except exception.ShareNetworkNotFound as e:
msg = "%s" % e msg = "%s" % e
raise exc.HTTPNotFound(explanation=msg) raise exc.HTTPNotFound(explanation=msg)
if share_network['status'] == constants.STATUS_ERROR:
msg = _("Share network is in 'ERROR' state.")
raise exc.HTTPBadRequest(explanation=msg)
else: else:
kwargs['share_network_id'] = share_network_id kwargs['share_network_id'] = share_network_id

View File

@ -141,11 +141,15 @@ class ShareDriver(object):
return self._stats return self._stats
def get_network_allocations_number(self): def get_network_allocations_number(self):
"""Returns number of network allocations for creating VIFs""" """Returns number of network allocations for creating VIFs."""
pass pass
def setup_network(self, network_info): def setup_network(self, network_info, metadata=None):
"""Set up and configures VIFs with given network parameters""" """Set up and configures VIFs with given network parameters."""
pass
def teardown_network(self, network_info):
"""Teardown previously configured VIFs for given network parameters."""
pass pass
def _update_share_status(self): def _update_share_status(self):

View File

@ -93,19 +93,6 @@ class ShareManager(manager.SchedulerDependentManager):
self.publish_service_capabilities(ctxt) self.publish_service_capabilities(ctxt)
def _setup_share_network(self, context, network_ref):
allocation_number = self.driver.get_network_allocations_number()
if allocation_number:
network_info = self.network_api.allocate_network(
context, network_ref, count=allocation_number)
try:
self.driver.setup_network(network_info)
return network_info
except exception.ManilaException as e:
with excutils.save_and_reraise_exception():
self.db.share_network_update(context, network_ref['id'],
{'status': 'error'})
def create_share(self, context, share_id, request_spec=None, def create_share(self, context, share_id, request_spec=None,
filter_properties=None, snapshot_id=None): filter_properties=None, snapshot_id=None):
"""Creates a share.""" """Creates a share."""
@ -119,23 +106,18 @@ class ShareManager(manager.SchedulerDependentManager):
else: else:
snapshot_ref = None snapshot_ref = None
network_id = share_ref.get('share_network_id', None) share_network_id = share_ref.get('share_network_id', None)
if network_id: if share_network_id:
network_ref = self.db.share_network_get( share_network = self.db.share_network_get(context,
context, share_ref['share_network_id']) share_network_id)
if network_ref['status'] != constants.STATUS_ACTIVE: if share_network['status'] == constants.STATUS_INACTIVE:
if network_ref['status'] in [constants.STATUS_INACTIVE, share_network = self._activate_share_network(
constants.STATUS_NEW]: context,
network_ref = self._setup_share_network(context, share_network)
network_ref)
else:
msg = _("Network status should be ACTIVE, INACTIVE or NEW")
LOG.error(msg)
raise exception.InvalidShareNetwork(reason=msg)
else: else:
network_ref = {} share_network = {}
share_ref['network_info'] = network_ref share_ref['network_info'] = share_network
try: try:
if snapshot_ref: if snapshot_ref:
@ -283,3 +265,28 @@ class ShareManager(manager.SchedulerDependentManager):
"""Collect driver status and then publish it.""" """Collect driver status and then publish it."""
self._report_driver_status(context) self._report_driver_status(context)
self._publish_service_capabilities(context) self._publish_service_capabilities(context)
def activate_network(self, context, share_network_id, metadata=None):
share_network = self.db.share_network_get(context, share_network_id)
self._activate_share_network(context, share_network, metadata)
def deactivate_network(self, context, share_network_id):
share_network = self.db.share_network_get(context, share_network_id)
self.driver.teardown_network(share_network)
self.network_api.deallocate_network(context, share_network)
def _activate_share_network(self, context, share_network, metadata=None):
allocation_number = self.driver.get_network_allocations_number()
if allocation_number:
share_network = self.network_api.allocate_network(
context,
share_network,
count=allocation_number)
try:
self.driver.setup_network(share_network, metadata=metadata)
except exception.ManilaException:
with excutils.save_and_reraise_exception():
self.network_api.deallocate_network(context,
share_network)
else:
return share_network

View File

@ -91,3 +91,16 @@ class ShareAPI(manila.openstack.common.rpc.proxy.RpcProxy):
def publish_service_capabilities(self, ctxt): def publish_service_capabilities(self, ctxt):
self.fanout_cast(ctxt, self.make_msg('publish_service_capabilities'), self.fanout_cast(ctxt, self.make_msg('publish_service_capabilities'),
version='1.0') version='1.0')
def activate_network(self, context, share_network_id, metadata):
self.fanout_cast(context,
self.make_msg('activate_network',
share_network_id=share_network_id,
metadata=metadata),
version='1.0')
def deactivate_network(self, context, share_network_id):
self.fanout_cast(context,
self.make_msg('deactivate_network',
share_network_id=share_network_id),
version='1.0')

View File

@ -21,6 +21,7 @@ from manila.api.v1 import share_networks
from manila.common import constants from manila.common import constants
from manila.db import api as db_api from manila.db import api as db_api
from manila import exception from manila import exception
from manila import policy
from manila.tests.api import fakes from manila.tests.api import fakes
@ -274,3 +275,159 @@ class ShareNetworkAPITest(unittest.TestCase):
self.req, self.req,
share_nw, share_nw,
body) body)
def test_action_add_security_service(self):
share_network_id = 'fake network id'
security_service_id = 'fake ss id'
body = {'add_security_service': {'security_service_id':
security_service_id}}
with mock.patch.object(self.controller, '_add_security_service',
mock.Mock()):
self.controller.action(self.req, share_network_id, body)
self.controller._add_security_service.assert_called_once_with(
self.req, share_network_id, body['add_security_service'])
def test_action_remove_security_service(self):
share_network_id = 'fake network id'
security_service_id = 'fake ss id'
body = {'remove_security_service': {'security_service_id':
security_service_id}}
with mock.patch.object(self.controller, '_remove_security_service',
mock.Mock()):
self.controller.action(self.req, share_network_id, body)
self.controller._remove_security_service.assert_called_once_with(
self.req, share_network_id, body['remove_security_service'])
def test_action_activate(self):
share_network_id = 'fake network id'
body = {'activate': {}}
with mock.patch.object(self.controller, '_activate', mock.Mock()):
self.controller.action(self.req, share_network_id, body)
self.controller._activate.assert_called_once_with(
self.req, share_network_id, body['activate'])
def test_action_deactivate(self):
share_network_id = 'fake network id'
body = {'deactivate': {}}
with mock.patch.object(self.controller, '_deactivate', mock.Mock()):
self.controller.action(self.req, share_network_id, body)
self.controller._deactivate.assert_called_once_with(
self.req, share_network_id, body['deactivate'])
def test_action_bad_request(self):
share_network_id = 'fake network id'
body = {'bad_action': {}}
self.assertRaises(webob_exc.HTTPBadRequest,
self.controller.action,
self.req,
share_network_id,
body)
@mock.patch.object(db_api, 'share_network_get',
mock.Mock(return_value=fake_share_network))
@mock.patch.object(policy, 'check_policy', mock.Mock())
def test_activate(self):
share_network_id = 'fake network id'
with mock.patch.object(self.controller.share_rpcapi,
'activate_network', mock.Mock()):
self.controller._activate(self.req, share_network_id, {})
policy.check_policy.assert_called_once_with(
self.context,
share_networks.RESOURCE_NAME,
'activate')
db_api.share_network_get.assert_called_once_with(
self.context,
share_network_id)
self.controller.share_rpcapi.activate_network.\
assert_called_once_with(self.context, share_network_id, {})
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
def test_activate_not_found(self):
share_network_id = 'fake network id'
db_api.share_network_get.side_effect = \
exception.ShareNetworkNotFound(share_network_id=share_network_id)
self.assertRaises(webob_exc.HTTPNotFound,
self.controller._activate,
self.req,
share_network_id,
{})
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
def test_activate_not_inactive(self):
share_network_id = 'fake network id'
share_network = fake_share_network.copy()
share_network['status'] = constants.STATUS_ERROR
db_api.share_network_get.return_value = share_network
self.assertRaises(webob_exc.HTTPBadRequest,
self.controller._activate,
self.req,
share_network_id,
{})
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
@mock.patch.object(policy, 'check_policy', mock.Mock())
def test_deactivate(self):
share_network_id = 'fake network id'
share_network = fake_share_network.copy()
share_network['status'] = constants.STATUS_ACTIVE
db_api.share_network_get.return_value = share_network
with mock.patch.object(self.controller.share_rpcapi,
'deactivate_network', mock.Mock()):
self.controller._deactivate(self.req, share_network_id, None)
policy.check_policy.assert_called_once_with(
self.context,
share_networks.RESOURCE_NAME,
'deactivate')
db_api.share_network_get.assert_called_once_with(
self.context,
share_network_id)
self.controller.share_rpcapi.deactivate_network.\
assert_called_once_with(self.context, share_network_id)
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
def test_deactivate_not_found(self):
share_network_id = 'fake network id'
db_api.share_network_get.side_effect = \
exception.ShareNetworkNotFound(share_network_id=share_network_id)
self.assertRaises(webob_exc.HTTPNotFound,
self.controller._deactivate,
self.req,
share_network_id,
None)
@mock.patch.object(db_api, 'share_network_get',
mock.Mock(return_value=fake_share_network))
def test_deactivate_not_active(self):
share_network_id = 'fake network id'
self.assertRaises(webob_exc.HTTPBadRequest,
self.controller._deactivate,
self.req,
share_network_id,
None)
@mock.patch.object(db_api, 'share_network_get', mock.Mock())
def test_deactivate_in_use(self):
share_network_id = 'fake network id'
share_network = fake_share_network.copy()
share_network['shares'].append('fake share')
db_api.share_network_get.return_value = share_network
self.assertRaises(webob_exc.HTTPBadRequest,
self.controller._deactivate,
self.req,
share_network_id,
None)

View File

@ -73,6 +73,9 @@ class FakeShareDriver(object):
def setup_network(self, context, network, policy=None): def setup_network(self, context, network, policy=None):
pass pass
def teardown_network(self, context, network):
pass
def get_network_allocations_number(self): def get_network_allocations_number(self):
pass pass
@ -369,23 +372,85 @@ class ShareTestCase(test.TestCase):
self.share.network_api.allocate_network = mock.Mock( self.share.network_api.allocate_network = mock.Mock(
return_value={'network_info': 'network_info'}) return_value={'network_info': 'network_info'})
self.share.driver.setup_network = mock.Mock() self.share.driver.setup_network = mock.Mock()
self.share._setup_share_network(self.context, network_info) self.share._activate_share_network(self.context, network_info)
self.share.network_api.allocate_network.assert_called_once_with( self.share.network_api.allocate_network.assert_called_once_with(
self.context, network_info, count=555) self.context, network_info, count=555)
self.share.driver.setup_network.assert_called_once_with( self.share.driver.setup_network.assert_called_once_with(
{'network_info': 'network_info'}) {'network_info': 'network_info'}, metadata=None)
def test_setup_share_network_error(self): def test_setup_share_network_error(self):
network_info = {'fake': 'fake', 'id': 'fakeid'} network_info = {'fake': 'fake', 'id': 'fakeid'}
self.share.driver.get_network_allocations_number = mock.Mock( drv_allocation_cnt = mock.patch.object(
return_value=555) self.share.driver,
self.share.network_api.allocate_network = mock.Mock( 'get_network_allocations_number').start()
return_value={'network_info': 'network_info'}) drv_allocation_cnt.return_value = 555
self.share.driver.setup_network = mock.Mock( nw_api_allocate_nw = mock.patch.object(self.share.network_api,
side_effect=exception.Invalid) 'allocate_network').start()
self.share.db.share_network_update = mock.Mock() nw_api_allocate_nw.return_value = network_info
self.assertRaises(exception.Invalid, nw_api_deallocate_nw = mock.patch.object(self.share.network_api,
self.share._setup_share_network, 'deallocate_network').start()
self.context, network_info)
self.share.db.share_network_update.assert_called_once_with( with mock.patch.object(self.share.driver, 'setup_network',
self.context, 'fakeid', {'status': 'error'}) mock.Mock(side_effect=exception.Invalid)):
self.assertRaises(exception.Invalid,
self.share._activate_share_network,
self.context, network_info)
nw_api_deallocate_nw.assert_called_once_with(self.context,
network_info)
drv_allocation_cnt.stop()
nw_api_allocate_nw.stop()
nw_api_deallocate_nw.stop()
def test_activate_network(self):
share_network_id = 'fake network id'
share_network = {}
db_share_nw_get = mock.patch.object(self.share.db,
'share_network_get').start()
db_share_nw_get.return_value = share_network
drv_get_alloc_cnt = mock.patch.object(
self.share.driver,
'get_network_allocations_number').start()
drv_get_alloc_cnt.return_value = 1
nw_api_allocate_nw = mock.patch.object(self.share.network_api,
'allocate_network').start()
nw_api_allocate_nw.return_value = share_network
with mock.patch.object(self.share.driver, 'setup_network',
mock.Mock()):
self.share.activate_network(self.context, share_network_id)
db_share_nw_get.assert_called_once_with(self.context,
share_network_id)
drv_get_alloc_cnt.assert_any_call()
nw_api_allocate_nw.assert_called_once_with(self.context,
share_network,
count=1)
self.share.driver.setup_network.assert_called_once_with(
share_network,
metadata=None)
db_share_nw_get.stop()
drv_get_alloc_cnt.stop()
nw_api_allocate_nw.stop()
def test_deactivate_network(self):
share_network_id = 'fake network id'
share_network = {}
db_share_nw_get = mock.patch.object(self.share.db,
'share_network_get').start()
db_share_nw_get.return_value = share_network
nw_api_deallocate_nw = mock.patch.object(self.share.network_api,
'deallocate_network').start()
with mock.patch.object(self.share.driver, 'teardown_network',
mock.Mock()):
self.share.deactivate_network(self.context, share_network_id)
db_share_nw_get.assert_called_once_with(self.context,
share_network_id)
nw_api_deallocate_nw.assert_called_once_with(self.context,
share_network)
self.share.driver.teardown_network.assert_called_once_with(
share_network)
db_share_nw_get.stop()
nw_api_deallocate_nw.stop()