From dba6a0836819361eefda04bd5350085ef234bb06 Mon Sep 17 00:00:00 2001 From: Bin Sun Date: Mon, 3 Sep 2018 14:37:30 +0800 Subject: Add server action interface for VIO plugin API v1 supported Change-Id: I5123727b7fcde5ecdc893e5045a19acde3aa3934 Issue-ID: MULTICLOUD-336 Signed-off-by: Bin Sun --- vio/vio/pub/vim/drivers/vimsdk/compute.py | 13 ++++++++ vio/vio/pub/vim/vimapi/nova/OperateServers.py | 30 +++++++++++++++++ vio/vio/swagger/urls.py | 11 +++++++ vio/vio/swagger/views/server/views.py | 46 +++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) diff --git a/vio/vio/pub/vim/drivers/vimsdk/compute.py b/vio/vio/pub/vim/drivers/vimsdk/compute.py index 2326fff..e415573 100644 --- a/vio/vio/pub/vim/drivers/vimsdk/compute.py +++ b/vio/vio/pub/vim/drivers/vimsdk/compute.py @@ -76,6 +76,19 @@ class ComputeClient(base.DriverBase): ifaces = self.conn.compute.server_interfaces(server_id) return list(ifaces) + @sdk.translate_exception + def start_server(self, server_id): + self.conn.compute.start_server(server=server_id) + + @sdk.translate_exception + def stop_server(self, server_id): + self.conn.compute.stop_server(server=server_id) + + @sdk.translate_exception + def reboot_server(self, server_id, reboot_type): + self.conn.compute.reboot_server(server=server_id, + reboot_type=reboot_type) + @sdk.translate_exception def list_flavors(self, **query): flavors = self.conn.compute.flavors(**query) diff --git a/vio/vio/pub/vim/vimapi/nova/OperateServers.py b/vio/vio/pub/vim/vimapi/nova/OperateServers.py index 3075276..b14c7f4 100644 --- a/vio/vio/pub/vim/vimapi/nova/OperateServers.py +++ b/vio/vio/pub/vim/vimapi/nova/OperateServers.py @@ -162,3 +162,33 @@ class OperateServers(OperateNova): 'project_id': project_id} project = self.compute(param).delete_server(server_id) return project + + def start_server(self, data, project_id, server_id): + param = {'username': data['username'], + 'user_domain_name': 'default', + 'project_domain_name': 'default', + 'password': data['password'], + 'auth_url': data['url'], + 'project_id': project_id} + project = self.compute(param).start_server(server_id) + return project + + def stop_server(self, data, project_id, server_id): + param = {'username': data['username'], + 'user_domain_name': 'default', + 'project_domain_name': 'default', + 'password': data['password'], + 'auth_url': data['url'], + 'project_id': project_id} + project = self.compute(param).stop_server(server_id) + return project + + def reboot_server(self, data, project_id, server_id, reboot_type): + param = {'username': data['username'], + 'user_domain_name': 'default', + 'project_domain_name': 'default', + 'password': data['password'], + 'auth_url': data['url'], + 'project_id': project_id} + project = self.compute(param).reboot_server(server_id, reboot_type) + return project diff --git a/vio/vio/swagger/urls.py b/vio/vio/swagger/urls.py index 3b5dac7..8456d71 100644 --- a/vio/vio/swagger/urls.py +++ b/vio/vio/swagger/urls.py @@ -25,6 +25,8 @@ from vio.swagger.views.image.views import GetImageFileView from vio.swagger.views.volume.views import CreateListVolumeView from vio.swagger.views.volume.views import GetDeleteVolumeView from vio.swagger.views.server.views import ListServersView, GetServerView +from vio.swagger.views.server.views import ServerActionView +from vio.swagger.views.server.views import ServerActionViewV1 from vio.swagger.views.flavor.views import FlavorsView, FlavorView from vio.swagger.views.network.views import CreateNetworkView from vio.swagger.views.network.views import DeleteNetworkView @@ -148,6 +150,10 @@ urlpatterns = [ url(r'^api/multicloud-vio/v0/(?P[0-9a-zA-Z_-]+)/' r'(?P[0-9a-zA-Z]+)/servers/(?P[0-9a-zA-Z_-]+)$', GetServerView.as_view()), + url(r'^api/multicloud-vio/v0/(?P[0-9a-zA-Z_-]+)/' + r'(?P[0-9a-zA-Z]+)/servers/' + r'(?P[0-9a-zA-Z_-]+)/action$', + ServerActionView.as_view()), url(r'^api/multicloud-vio/v0/(?P[0-9a-zA-Z_-]+)/' r'(?P[0-9a-zA-Z]+)/flavors$', FlavorsView.as_view()), @@ -185,6 +191,7 @@ urlpatterns = [ r'(?P[0-9a-zA-Z\-\_]+)$', DeletePortView.as_view()), + # V1 urls url(r'^api/multicloud-vio/v1/(?P[0-9a-zA-Z_-]+)/' r'(?P[0-9a-zA-Z_-]+)/tenants$', @@ -221,6 +228,10 @@ urlpatterns = [ r'(?P[0-9a-zA-Z_-]+)/(?P[0-9a-zA-Z]+)/' r'servers/(?P[0-9a-zA-Z_-]+)$', GetServerViewV1.as_view()), + url(r'^api/multicloud-vio/v1/(?P[0-9a-zA-Z_-]+)/' + r'(?P[0-9a-zA-Z_-]+)/(?P[0-9a-zA-Z]+)/' + r'servers/(?P[0-9a-zA-Z_-]+)/action$', + ServerActionViewV1.as_view()), url(r'^api/multicloud-vio/v1/(?P[0-9a-zA-Z_-]+)/' r'(?P[0-9a-zA-Z_-]+)/(?P[0-9a-zA-Z]+)/' r'flavors$', diff --git a/vio/vio/swagger/views/server/views.py b/vio/vio/swagger/views/server/views.py index fca9cb9..be720c8 100644 --- a/vio/vio/swagger/views/server/views.py +++ b/vio/vio/swagger/views/server/views.py @@ -183,3 +183,49 @@ class GetServerViewV1(GetServerView): def delete(self, request, cloud_owner, cloud_region, tenantid, serverid): return super(GetServerViewV1, self).delete( request, cloud_owner + "_" + cloud_region, tenantid, serverid) + + +class ServerActionView(APIView): + + def post(self, request, vimid, tenantid, serverid): + try: + action_req = json.loads(request.body) + except Exception as e: + return Response(data={'error': 'Fail to decode request body.'}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + try: + vim_info = extsys.get_vim_by_id(vimid) + except VimDriverVioException as e: + return Response(data={'error': str(e)}, status=e.status_code) + data = {'vimid': vim_info['vimId'], + 'vimName': vim_info['name'], + 'username': vim_info['userName'], + 'password': vim_info['password'], + 'url': vim_info['url']} + + server_op = OperateServers.OperateServers() + try: + if 'os-start' in action_req: + server_op.start_server(data, tenantid, serverid) + elif 'os-stop' in action_req: + server_op.stop_server(data, tenantid, serverid) + elif 'reboot' in action_req: + reboot_type = action_req.get('reboot').get('type') + server_op.reboot_server(data, tenantid, serverid, reboot_type) + else: + return Response(data={'error': 'invalid request body.'}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + if hasattr(e, "http_status"): + return Response(data={'error': str(e)}, status=e.http_status) + else: + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + return Response(status=status.HTTP_202_ACCEPTED) + + +class ServerActionViewV1(ServerActionView): + def post(self, request, cloud_owner, cloud_region, tenantid, serverid): + return super(ServerActionViewV1, self).post( + request, cloud_owner + "_" + cloud_region, tenantid, serverid) -- cgit 1.2.3-korg