From 9c5468b5c14730b2e72fac736115eb2184a402c6 Mon Sep 17 00:00:00 2001 From: "wu.zhihui" Date: Sat, 8 Oct 2016 16:16:33 +0800 Subject: code refactor: create_zones.py 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 --- func/create_zones.py | 108 ++++++++++++++------------------------------- func/spawn_vm.py | 9 ++-- tests/create_zones_test.py | 58 ++++++++++++++++-------- tests/spawn_vm_test.py | 2 +- 4 files changed, 78 insertions(+), 99 deletions(-) diff --git a/func/create_zones.py b/func/create_zones.py index e715dfd4..30b6ef57 100644 --- a/func/create_zones.py +++ b/func/create_zones.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2015 Dell Inc and others. +# Copyright (c) 2016 Dell Inc, ZTE and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -10,14 +10,15 @@ from keystoneclient.auth.identity import v2 from keystoneclient import session from novaclient import client import os -import re -from collections import defaultdict +import random +from utils import logger_utils +logger = logger_utils.QtipLogger('create_zones').get -class create_zones: + +class AvailabilityZone: def __init__(self): - print 'Creating Zones' self._keystone_client = None self._nova_client = None @@ -49,82 +50,37 @@ class create_zones: self._nova_client = client.Client('2', session=keystone) return self._nova_client - @staticmethod - def check_aggregate(nova, agg_name): - list1 = nova.aggregates.list() - agg_name_exist = False - for x in list1: - if x.name == agg_name: - agg_name_exist = True - return agg_name_exist - - @staticmethod - def get_aggregate_id(nova, agg_name): - list1 = nova.aggregates.list() - for x in list1: - if x.name == agg_name: - agg_id = x.id - return agg_id - - @staticmethod - def check_host_added_to_aggregate(nova, agg_id, hostname): - host_added = False - list1 = nova.aggregates.get_details(agg_id) - - nme = str(list1.hosts) - if hostname in nme: - host_added = True - return host_added - - @staticmethod - def del_agg(nova, id, host): - - nova.aggregates.remove_host(id, host) - nova.aggregates.delete(id) - - @staticmethod - def get_compute_num(compute_name): - - num = re.findall(r'\d+', compute_name) - return int(num[0]) - 1 - - def test(self): - nova = self._get_nova_client() - hyper_list = nova.hypervisors.list() - return hyper_list - - def create_agg(self, d): + def clean_all_aggregates(self): + logger.info("clean all aggregates") nova = self._get_nova_client() - hyper_list = nova.hypervisors.list() - host_a = [] - zone_machine = defaultdict(list) - - for x in range(len(hyper_list)): + agg_list = nova.aggregates.list() - host_a.append(hyper_list[x].service['host']) - host_a[x] = str(host_a[x]) + for agg in agg_list: + agg_info = nova.aggregates.get_details(agg.id) + agg_hosts = agg_info.hosts + if len(agg_hosts): + for host in agg_hosts: + nova.aggregates.remove_host(agg.id, host) + nova.aggregates.delete(agg.id) - host_a.sort() - for k in d: + def create_aggs(self, args): + azone_list = list(set(args)) + azone_list.sort() - zone_machine[k].append(' ') + nova = self._get_nova_client() + hyper_list = nova.hypervisors.list() - for x in range(len(zone_machine)): - compute_index = self.get_compute_num(d[x]) - if compute_index > len(hyper_list): - print '\n The specified compute node doesnt exist. using compute 1' - compute_index = 1 - if not self.check_aggregate(nova, host_a[compute_index]): - agg_id_a = nova.aggregates.create(host_a[compute_index], d[x]) - nova.aggregates.add_host(aggregate=agg_id_a, host=host_a[compute_index]) + if len(azone_list) > len(hyper_list): + logger.error("required available zones > compute nodes") + return None - else: - id1 = self.get_aggregate_id(nova, host_a[compute_index]) - self.del_agg(nova, id1, host_a[compute_index]) - nova.aggregates.create(host_a[compute_index], d[x]) - id1 = self.get_aggregate_id(nova, host_a[compute_index]) + compute_nodes = map(lambda x: x.service['host'], hyper_list) + sample_nodes = random.sample(compute_nodes, len(azone_list)) + sample_nodes.sort() - if not self.check_host_added_to_aggregate( - nova, id1, host_a[compute_index]): + for index, item in enumerate(azone_list): + logger.info("create aggregates: %s" % str(item)) + agg_id = nova.aggregates.create(item, item) - nova.aggregates.add_host(aggregate=id1, host=host_a[compute_index]) + logger.info("add host: %s" % sample_nodes[index]) + nova.aggregates.add_host(aggregate=agg_id, host=sample_nodes[index]) diff --git a/func/spawn_vm.py b/func/spawn_vm.py index b467ab1f..5e2c1a70 100644 --- a/func/spawn_vm.py +++ b/func/spawn_vm.py @@ -16,7 +16,7 @@ import heatclient.client import keystoneclient from novaclient import client import time -from func.create_zones import create_zones +from func.create_zones import AvailabilityZone class SpawnVM(Env_setup): @@ -25,6 +25,7 @@ class SpawnVM(Env_setup): def __init__(self, vm_info): print 'SpawnVM Class initiated' + print 'vm_info: %s' % vm_info vm_role_ip_dict = vm_info.copy() print 'Generating Heat Template\n' self._keystone_client = None @@ -32,8 +33,10 @@ class SpawnVM(Env_setup): self._glance_client = None self._nova_client = None self. _get_nova_client() - azoneobj = create_zones() - azoneobj.create_agg(vm_info['availability_zone']) + self.azone = AvailabilityZone() + # TODO: it should clean up aggregates and stack after test case finished. + self.azone.clean_all_aggregates() + self.azone.create_agg(vm_info['availability_zone']) installer = self.get_installer_type() self.Heat_template1 = self.heat_template_vm(vm_info, installer) self.create_stack(vm_role_ip_dict, self.Heat_template1) diff --git a/tests/create_zones_test.py b/tests/create_zones_test.py index e431a907..39e71c17 100644 --- a/tests/create_zones_test.py +++ b/tests/create_zones_test.py @@ -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: diff --git a/tests/spawn_vm_test.py b/tests/spawn_vm_test.py index 0ec5c902..7890abd1 100644 --- a/tests/spawn_vm_test.py +++ b/tests/spawn_vm_test.py @@ -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) -- cgit 1.2.3-korg