code refactor: create_zones.py 31/22831/4
authorwu.zhihui <wu.zhihui1@zte.com.cn>
Sat, 8 Oct 2016 08:16:33 +0000 (16:16 +0800)
committerwu.zhihui <wu.zhihui1@zte.com.cn>
Sun, 9 Oct 2016 01:29:03 +0000 (09:29 +0800)
1. simply the process of creating aggregates in create_zones.py.
2. before creating aggregates, it will clean all aggregates firstly.

TODO:
It should clean up the created aggregates. It needs a big structure
modification in args_handler.py. Let's do it step by step.

Change-Id: I31e09e917ba83d4676f7f95d9f5186bce8d2a449
Signed-off-by: wu.zhihui <wu.zhihui1@zte.com.cn>
func/create_zones.py
func/spawn_vm.py
tests/create_zones_test.py
tests/spawn_vm_test.py

index e715dfd..30b6ef5 100644 (file)
@@ -1,5 +1,5 @@
 ##############################################################################\r
-# Copyright (c) 2015 Dell Inc  and others.\r
+# Copyright (c) 2016 Dell Inc, ZTE and others.\r
 #\r
 # All rights reserved. This program and the accompanying materials\r
 # are made available under the terms of the Apache License, Version 2.0\r
@@ -10,14 +10,15 @@ from keystoneclient.auth.identity import v2
 from keystoneclient import session\r
 from novaclient import client\r
 import os\r
-import re\r
-from collections import defaultdict\r
+import random\r
+from utils import logger_utils\r
 \r
+logger = logger_utils.QtipLogger('create_zones').get\r
 \r
-class create_zones:\r
+\r
+class AvailabilityZone:\r
 \r
     def __init__(self):\r
-        print 'Creating Zones'\r
         self._keystone_client = None\r
         self._nova_client = None\r
 \r
@@ -49,82 +50,37 @@ class create_zones:
             self._nova_client = client.Client('2', session=keystone)\r
         return self._nova_client\r
 \r
-    @staticmethod\r
-    def check_aggregate(nova, agg_name):\r
-        list1 = nova.aggregates.list()\r
-        agg_name_exist = False\r
-        for x in list1:\r
-            if x.name == agg_name:\r
-                agg_name_exist = True\r
-        return agg_name_exist\r
-\r
-    @staticmethod\r
-    def get_aggregate_id(nova, agg_name):\r
-        list1 = nova.aggregates.list()\r
-        for x in list1:\r
-            if x.name == agg_name:\r
-                agg_id = x.id\r
-                return agg_id\r
-\r
-    @staticmethod\r
-    def check_host_added_to_aggregate(nova, agg_id, hostname):\r
-        host_added = False\r
-        list1 = nova.aggregates.get_details(agg_id)\r
-\r
-        nme = str(list1.hosts)\r
-        if hostname in nme:\r
-            host_added = True\r
-        return host_added\r
-\r
-    @staticmethod\r
-    def del_agg(nova, id, host):\r
-\r
-        nova.aggregates.remove_host(id, host)\r
-        nova.aggregates.delete(id)\r
-\r
-    @staticmethod\r
-    def get_compute_num(compute_name):\r
-\r
-        num = re.findall(r'\d+', compute_name)\r
-        return int(num[0]) - 1\r
-\r
-    def test(self):\r
-        nova = self._get_nova_client()\r
-        hyper_list = nova.hypervisors.list()\r
-        return hyper_list\r
-\r
-    def create_agg(self, d):\r
+    def clean_all_aggregates(self):\r
+        logger.info("clean all aggregates")\r
         nova = self._get_nova_client()\r
-        hyper_list = nova.hypervisors.list()\r
-        host_a = []\r
-        zone_machine = defaultdict(list)\r
-\r
-        for x in range(len(hyper_list)):\r
+        agg_list = nova.aggregates.list()\r
 \r
-            host_a.append(hyper_list[x].service['host'])\r
-            host_a[x] = str(host_a[x])\r
+        for agg in agg_list:\r
+            agg_info = nova.aggregates.get_details(agg.id)\r
+            agg_hosts = agg_info.hosts\r
+            if len(agg_hosts):\r
+                for host in agg_hosts:\r
+                    nova.aggregates.remove_host(agg.id, host)\r
+            nova.aggregates.delete(agg.id)\r
 \r
-        host_a.sort()\r
-        for k in d:\r
+    def create_aggs(self, args):\r
+        azone_list = list(set(args))\r
+        azone_list.sort()\r
 \r
-            zone_machine[k].append(' ')\r
+        nova = self._get_nova_client()\r
+        hyper_list = nova.hypervisors.list()\r
 \r
-        for x in range(len(zone_machine)):\r
-            compute_index = self.get_compute_num(d[x])\r
-            if compute_index > len(hyper_list):\r
-                print '\n The specified compute node doesnt exist. using compute 1'\r
-                compute_index = 1\r
-            if not self.check_aggregate(nova, host_a[compute_index]):\r
-                agg_id_a = nova.aggregates.create(host_a[compute_index], d[x])\r
-                nova.aggregates.add_host(aggregate=agg_id_a, host=host_a[compute_index])\r
+        if len(azone_list) > len(hyper_list):\r
+            logger.error("required available zones > compute nodes")\r
+            return None\r
 \r
-            else:\r
-                id1 = self.get_aggregate_id(nova, host_a[compute_index])\r
-                self.del_agg(nova, id1, host_a[compute_index])\r
-                nova.aggregates.create(host_a[compute_index], d[x])\r
-                id1 = self.get_aggregate_id(nova, host_a[compute_index])\r
+        compute_nodes = map(lambda x: x.service['host'], hyper_list)\r
+        sample_nodes = random.sample(compute_nodes, len(azone_list))\r
+        sample_nodes.sort()\r
 \r
-                if not self.check_host_added_to_aggregate(\r
-                        nova, id1, host_a[compute_index]):\r
+        for index, item in enumerate(azone_list):\r
+            logger.info("create aggregates: %s" % str(item))\r
+            agg_id = nova.aggregates.create(item, item)\r
 \r
-                    nova.aggregates.add_host(aggregate=id1, host=host_a[compute_index])\r
+            logger.info("add host: %s" % sample_nodes[index])\r
+            nova.aggregates.add_host(aggregate=agg_id, host=sample_nodes[index])\r
index b467ab1..5e2c1a7 100644 (file)
@@ -16,7 +16,7 @@ import heatclient.client
 import keystoneclient\r
 from novaclient import client\r
 import time\r
-from func.create_zones import create_zones\r
+from func.create_zones import AvailabilityZone\r
 \r
 \r
 class SpawnVM(Env_setup):\r
@@ -25,6 +25,7 @@ class SpawnVM(Env_setup):
 \r
     def __init__(self, vm_info):\r
         print 'SpawnVM Class initiated'\r
+        print 'vm_info: %s' % vm_info\r
         vm_role_ip_dict = vm_info.copy()\r
         print 'Generating Heat Template\n'\r
         self._keystone_client = None\r
@@ -32,8 +33,10 @@ class SpawnVM(Env_setup):
         self._glance_client = None\r
         self._nova_client = None\r
         self. _get_nova_client()\r
-        azoneobj = create_zones()\r
-        azoneobj.create_agg(vm_info['availability_zone'])\r
+        self.azone = AvailabilityZone()\r
+        # TODO: it should clean up aggregates and stack after test case finished.\r
+        self.azone.clean_all_aggregates()\r
+        self.azone.create_agg(vm_info['availability_zone'])\r
         installer = self.get_installer_type()\r
         self.Heat_template1 = self.heat_template_vm(vm_info, installer)\r
         self.create_stack(vm_role_ip_dict, self.Heat_template1)\r
index e431a90..39e71c1 100644 (file)
@@ -2,7 +2,7 @@ import pytest
 import mock
 from mock import Mock, MagicMock
 import os
-from func.create_zones import create_zones
+from func.create_zones import AvailabilityZone
 
 return_list = []
 
@@ -22,7 +22,7 @@ class HyperMock(MagicMock):
 
 class AggMock(MagicMock):
     def get_details(self, agg_id):
-        print "get_detail:{0}".format(agg_id)
+        print "get_details:{0}".format(agg_id)
         return Mock(hosts=[])
 
     def create(self, host, agg):
@@ -41,6 +41,7 @@ class AggMock(MagicMock):
         pass
 
     def remove_host(self, agg_id, host):
+        print "remove_host:{0}:{1}".format(agg_id, host)
         pass
 
 
@@ -51,29 +52,48 @@ class NovaMock(MagicMock):
 
 class TestClass:
     @pytest.mark.parametrize("test_input, expected", [
-        ([[], ['compute1', 'compute2']],
-         ['create:10.20.0.4:compute1',
+        (['compute1', 'compute2'],
+         ['create:compute1:compute1',
           'add_host:compute1:10.20.0.4',
-          'create:10.20.0.5:compute2',
+          'create:compute2:compute2',
           'add_host:compute2:10.20.0.5']),
-        ([[get_agg_mock('10.20.0.4'), get_agg_mock('10.20.0.5')], ['compute1', 'compute2']],
-         ['delete:10.20.0.4',
-          'create:10.20.0.4:compute1',
-          'get_detail:10.20.0.4',
-          'add_host:10.20.0.4:10.20.0.4',
-          'delete:10.20.0.5',
-          'create:10.20.0.5:compute2',
-          'get_detail:10.20.0.5',
-          'add_host:10.20.0.5:10.20.0.5']),
-        ([[], ['compute1', 'compute5']],
-         ['The specified compute node doesnt exist. using compute 1'])
+        (['compute1', 'compute1'],
+         ['create:compute1:compute1',
+          'add_host:compute1:10.20.0.4']),
     ])
     @mock.patch('func.create_zones.client', autospec=True)
     @mock.patch('func.create_zones.v2', autospec=True)
     @mock.patch('func.create_zones.session')
     def test_create_zones_success(self, mock_keystone_session, mock_keystone_v2, mock_nova_client, test_input, expected, capfd):
+        nova_obj = NovaMock()
+        mock_nova_client.Client.return_value = nova_obj()
+        k = mock.patch.dict(os.environ, {'OS_AUTH_URL': 'http://172.10.0.5:5000',
+                                         'OS_USERNAME': 'admin',
+                                         'OS_PASSWORD': 'admin',
+                                         'OS_TENANT_NAME': 'admin'})
+        k.start()
+        azone = AvailabilityZone()
+        azone.create_agg(test_input)
+        k.stop()
+        resout, reserr = capfd.readouterr()
+        for x in expected:
+            assert x in resout
+
+    @pytest.mark.parametrize("test_input, expected", [
+        ([get_agg_mock('10.20.0.4'), get_agg_mock('10.20.0.5')],
+         ['get_details:10.20.0.4',
+          'delete:10.20.0.4',
+          'get_details:10.20.0.5',
+          'delete:10.20.0.5']),
+        ([],
+         []),
+    ])
+    @mock.patch('func.create_zones.client', autospec=True)
+    @mock.patch('func.create_zones.v2', autospec=True)
+    @mock.patch('func.create_zones.session')
+    def test_clean_all_aggregates(self, mock_keystone_session, mock_keystone_v2, mock_nova_client, test_input, expected, capfd):
         global return_list
-        return_list = test_input[0]
+        return_list = test_input
         nova_obj = NovaMock()
         mock_nova_client.Client.return_value = nova_obj()
         k = mock.patch.dict(os.environ, {'OS_AUTH_URL': 'http://172.10.0.5:5000',
@@ -81,8 +101,8 @@ class TestClass:
                                          'OS_PASSWORD': 'admin',
                                          'OS_TENANT_NAME': 'admin'})
         k.start()
-        create = create_zones()
-        create.create_agg(test_input[1])
+        azone = AvailabilityZone()
+        azone.clean_all_aggregates()
         k.stop()
         resout, reserr = capfd.readouterr()
         for x in expected:
index 0ec5c90..7890abd 100644 (file)
@@ -43,7 +43,7 @@ class TestClass:
          [('172.10.0.154', '')]),
     ])
     @mock.patch('func.spawn_vm.Env_setup')
-    @mock.patch('func.spawn_vm.create_zones')
+    @mock.patch('func.spawn_vm.AvailabilityZone')
     @mock.patch('func.spawn_vm.client', autospec=True)
     @mock.patch('func.spawn_vm.keystoneclient.v2_0', autospec=True)
     @mock.patch('func.spawn_vm.heatclient.client', autospec=True)