diff options
-rw-r--r-- | vio/assembly.xml | 2 | ||||
-rw-r--r-- | vio/cert.crt | 20 | ||||
-rw-r--r-- | vio/cert.key | 27 | ||||
-rw-r--r-- | vio/docker/Dockerfile | 2 | ||||
-rwxr-xr-x | vio/run.sh | 7 | ||||
-rw-r--r-- | vio/vio/heatbridge.py | 59 | ||||
-rw-r--r-- | vio/vio/pub/vim/drivers/vimsdk/compute.py | 4 | ||||
-rw-r--r-- | vio/vio/pub/vim/vimapi/nova/OperateNova.py | 6 | ||||
-rw-r--r-- | vio/vio/swagger/views/capacity/views.py | 85 | ||||
-rw-r--r-- | vio/vio/tests/test_capacity_view.py | 12 |
10 files changed, 202 insertions, 22 deletions
diff --git a/vio/assembly.xml b/vio/assembly.xml index 69ea59a..12f6de5 100644 --- a/vio/assembly.xml +++ b/vio/assembly.xml @@ -58,6 +58,8 @@ <include>*.ini</include> <include>*.md</include> <include>*.yml</include> + <include>*.crt</include> + <include>*.key</include> </includes> </fileSet> </fileSets> diff --git a/vio/cert.crt b/vio/cert.crt new file mode 100644 index 0000000..b025450 --- /dev/null +++ b/vio/cert.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOTCCAiECFGvacmXFIVjsVSCu473GhbCDWPjjMA0GCSqGSIb3DQEBCwUAMFkx +CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMQ8wDQYDVQQKDAZWTXdh +cmUxJDAiBgkqhkiG9w0BCQEWFWV0aGFubHlubmxAdm13YXJlLmNvbTAeFw0xOTA0 +MDIwMzI1MzZaFw0yOTAzMzAwMzI1MzZaMFkxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApTb21lLVN0YXRlMQ8wDQYDVQQKDAZWTXdhcmUxJDAiBgkqhkiG9w0BCQEWFWV0 +aGFubHlubmxAdm13YXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAPCrLGXnbKErvSG3ivbNlgXb89MglL3A8OtBYutThoaGNaZcZ1ccBg/Z4xJx +WEJoyNGJAOzAdCKLClaSSTH77g/FuLCeos8PWpFB61+cdjG/igP65bkVowa9Ubi/ +3bE5aR14RjIPPm2KWMszy/4eKEgj7cb94QjMGn+qpTY1OyQCMtpSxrJ6ZZbAa5NR +1UQukyHUx1FZKQf3XLenVgR+aSlhoCIiSr1fWR9K8nsSDj41Gjmt31rV4UwKFAHw +Rpi/4ke5Hxf8oTU3D+6r6TJeDZWDJXJQbyir6xyx4E3yvaoZf7XoPJK295+9POwN +ZMkwg6414Ut0EPzuUCzgMwjQCNECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAbRyK +paK0jO4JL6RWIWWAsgHIaHXeghmcZwLEnZKl//k3sAKm9M2IEeiqLHMIkdxz9S8b +OdT6mMEsS0dj7foDru+DlE/qao2yKNxjYiq1Ht3tCZqDtCKhqbBnoos+g9QT26kM +dxXBzKft/WwTi5AVqRZAwgVnU7VkCS9uJzFQ3nhbP8qMOXszt9yKydXbODmiUtY6 +ibcbI/WN2IVfuNNtwLxB2lpec7xtJrULRn73vQ4uQ1SXuw58kcLa9PYCWZbGE7/r +iHDS64dHQD+MmVxWF9X8U3u/uSo8w/EdsGW5yHYkERpaqqH/zsLXPBg4LpNjoBzH +Z6L/anbTkBSvIhodBw== +-----END CERTIFICATE----- diff --git a/vio/cert.key b/vio/cert.key new file mode 100644 index 0000000..bc35b99 --- /dev/null +++ b/vio/cert.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEA8KssZedsoSu9IbeK9s2WBdvz0yCUvcDw60Fi61OGhoY1plxn +VxwGD9njEnFYQmjI0YkA7MB0IosKVpJJMfvuD8W4sJ6izw9akUHrX5x2Mb+KA/rl +uRWjBr1RuL/dsTlpHXhGMg8+bYpYyzPL/h4oSCPtxv3hCMwaf6qlNjU7JAIy2lLG +snpllsBrk1HVRC6TIdTHUVkpB/dct6dWBH5pKWGgIiJKvV9ZH0ryexIOPjUaOa3f +WtXhTAoUAfBGmL/iR7kfF/yhNTcP7qvpMl4NlYMlclBvKKvrHLHgTfK9qhl/teg8 +krb3n7087A1kyTCDrjXhS3QQ/O5QLOAzCNAI0QIDAQABAoIBAQC+a9GPN5Ld2wuk +d+L98CB5tlSvgiHuGZEFsxCffdD884fTf11MsSGivRVLbF8W/G2YTLxslsHM6xJc ++RXs9Jah6CF/raTIDC/uqqefWN6z8gczqvrEfPgmxvi4Iyc3qGMhLB7uUN1mMoab +EPqgsB/TJIpoXkwFd+inhs99mpSWoZXVKYw8b8omKwXbJO0yF/1lwn+UoUe+AT2A +odxxORS5SHut83GUhxCL4mFOU+RvuRCLGWrqT2JZEwffw6WtMiLk0hK9njKVT8EO +LcLy4SQD6R5YNRpgeQuHHSsHjFmmncjizNzBkhDwOAtk1vvo0yROWLfR+Uw+nscf +0gqgiFN5AoGBAP2YSv8OB/rULH+fMgwoux15UBZCqFrbyDPo8sJuKro2GdYoPtCh +Iq0g6xIUOS2K1VOIwNHr/gnOQgtoQJiDCgQKM06yLaNPgQSykjJF90DvEzGBzRgm +sUZPs8jBs480m6k3JHe0bArUlK/ddLBB9F+fajqUotgwkvD/gZioH7EnAoGBAPLz +fyNj+Gwh+7nDjPqmOPWa7rDiSx9R1BXPjDyGHcg8SrJvRgfM8lN9SevK7si6kxvu +dc47TM3w52r/3Q2hUW48eKeC8RXVgaQzgZKBY1bR6pC/90arJqveojwO0m8/HnBd +5VUfn8JBabhyxmXVm8sbR+nDo06o0Nex3wfEfUFHAoGBAP0hbBLFZa+45CYLuQAs +FAJqmkduB/CRm3g9WTw8jUfMQuPizjif7yYTSrGEIELWZvP3+EhSIQSWrpQGXxwd +CP1ZVTeDYUy3SlhvCsFF13Uobucm4prt3FwLqLCGsP4MDCjPUwZtwL7azQPysMxT +OWPNk1KgFSBo8/O9hxXjE6dXAoGBAMgDEs5OBTzwlU6P4UaRBh+dF5jkFDiKo3H5 +VliViXtJt61C0oKlhXKamPrYLNFwWKAMJ0xLoaWCCOMcFh6cim+YtTQjJtt01LAb +/zZf8yqM0vGsOKUjTkj8ls+e3Dvd2O9lPeJgkKPaOnExfIhl3UbPBNs8xvuBG74X +n6fDaeMNAoGBAMi08oqjILp7EuVhVjrGgdo3Gxl2Q4Us+OkLYp7vVsWEegsjhtDk +erYtukArSyQWYdJZ/HJP7QVu/bGUO2F2SOmk/Cd0QjrPnc0CQlONbqk+skgXOHOr +8cRFN0XIiX89YQK34ovXF8xGN5DcgUcRMCpSh02Mor4Exh6fwOKr3Am0 +-----END RSA PRIVATE KEY----- diff --git a/vio/docker/Dockerfile b/vio/docker/Dockerfile index 0330232..b035fc6 100644 --- a/vio/docker/Dockerfile +++ b/vio/docker/Dockerfile @@ -15,7 +15,7 @@ EXPOSE 9004 RUN groupadd -r onap && useradd -r -g onap onap RUN apt-get update && \ - apt-get install -y unzip wget curl gcc && \ + apt-get install -y unzip wget curl gcc libssl-dev && \ cd /opt/ && \ wget -q -O multicloud-vio.zip 'https://nexus.onap.org/service/local/artifact/maven/redirect?r=snapshots&g=org.onap.multicloud.openstack.vmware&a=multicloud-openstack-vmware&v=1.3.0-SNAPSHOT&e=zip' && \ unzip multicloud-vio.zip && \ @@ -32,7 +32,12 @@ then python multivimbroker/scripts/api.py else # nohup python manage.py runserver 0.0.0.0:9004 2>&1 & - nohup uwsgi --http :9004 --module vio.wsgi --master --processes 4 & + if [ ${SSL_ENABLED} = "true" ]; then + nohup uwsgi --https :9004,/opt/vio/cert.crt,/opt/vio/cert.key --module vio.wsgi --master --processes 4 & + + else + nohup uwsgi --http :9004 --module vio.wsgi --master --processes 4 & + fi nohup python -m vio.event_listener.server 2>&1 & while [ ! -f $logDir/vio.log ]; do diff --git a/vio/vio/heatbridge.py b/vio/vio/heatbridge.py new file mode 100644 index 0000000..325d20c --- /dev/null +++ b/vio/vio/heatbridge.py @@ -0,0 +1,59 @@ +# Copyright (c) 2019 VMware, Inc. +# +# 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. + + +# from vio.pub.msapi import extsys +from vio.pub.vim.vimapi.heat import OperateStack +from vio.pub.vim.vimapi.nova import OperateServers + +import logging + +logger = logging.getLogger(__name__) + + +def heat_bridge(vim_info, stack_id): + ret = { + "servers": [] + } + stack_op = OperateStack.OperateStack(vim_info) + server_op = OperateServers.OperateServers() + data = {'vimid': vim_info['vimId'], + 'vimName': vim_info['name'], + 'username': vim_info['userName'], + 'password': vim_info['password'], + 'url': vim_info['url']} + resources = stack_op.get_stack_resources(stack_id) + for res in resources: + if res.resource_type != "OS::Nova::Server": + continue + if not res.status.endswith("COMPLETE"): + continue + instance = server_op.get_server(data, None, res.physical_resource_id) + if instance is None: + logger.info("can not find server %s" % res.physical_resource_id) + continue + for link in instance.links: + if link['rel'] == "self": + slink = link['rel'] + break + ret['servers'].append({ + "name": instance.name, + "id": instance.id, + "status": instance.status, + "link": slink, + }) + return ret + +# if __name__ == "__main__": +# import ipdb; ipdb.set_trace() +# vim_info = extsys.get_vim_by_id("vmware_nova2") +# datas = heat_bridge(vim_info, "test") diff --git a/vio/vio/pub/vim/drivers/vimsdk/compute.py b/vio/vio/pub/vim/drivers/vimsdk/compute.py index e415573..9dccd2a 100644 --- a/vio/vio/pub/vim/drivers/vimsdk/compute.py +++ b/vio/vio/pub/vim/drivers/vimsdk/compute.py @@ -142,3 +142,7 @@ class ComputeClient(base.DriverBase): @sdk.translate_exception def list_hypervisors(self, **query): return self.conn.compute.hypervisors(**query) + + @sdk.translate_exception + def availability_zones(self, **query): + return self.conn.compute.availability_zones(**query) diff --git a/vio/vio/pub/vim/vimapi/nova/OperateNova.py b/vio/vio/pub/vim/vimapi/nova/OperateNova.py index 262da57..76dae71 100644 --- a/vio/vio/pub/vim/vimapi/nova/OperateNova.py +++ b/vio/vio/pub/vim/vimapi/nova/OperateNova.py @@ -37,3 +37,9 @@ class OperateNova(baseclient): compute = self.compute(param) func = getattr(compute, op) return func(**kwargs) + + +class OperateAZ(OperateNova): + + def list_availability_zones(self, data, **kwargs): + return self.request('availability_zones', data, **kwargs) diff --git a/vio/vio/swagger/views/capacity/views.py b/vio/vio/swagger/views/capacity/views.py index f679931..5cbd38e 100644 --- a/vio/vio/swagger/views/capacity/views.py +++ b/vio/vio/swagger/views/capacity/views.py @@ -21,6 +21,7 @@ from vio.pub.exceptions import VimDriverVioException from vio.pub.msapi import extsys from vio.pub.vim.vimapi.nova import OperateHypervisor from vio.pub.vim.vimapi.nova import OperateLimits +from vio.pub.vim.vimapi.nova import OperateNova from cinderclient import client @@ -69,16 +70,16 @@ class CapacityCheck(APIView): return False return True - def post(self, request, vimid): + def _post_handler(self, request, vimid): try: requirement = json.loads(request.body) except ValueError as ex: - return Response(data={'error': str(ex)}, - status=status.HTTP_400_BAD_REQUEST) + return {'error': str(ex), + "status_code": status.HTTP_400_BAD_REQUEST} try: vim_info = extsys.get_vim_by_id(vimid) except VimDriverVioException as e: - return Response(data={'error': str(e)}, status=e.status_code) + return {'error': str(e), "status_code": e.status_code} auth_info = { "username": vim_info['userName'], "password": vim_info['password'], @@ -92,38 +93,86 @@ class CapacityCheck(APIView): nova_limits = servers_op.get_limits(auth_info, None) except Exception as e: logger.exception("get nova limits error %(e)s", {"e": e}) - return Response(data={'error': str(e)}, status=e.status_code) + return {'error': str(e), "status_code": e.status_code} if not self._check_nova_limits(nova_limits, requirement): - return Response( - data={'result': False}, status=status.HTTP_200_OK) + return {'result': False, "status_code": status.HTTP_200_OK} # check cinder limits cinder = client.Client( - "2", auth_info['username'], auth_info['password'], + "3", auth_info['username'], auth_info['password'], auth_info['project_name'], auth_info['url'], insecure=True) try: limits = cinder.limits.get().to_dict() except Exception as e: logger.exception("get cinder limits error %(e)s", {"e": e}) - return Response(data={'error': str(e)}, status=e.status_code) + return {'error': str(e), "status_code": e.status_code} if not self._check_cinder_limits(limits, requirement): - return Response( - data={'result': False}, status=status.HTTP_200_OK) + return {'result': False, "status_code": status.HTTP_200_OK} + # Get Availability zones info + nova_op = OperateNova.OperateAZ() + try: + azs = nova_op.list_availability_zones(auth_info, details=True) + except Exception as e: + logger.exception("get availability_zones error %(e)s", {"e": e}) + return {'error': str(e), "status_code": e.status_code} + availability_zones = [] + for az in azs: + if az.name == "internal": + continue + availability_zones.append({ + "availability-zone-name": az.name, + "hosts": az.hosts, + "vCPUTotal": 0, + "vCPUAvail": 0, + "MemoryTotal": 0, + "MemoryAvail": 0, + "StorageTotal": 0, + "StorageAvail": 0, + }) # check hypervisor resources hypervisor_op = OperateHypervisor.OperateHypervisor() try: hypervisors = hypervisor_op.list_hypervisors(auth_info) except Exception as e: logger.exception("get hypervisors error %(e)s", {"e": e}) - return Response(data={'error': str(e)}, status=e.status_code) + return {'error': str(e), "status_code": e.status_code} + ret = {'result': False, "status_code": status.HTTP_200_OK} + # import ipdb; ipdb.set_trace() for hypervisor in hypervisors: + if hypervisor.status != "enabled": + continue hyper = hypervisor_op.get_hypervisor(auth_info, hypervisor.id) - if self._check_capacity(hyper.to_dict(), requirement): - return Response(data={'result': True}, - status=status.HTTP_200_OK) - return Response(data={'result': False}, status=status.HTTP_200_OK) + hyper_dict = hyper.to_dict() + for az in availability_zones: + if az['hosts'].get(hyper_dict["service_details"]['host']): + az['vCPUTotal'] += hyper_dict["vcpus"] + az['vCPUAvail'] += hyper_dict["vcpus"] - hyper_dict[ + "vcpus_used"] + az['MemoryTotal'] += hyper_dict["memory_size"] + az['MemoryAvail'] += hyper_dict["memory_free"] + az['StorageTotal'] += hyper_dict["local_disk_size"] + az['StorageAvail'] += hyper_dict["local_disk_free"] + if self._check_capacity(hyper_dict, requirement): + ret["result"] = True + if ret["result"]: + for az in availability_zones: + del az["hosts"] + ret["AZs"] = availability_zones + return ret + + def post(self, request, vimid): + ret = self._post_handler(request, vimid) + status_code = ret["status_code"] + del ret["status_code"] + if ret.get("AZs"): + del ret["AZs"] + return Response(data=ret, status=status_code) class CapacityCheckV1(CapacityCheck): def post(self, request, cloud_owner, cloud_region): - return super(CapacityCheckV1, self).post( - request, cloud_owner + "_" + cloud_region) + # import ipdb; ipdb.set_trace() + vimid = cloud_owner + "_" + cloud_region + ret = self._post_handler(request, vimid) + status_code = ret["status_code"] + del ret["status_code"] + return Response(data=ret, status=status_code) diff --git a/vio/vio/tests/test_capacity_view.py b/vio/vio/tests/test_capacity_view.py index d27efba..3079bac 100644 --- a/vio/vio/tests/test_capacity_view.py +++ b/vio/vio/tests/test_capacity_view.py @@ -18,6 +18,7 @@ from rest_framework import status from vio.pub.msapi import extsys from vio.pub.vim.vimapi.nova import OperateHypervisor from vio.pub.vim.vimapi.nova import OperateLimits +from vio.pub.vim.vimapi.nova import OperateNova from vio.swagger.views.capacity.views import CapacityCheck from cinderclient import client @@ -32,12 +33,13 @@ class CapacityCheckTest(unittest.TestCase): def setUp(self): self.view = CapacityCheck() + @mock.patch.object(OperateNova, "OperateAZ") @mock.patch.object(OperateHypervisor, "OperateHypervisor") @mock.patch.object(OperateLimits, "OperateLimits") @mock.patch.object(client, "Client") @mock.patch.object(extsys, "get_vim_by_id") def test_check_capacity_success(self, mock_get_vim, mock_cinder, - mock_limit, mock_hypervisor): + mock_limit, mock_hypervisor, mock_az): mock_get_vim.return_value = VIM_INFO req = mock.Mock() req.body = """{ @@ -63,11 +65,17 @@ class CapacityCheckTest(unittest.TestCase): cclient.limits.get.return_value = climits mock_cinder.return_value = cclient + nazs = [mock.Mock(name="nova", hosts={"compute01": {}})] + nclient = mock.Mock() + nclient.list_availability_zones.return_value = nazs + mock_az.return_value = nclient + ophypervisor = mock.Mock() ophypervisor.list_hypervisors.return_value = [ - mock.Mock(id="compute01")] + mock.Mock(id="compute01", status="enabled")] hyper = mock.Mock() hyper.to_dict.return_value = { + "service_details": {"host": "compute01"}, "vcpus": 20, "vcpus_used": 1, "memory_size": 128*1024, |