Handle locations for ad-hoc requests
Change-Id: I025b9afd6ebb1027019e2b9a35934b8af6ab092a
This commit is contained in:
parent
1e146b1499
commit
0dcfb240b2
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,3 +1,9 @@
|
|||||||
|
# MacOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# IDEA / IDE
|
||||||
|
.idea/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
@ -108,4 +114,3 @@ obj/
|
|||||||
[Rr]elease*/
|
[Rr]elease*/
|
||||||
_ReSharper*/
|
_ReSharper*/
|
||||||
[Tt]est[Rr]esult*
|
[Tt]est[Rr]esult*
|
||||||
.idea/*
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
[program:HAValet]
|
|
||||||
command=python /usr/local/lib/python2.7/dist-packages/valet/ha/ha_valet.py
|
|
||||||
autostart=true
|
|
||||||
autorestart=true
|
|
||||||
stderr_logfile=/var/log/HAValet.err.log
|
|
||||||
stdout_logfile=/var/log/HAValet.out.log
|
|
@ -1,15 +0,0 @@
|
|||||||
[program:cassandra]
|
|
||||||
command=/bin/bash -c '/opt/app/apache-cassandra-2.1.1/bin/cassandra -f'
|
|
||||||
autostart=true
|
|
||||||
autorestart=true
|
|
||||||
stopsignal=KILL
|
|
||||||
stderr_logfile=/var/log/cassandra.err.log
|
|
||||||
stdout_logfile=/var/log/cassandra.out.log
|
|
||||||
|
|
||||||
[program:Zookeeper]
|
|
||||||
command=/opt/app/zookeeper-3.4.6/bin/zkServer.sh start-foreground
|
|
||||||
autostart=true
|
|
||||||
autorestart=true
|
|
||||||
stopsignal=KILL
|
|
||||||
stderr_logfile=/var/log/zookeeper.err.log
|
|
||||||
stdout_logfile=/var/log/zookeeper.out.log
|
|
@ -48,8 +48,6 @@ class AppHandler(object):
|
|||||||
|
|
||||||
app_topology = AppTopology(self.resource, self.logger)
|
app_topology = AppTopology(self.resource, self.logger)
|
||||||
|
|
||||||
self.logger.debug("AppHandler: parse app")
|
|
||||||
|
|
||||||
stack_id = None
|
stack_id = None
|
||||||
if "stack_id" in _app.keys():
|
if "stack_id" in _app.keys():
|
||||||
stack_id = _app["stack_id"]
|
stack_id = _app["stack_id"]
|
||||||
@ -88,6 +86,11 @@ class AppHandler(object):
|
|||||||
else:
|
else:
|
||||||
app_id = app_topology.set_app_topology(_app)
|
app_id = app_topology.set_app_topology(_app)
|
||||||
|
|
||||||
|
if len(app_topology.candidate_list_map) > 0:
|
||||||
|
self.logger.debug("got ad-hoc placement: " + stack_id)
|
||||||
|
else:
|
||||||
|
self.logger.debug("got placement: " + stack_id)
|
||||||
|
|
||||||
if app_id is None:
|
if app_id is None:
|
||||||
self.logger.error(app_topology.status)
|
self.logger.error(app_topology.status)
|
||||||
self.status = app_topology.status
|
self.status = app_topology.status
|
||||||
@ -204,17 +207,9 @@ class AppHandler(object):
|
|||||||
_app_topology.candidate_list_map[vmk] = \
|
_app_topology.candidate_list_map[vmk] = \
|
||||||
_app["locations"]
|
_app["locations"]
|
||||||
|
|
||||||
self.logger.debug("AppHandler: re-requested vm = " +
|
|
||||||
vm["name"] + " in")
|
|
||||||
for hk in _app["locations"]:
|
|
||||||
self.logger.debug(" " + hk)
|
|
||||||
|
|
||||||
elif vmk in _app["exclusions"]:
|
elif vmk in _app["exclusions"]:
|
||||||
_app_topology.planned_vm_map[vmk] = vm["host"]
|
_app_topology.planned_vm_map[vmk] = vm["host"]
|
||||||
|
|
||||||
self.logger.debug("AppHandler: exception from "
|
|
||||||
"replan = " + vm["name"])
|
|
||||||
|
|
||||||
elif _action == "migrate":
|
elif _action == "migrate":
|
||||||
if vmk == _app["orchestration_id"]:
|
if vmk == _app["orchestration_id"]:
|
||||||
_app_topology.exclusion_list_map[vmk] = _app[
|
_app_topology.exclusion_list_map[vmk] = _app[
|
||||||
|
@ -67,6 +67,9 @@ class AppTopology(object):
|
|||||||
"""
|
"""
|
||||||
(vgroups, vms, volumes) = self.parser.set_topology(_app_graph)
|
(vgroups, vms, volumes) = self.parser.set_topology(_app_graph)
|
||||||
|
|
||||||
|
if len(self.parser.candidate_list_map) > 0:
|
||||||
|
self.candidate_list_map = self.parser.candidate_list_map
|
||||||
|
|
||||||
if len(vgroups) == 0 and len(vms) == 0 and len(volumes) == 0:
|
if len(vgroups) == 0 and len(vms) == 0 and len(volumes) == 0:
|
||||||
self.status = self.parser.status
|
self.status = self.parser.status
|
||||||
return None
|
return None
|
||||||
|
@ -48,6 +48,8 @@ class Parser(object):
|
|||||||
self.application_name = None
|
self.application_name = None
|
||||||
self.action = None # [create|update|ping]
|
self.action = None # [create|update|ping]
|
||||||
|
|
||||||
|
self.candidate_list_map = {}
|
||||||
|
|
||||||
self.status = "success"
|
self.status = "success"
|
||||||
|
|
||||||
def set_topology(self, _graph):
|
def set_topology(self, _graph):
|
||||||
@ -72,6 +74,11 @@ class Parser(object):
|
|||||||
else:
|
else:
|
||||||
self.action = "any"
|
self.action = "any"
|
||||||
|
|
||||||
|
if "locations" in _graph.keys() and len(_graph["locations"]) > 0:
|
||||||
|
if len(_graph["resources"]) == 1:
|
||||||
|
v_uuid = _graph["resources"].keys()[0]
|
||||||
|
self.candidate_list_map[v_uuid] = _graph["locations"]
|
||||||
|
|
||||||
return self._set_topology(_graph["resources"])
|
return self._set_topology(_graph["resources"])
|
||||||
|
|
||||||
def _set_topology(self, _elements):
|
def _set_topology(self, _elements):
|
||||||
@ -103,6 +110,10 @@ class Parser(object):
|
|||||||
# NOTE: do not allow to specify a certain host name
|
# NOTE: do not allow to specify a certain host name
|
||||||
vm.availability_zone = az.split(":")[0]
|
vm.availability_zone = az.split(":")[0]
|
||||||
|
|
||||||
|
if "locations" in r.keys():
|
||||||
|
if len(r["locations"]) > 0:
|
||||||
|
self.candidate_list_map[rk] = r["locations"]
|
||||||
|
|
||||||
vms[vm.uuid] = vm
|
vms[vm.uuid] = vm
|
||||||
|
|
||||||
self.logger.debug("vm = " + vm.uuid)
|
self.logger.debug("vm = " + vm.uuid)
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
# Version 2.0.2:
|
|
||||||
|
|
||||||
# Set database keyspace
|
|
||||||
db_keyspace=valet_test
|
|
||||||
db_request_table=placement_requests
|
|
||||||
db_response_table=placement_results
|
|
||||||
db_event_table=oslo_messages
|
|
||||||
db_resource_table=resource_status
|
|
||||||
db_resource_index_table=resource_log_index
|
|
||||||
db_app_index_table=app_log_index
|
|
||||||
db_app_table=app
|
|
||||||
db_uuid_table=uuid_map
|
|
||||||
|
|
||||||
#replication_factor=3
|
|
@ -1,84 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2014-2017 AT&T Intellectual Property
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
"""Configuration."""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
class Config(object):
|
|
||||||
"""Config Class.
|
|
||||||
|
|
||||||
This class consists of one function that reads client config options
|
|
||||||
from a file and sets the corresponding config variables of this class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Init Config class."""
|
|
||||||
self.mode = None
|
|
||||||
|
|
||||||
self.db_keyspace = None
|
|
||||||
self.db_request_table = None
|
|
||||||
self.db_response_table = None
|
|
||||||
self.db_event_table = None
|
|
||||||
self.db_resource_table = None
|
|
||||||
self.db_app_table = None
|
|
||||||
self.db_resource_index_table = None
|
|
||||||
self.db_app_index_table = None
|
|
||||||
self.db_uuid_table = None
|
|
||||||
|
|
||||||
def configure(self):
|
|
||||||
"""Read client config file for config options and return success."""
|
|
||||||
try:
|
|
||||||
f = open("./client.cfg", "r")
|
|
||||||
line = f.readline()
|
|
||||||
|
|
||||||
while line:
|
|
||||||
if line.startswith("#") or line.startswith(" ") or line == "\n":
|
|
||||||
line = f.readline()
|
|
||||||
continue
|
|
||||||
|
|
||||||
(rk, v) = line.split("=")
|
|
||||||
k = rk.strip()
|
|
||||||
|
|
||||||
if k == "db_keyspace":
|
|
||||||
self.db_keyspace = v.strip()
|
|
||||||
elif k == "db_request_table":
|
|
||||||
self.db_request_table = v.strip()
|
|
||||||
elif k == "db_response_table":
|
|
||||||
self.db_response_table = v.strip()
|
|
||||||
elif k == "db_event_table":
|
|
||||||
self.db_event_table = v.strip()
|
|
||||||
elif k == "db_resource_table":
|
|
||||||
self.db_resource_table = v.strip()
|
|
||||||
elif k == "db_app_table":
|
|
||||||
self.db_app_table = v.strip()
|
|
||||||
elif k == "db_resource_index_table":
|
|
||||||
self.db_resource_index_table = v.strip()
|
|
||||||
elif k == "db_app_index_table":
|
|
||||||
self.db_app_index_table = v.strip()
|
|
||||||
elif k == "db_uuid_table":
|
|
||||||
self.db_uuid_table = v.strip()
|
|
||||||
|
|
||||||
line = f.readline()
|
|
||||||
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
return "success"
|
|
||||||
|
|
||||||
except IOError as e:
|
|
||||||
return "I/O error({}): {}".format(e.errno, e.strerror)
|
|
||||||
except Exception:
|
|
||||||
return "Unexpected error: ", sys.exc_info()[0]
|
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import operator
|
import operator
|
||||||
|
import time
|
||||||
from valet.common.music import Music
|
from valet.common.music import Music
|
||||||
from valet.engine.optimizer.db_connect.event import Event
|
from valet.engine.optimizer.db_connect.event import Event
|
||||||
|
|
||||||
@ -175,12 +176,14 @@ class MusicHandler(object):
|
|||||||
"""
|
"""
|
||||||
event_list = []
|
event_list = []
|
||||||
|
|
||||||
|
ts = time.time()
|
||||||
events = {}
|
events = {}
|
||||||
try:
|
try:
|
||||||
events = self.music.read_all_rows(self.config.db_keyspace,
|
events = self.music.read_all_rows(self.config.db_keyspace,
|
||||||
self.config.db_event_table)
|
self.config.db_event_table)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error("DB:event: " + str(e))
|
self.logger.error("DB:event: " + str(e))
|
||||||
|
self.logger.debug("EVAL: the delay of getting events = " + str(time.time() - ts))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if len(events) > 0:
|
if len(events) > 0:
|
||||||
@ -330,6 +333,7 @@ class MusicHandler(object):
|
|||||||
if len(event_list) > 0:
|
if len(event_list) > 0:
|
||||||
event_list.sort(key=operator.attrgetter('event_id'))
|
event_list.sort(key=operator.attrgetter('event_id'))
|
||||||
|
|
||||||
|
self.logger.debug("EVAL: the delay of getting events = " + str(time.time() - ts))
|
||||||
return event_list
|
return event_list
|
||||||
|
|
||||||
def delete_event(self, _event_id):
|
def delete_event(self, _event_id):
|
||||||
@ -409,12 +413,14 @@ class MusicHandler(object):
|
|||||||
"""Return list of requests that consists of all rows in a db table."""
|
"""Return list of requests that consists of all rows in a db table."""
|
||||||
request_list = []
|
request_list = []
|
||||||
|
|
||||||
|
ts = time.time()
|
||||||
requests = {}
|
requests = {}
|
||||||
try:
|
try:
|
||||||
requests = self.music.read_all_rows(self.config.db_keyspace,
|
requests = self.music.read_all_rows(self.config.db_keyspace,
|
||||||
self.config.db_request_table)
|
self.config.db_request_table)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error("DB: while reading requests: " + str(e))
|
self.logger.error("DB: while reading requests: " + str(e))
|
||||||
|
self.logger.debug("EVAL: the delay of getting requests = " + str(time.time() - ts))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if len(requests) > 0:
|
if len(requests) > 0:
|
||||||
@ -428,6 +434,7 @@ class MusicHandler(object):
|
|||||||
for r in r_list:
|
for r in r_list:
|
||||||
request_list.append(r)
|
request_list.append(r)
|
||||||
|
|
||||||
|
self.logger.debug("EVAL: the delay of getting requests = " + str(time.time() - ts))
|
||||||
return request_list
|
return request_list
|
||||||
|
|
||||||
def put_result(self, _result):
|
def put_result(self, _result):
|
||||||
|
@ -49,8 +49,6 @@ class ConstraintSolver(object):
|
|||||||
|
|
||||||
"""When replanning."""
|
"""When replanning."""
|
||||||
if _n.node.host is not None and len(_n.node.host) > 0:
|
if _n.node.host is not None and len(_n.node.host) > 0:
|
||||||
self.logger.debug("ConstraintSolver: reconsider with given "
|
|
||||||
"candidates")
|
|
||||||
for hk in _n.node.host:
|
for hk in _n.node.host:
|
||||||
for ark, ar in _avail_resources.iteritems():
|
for ark, ar in _avail_resources.iteritems():
|
||||||
if hk == ark:
|
if hk == ark:
|
||||||
@ -275,10 +273,6 @@ class ConstraintSolver(object):
|
|||||||
if r not in conflict_list:
|
if r not in conflict_list:
|
||||||
conflict_list.append(r)
|
conflict_list.append(r)
|
||||||
|
|
||||||
debug_resource_name = r.get_resource_name(_level)
|
|
||||||
self.logger.debug("ConstraintSolver: exclusivity defined "
|
|
||||||
"in resource = " + debug_resource_name)
|
|
||||||
|
|
||||||
_candidate_list[:] = [c for c in _candidate_list
|
_candidate_list[:] = [c for c in _candidate_list
|
||||||
if c not in conflict_list]
|
if c not in conflict_list]
|
||||||
|
|
||||||
@ -330,10 +324,6 @@ class ConstraintSolver(object):
|
|||||||
if self.exist_group(_level, _exclusivity_id, "EX", r) is True:
|
if self.exist_group(_level, _exclusivity_id, "EX", r) is True:
|
||||||
if r not in candidate_list:
|
if r not in candidate_list:
|
||||||
candidate_list.append(r)
|
candidate_list.append(r)
|
||||||
else:
|
|
||||||
debug_resource_name = r.get_resource_name(_level)
|
|
||||||
self.logger.debug("ConstraintSolver: exclusivity not exist in "
|
|
||||||
"resource = " + debug_resource_name)
|
|
||||||
|
|
||||||
return candidate_list
|
return candidate_list
|
||||||
|
|
||||||
@ -344,10 +334,6 @@ class ConstraintSolver(object):
|
|||||||
if self.check_hibernated(_level, r) is True:
|
if self.check_hibernated(_level, r) is True:
|
||||||
if r not in candidate_list:
|
if r not in candidate_list:
|
||||||
candidate_list.append(r)
|
candidate_list.append(r)
|
||||||
else:
|
|
||||||
debug_resource_name = r.get_resource_name(_level)
|
|
||||||
self.logger.debug("ConstraintSolver: exclusivity not allowed "
|
|
||||||
"in resource = " + debug_resource_name)
|
|
||||||
|
|
||||||
return candidate_list
|
return candidate_list
|
||||||
|
|
||||||
|
@ -89,17 +89,11 @@ class AggregateInstanceExtraSpecsFilter(object):
|
|||||||
|
|
||||||
aggregate_vals = _metadata.get(key, None)
|
aggregate_vals = _metadata.get(key, None)
|
||||||
if not aggregate_vals:
|
if not aggregate_vals:
|
||||||
self.logger.debug("key (" + key + ") not exists in logical_"
|
|
||||||
"group (" + _lg_name + ") " +
|
|
||||||
" of host (" + _h_name + ")")
|
|
||||||
return False
|
return False
|
||||||
for aggregate_val in aggregate_vals:
|
for aggregate_val in aggregate_vals:
|
||||||
if openstack_utils.match(aggregate_val, req):
|
if openstack_utils.match(aggregate_val, req):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.logger.debug("key (" + key + ")'s value (" + req + ") not "
|
|
||||||
"exists in logical_group " + "(" + _lg_name +
|
|
||||||
") " + " of host (" + _h_name + ")")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -138,8 +132,6 @@ class AvailabilityZoneFilter(object):
|
|||||||
|
|
||||||
for azr in az_request_list:
|
for azr in az_request_list:
|
||||||
if azr not in availability_zone_list:
|
if azr not in availability_zone_list:
|
||||||
self.logger.debug("AZ (" + azr + ") not exists in host " + "(" +
|
|
||||||
_host.get_resource_name(_level) + ")")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -160,17 +152,9 @@ class RamFilter(object):
|
|||||||
# Do not allow an instance to overcommit against itself, only against
|
# Do not allow an instance to overcommit against itself, only against
|
||||||
# other instances.
|
# other instances.
|
||||||
if not total_ram >= requested_ram:
|
if not total_ram >= requested_ram:
|
||||||
self.logger.debug("requested mem (" + str(requested_ram) +
|
|
||||||
") more than total mem (" +
|
|
||||||
str(total_ram) + ") in host (" +
|
|
||||||
_host.get_resource_name(_level) + ")")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not usable_ram >= requested_ram:
|
if not usable_ram >= requested_ram:
|
||||||
self.logger.debug("requested mem (" + str(requested_ram) +
|
|
||||||
") more than avail mem (" +
|
|
||||||
str(usable_ram) + ") in host (" +
|
|
||||||
_host.get_resource_name(_level) + ")")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -192,17 +176,9 @@ class CoreFilter(object):
|
|||||||
# Do not allow an instance to overcommit against itself, only against
|
# Do not allow an instance to overcommit against itself, only against
|
||||||
# other instances.
|
# other instances.
|
||||||
if instance_vCPUs > vCPUs:
|
if instance_vCPUs > vCPUs:
|
||||||
self.logger.debug("requested vCPUs (" + str(instance_vCPUs) +
|
|
||||||
") more than total vCPUs (" +
|
|
||||||
str(vCPUs) + ") in host (" +
|
|
||||||
_host.get_resource_name(_level) + ")")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if avail_vCPUs < instance_vCPUs:
|
if avail_vCPUs < instance_vCPUs:
|
||||||
self.logger.debug("requested vCPUs (" + str(instance_vCPUs) +
|
|
||||||
") more than avail vCPUs (" +
|
|
||||||
str(avail_vCPUs) + ") in host (" +
|
|
||||||
_host.get_resource_name(_level) + ")")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -221,10 +197,6 @@ class DiskFilter(object):
|
|||||||
(_, usable_disk) = _host.get_local_disk(_level)
|
(_, usable_disk) = _host.get_local_disk(_level)
|
||||||
|
|
||||||
if not usable_disk >= requested_disk:
|
if not usable_disk >= requested_disk:
|
||||||
self.logger.debug("requested disk (" + str(requested_disk) +
|
|
||||||
") more than avail disk (" +
|
|
||||||
str(usable_disk) + ") in host (" +
|
|
||||||
_host.get_resource_name(_level) + ")")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -44,10 +44,12 @@ class Optimizer(object):
|
|||||||
|
|
||||||
start_ts = time.time()
|
start_ts = time.time()
|
||||||
|
|
||||||
if len(_app_topology.candidate_list_map) > 0:
|
if len(_app_topology.exclusion_list_map) > 0:
|
||||||
place_type = "replan"
|
|
||||||
elif len(_app_topology.exclusion_list_map) > 0:
|
|
||||||
place_type = "migration"
|
place_type = "migration"
|
||||||
|
else:
|
||||||
|
if (len(_app_topology.old_vm_map) > 0 or len(_app_topology.planned_vm_map) > 0) and \
|
||||||
|
len(_app_topology.candidate_list_map) > 0:
|
||||||
|
place_type = "replan"
|
||||||
else:
|
else:
|
||||||
place_type = "create"
|
place_type = "create"
|
||||||
|
|
||||||
@ -65,9 +67,6 @@ class Optimizer(object):
|
|||||||
if len(_app_topology.old_vm_map) > 0:
|
if len(_app_topology.old_vm_map) > 0:
|
||||||
uuid_map = self._delete_old_vms(_app_topology.old_vm_map)
|
uuid_map = self._delete_old_vms(_app_topology.old_vm_map)
|
||||||
self.resource.update_topology(store=False)
|
self.resource.update_topology(store=False)
|
||||||
|
|
||||||
self.logger.debug("Optimizer: remove old placements for "
|
|
||||||
"replan")
|
|
||||||
else:
|
else:
|
||||||
success = self.search.place_nodes(_app_topology, self.resource)
|
success = self.search.place_nodes(_app_topology, self.resource)
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ class Ostro(object):
|
|||||||
self.end_of_process = False
|
self.end_of_process = False
|
||||||
|
|
||||||
self.batch_store_trigger = 10 # sec
|
self.batch_store_trigger = 10 # sec
|
||||||
self.batch_events_count = 1
|
# self.batch_events_count = 1
|
||||||
|
|
||||||
'''
|
'''
|
||||||
def run_ostro(self):
|
def run_ostro(self):
|
||||||
@ -107,9 +107,12 @@ class Ostro(object):
|
|||||||
else:
|
else:
|
||||||
if self.resource.resource_updated is True and \
|
if self.resource.resource_updated is True and \
|
||||||
(time.time()-self.resource.curr_db_timestamp) >= self.batch_store_trigger:
|
(time.time()-self.resource.curr_db_timestamp) >= self.batch_store_trigger:
|
||||||
|
self.data_lock.acquire()
|
||||||
if self.resource.store_topology_updates() is False:
|
if self.resource.store_topology_updates() is False:
|
||||||
|
self.data_lock.release()
|
||||||
break
|
break
|
||||||
self.resource.resource_updated = False
|
self.resource.resource_updated = False
|
||||||
|
self.data_lock.release()
|
||||||
else:
|
else:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
@ -158,9 +161,12 @@ class Ostro(object):
|
|||||||
else:
|
else:
|
||||||
if self.resource.resource_updated is True and \
|
if self.resource.resource_updated is True and \
|
||||||
(time.time() - self.resource.curr_db_timestamp) >= self.batch_store_trigger:
|
(time.time() - self.resource.curr_db_timestamp) >= self.batch_store_trigger:
|
||||||
|
self.data_lock.acquire()
|
||||||
if self.resource.store_topology_updates() is False:
|
if self.resource.store_topology_updates() is False:
|
||||||
|
self.data_lock.release()
|
||||||
break
|
break
|
||||||
self.resource.resource_updated = False
|
self.resource.resource_updated = False
|
||||||
|
self.data_lock.release()
|
||||||
|
|
||||||
self.topology.end_of_process = True
|
self.topology.end_of_process = True
|
||||||
self.compute.end_of_process = True
|
self.compute.end_of_process = True
|
||||||
@ -281,7 +287,7 @@ class Ostro(object):
|
|||||||
self.logger.info("done app placement")
|
self.logger.info("done app placement")
|
||||||
|
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
self.logger.info("EVAL: total decision delay of request = " + str(end_time - start_time) + " sec")
|
self.logger.debug("EVAL: total decision delay of request = " + str(end_time - start_time))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -424,8 +430,6 @@ class Ostro(object):
|
|||||||
if self._set_flavors() is False:
|
if self._set_flavors() is False:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.resource.update_topology(store=False)
|
|
||||||
|
|
||||||
flavor = self.resource.get_flavor(_vm.flavor)
|
flavor = self.resource.get_flavor(_vm.flavor)
|
||||||
if flavor is None:
|
if flavor is None:
|
||||||
return False
|
return False
|
||||||
@ -449,10 +453,12 @@ class Ostro(object):
|
|||||||
"""
|
"""
|
||||||
self.data_lock.acquire()
|
self.data_lock.acquire()
|
||||||
|
|
||||||
|
event_handler_start_time = time.time()
|
||||||
|
|
||||||
resource_updated = False
|
resource_updated = False
|
||||||
|
|
||||||
events_count = 0
|
# events_count = 0
|
||||||
handled_event_list = []
|
# handled_event_list = []
|
||||||
for e in _event_list:
|
for e in _event_list:
|
||||||
if e.host is not None and e.host != "none":
|
if e.host is not None and e.host != "none":
|
||||||
if self._check_host(e.host) is False:
|
if self._check_host(e.host) is False:
|
||||||
@ -587,15 +593,15 @@ class Ostro(object):
|
|||||||
self.logger.warn("Ostro.handle_events: unknown event "
|
self.logger.warn("Ostro.handle_events: unknown event "
|
||||||
"method = " + e.method)
|
"method = " + e.method)
|
||||||
|
|
||||||
events_count += 1
|
# events_count += 1
|
||||||
handled_event_list.append(e)
|
# handled_event_list.append(e)
|
||||||
if events_count >= self.batch_events_count:
|
# if events_count >= self.batch_events_count:
|
||||||
break
|
# break
|
||||||
|
|
||||||
if resource_updated is True:
|
if resource_updated is True:
|
||||||
self.resource.update_topology(store=False)
|
self.resource.update_topology(store=False)
|
||||||
|
|
||||||
for e in handled_event_list:
|
for e in _event_list:
|
||||||
if self.db.delete_event(e.event_id) is False:
|
if self.db.delete_event(e.event_id) is False:
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
return False
|
return False
|
||||||
@ -606,6 +612,8 @@ class Ostro(object):
|
|||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
self.logger.debug("EVAL: total delay for event handling = " + str(time.time() - event_handler_start_time))
|
||||||
|
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -149,8 +149,6 @@ class Search(object):
|
|||||||
|
|
||||||
if len(self.app_topology.old_vm_map) > 0:
|
if len(self.app_topology.old_vm_map) > 0:
|
||||||
self._adjust_resources()
|
self._adjust_resources()
|
||||||
self.logger.debug("Search: adjust resources by deducting prior "
|
|
||||||
"placements")
|
|
||||||
|
|
||||||
self._compute_resource_weights()
|
self._compute_resource_weights()
|
||||||
|
|
||||||
@ -808,8 +806,6 @@ class Search(object):
|
|||||||
"""Already-planned vgroup."""
|
"""Already-planned vgroup."""
|
||||||
planned_host = None
|
planned_host = None
|
||||||
if _n.node in self.planned_placements.keys():
|
if _n.node in self.planned_placements.keys():
|
||||||
self.logger.debug("Search: already determined node = " +
|
|
||||||
_n.node.name)
|
|
||||||
copied_host = self.planned_placements[_n.node]
|
copied_host = self.planned_placements[_n.node]
|
||||||
if _level == "host":
|
if _level == "host":
|
||||||
planned_host = _avail_resources[copied_host.host_name]
|
planned_host = _avail_resources[copied_host.host_name]
|
||||||
|
@ -99,19 +99,11 @@ class ComputeManager(threading.Thread):
|
|||||||
"status update ---")
|
"status update ---")
|
||||||
|
|
||||||
triggered_host_updates = self.set_hosts()
|
triggered_host_updates = self.set_hosts()
|
||||||
|
if triggered_host_updates is not True:
|
||||||
|
self.logger.warn("fail to set hosts from nova")
|
||||||
triggered_flavor_updates = self.set_flavors()
|
triggered_flavor_updates = self.set_flavors()
|
||||||
|
if triggered_flavor_updates is not True:
|
||||||
if triggered_host_updates is True and triggered_flavor_updates is True:
|
self.logger.warn("fail to set flavor from nova")
|
||||||
self.data_lock.acquire()
|
|
||||||
update_status = self.resource.update_topology(store=False)
|
|
||||||
self.data_lock.release()
|
|
||||||
|
|
||||||
if update_status is False:
|
|
||||||
# TODO(GY): error in MUSIC. ignore?
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# TODO(GY): error handling, e.g., 3 times failure then stop Ostro?
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.logger.info("ComputeManager: --- done compute_nodes "
|
self.logger.info("ComputeManager: --- done compute_nodes "
|
||||||
"status update ---")
|
"status update ---")
|
||||||
@ -138,8 +130,11 @@ class ComputeManager(threading.Thread):
|
|||||||
self._compute_avail_host_resources(hosts)
|
self._compute_avail_host_resources(hosts)
|
||||||
|
|
||||||
self.data_lock.acquire()
|
self.data_lock.acquire()
|
||||||
self._check_logical_group_update(logical_groups)
|
lg_updated = self._check_logical_group_update(logical_groups)
|
||||||
self._check_host_update(hosts)
|
host_updated = self._check_host_update(hosts)
|
||||||
|
|
||||||
|
if lg_updated is True or host_updated is True:
|
||||||
|
self.resource.update_topology(store=False)
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -149,6 +144,8 @@ class ComputeManager(threading.Thread):
|
|||||||
self.resource.compute_avail_resources(hk, host)
|
self.resource.compute_avail_resources(hk, host)
|
||||||
|
|
||||||
def _check_logical_group_update(self, _logical_groups):
|
def _check_logical_group_update(self, _logical_groups):
|
||||||
|
updated = False
|
||||||
|
|
||||||
for lk in _logical_groups.keys():
|
for lk in _logical_groups.keys():
|
||||||
if lk not in self.resource.logical_groups.keys():
|
if lk not in self.resource.logical_groups.keys():
|
||||||
self.resource.logical_groups[lk] = deepcopy(_logical_groups[lk])
|
self.resource.logical_groups[lk] = deepcopy(_logical_groups[lk])
|
||||||
@ -156,6 +153,7 @@ class ComputeManager(threading.Thread):
|
|||||||
self.resource.logical_groups[lk].last_update = time.time()
|
self.resource.logical_groups[lk].last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: new logical group (" +
|
self.logger.warn("ComputeManager: new logical group (" +
|
||||||
lk + ") added")
|
lk + ") added")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rlk in self.resource.logical_groups.keys():
|
for rlk in self.resource.logical_groups.keys():
|
||||||
rl = self.resource.logical_groups[rlk]
|
rl = self.resource.logical_groups[rlk]
|
||||||
@ -167,6 +165,7 @@ class ComputeManager(threading.Thread):
|
|||||||
self.resource.logical_groups[rlk].last_update = time.time()
|
self.resource.logical_groups[rlk].last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: logical group (" +
|
self.logger.warn("ComputeManager: logical group (" +
|
||||||
rlk + ") removed")
|
rlk + ") removed")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for lk in _logical_groups.keys():
|
for lk in _logical_groups.keys():
|
||||||
lg = _logical_groups[lk]
|
lg = _logical_groups[lk]
|
||||||
@ -178,28 +177,42 @@ class ComputeManager(threading.Thread):
|
|||||||
rlg.last_update = time.time()
|
rlg.last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: logical group (" +
|
self.logger.warn("ComputeManager: logical group (" +
|
||||||
lk + ") updated")
|
lk + ") updated")
|
||||||
|
updated = True
|
||||||
|
|
||||||
|
return updated
|
||||||
|
|
||||||
def _check_logical_group_metadata_update(self, _lg, _rlg):
|
def _check_logical_group_metadata_update(self, _lg, _rlg):
|
||||||
|
updated = False
|
||||||
|
|
||||||
if _lg.status != _rlg.status:
|
if _lg.status != _rlg.status:
|
||||||
_rlg.status = _lg.status
|
_rlg.status = _lg.status
|
||||||
|
updated = True
|
||||||
|
|
||||||
for mdk in _lg.metadata.keys():
|
for mdk in _lg.metadata.keys():
|
||||||
if mdk not in _rlg.metadata.keys():
|
if mdk not in _rlg.metadata.keys():
|
||||||
_rlg.metadata[mdk] = _lg.metadata[mdk]
|
_rlg.metadata[mdk] = _lg.metadata[mdk]
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rmdk in _rlg.metadata.keys():
|
for rmdk in _rlg.metadata.keys():
|
||||||
if rmdk not in _lg.metadata.keys():
|
if rmdk not in _lg.metadata.keys():
|
||||||
del _rlg.metadata[rmdk]
|
del _rlg.metadata[rmdk]
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hk in _lg.vms_per_host.keys():
|
for hk in _lg.vms_per_host.keys():
|
||||||
if hk not in _rlg.vms_per_host.keys():
|
if hk not in _rlg.vms_per_host.keys():
|
||||||
_rlg.vms_per_host[hk] = deepcopy(_lg.vms_per_host[hk])
|
_rlg.vms_per_host[hk] = deepcopy(_lg.vms_per_host[hk])
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rhk in _rlg.vms_per_host.keys():
|
for rhk in _rlg.vms_per_host.keys():
|
||||||
if rhk not in _lg.vms_per_host.keys():
|
if rhk not in _lg.vms_per_host.keys():
|
||||||
del _rlg.vms_per_host[rhk]
|
del _rlg.vms_per_host[rhk]
|
||||||
|
updated = True
|
||||||
|
|
||||||
|
return updated
|
||||||
|
|
||||||
def _check_host_update(self, _hosts):
|
def _check_host_update(self, _hosts):
|
||||||
|
updated = False
|
||||||
|
|
||||||
for hk in _hosts.keys():
|
for hk in _hosts.keys():
|
||||||
if hk not in self.resource.hosts.keys():
|
if hk not in self.resource.hosts.keys():
|
||||||
new_host = Host(hk)
|
new_host = Host(hk)
|
||||||
@ -208,6 +221,7 @@ class ComputeManager(threading.Thread):
|
|||||||
new_host.last_update = time.time()
|
new_host.last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: new host (" +
|
self.logger.warn("ComputeManager: new host (" +
|
||||||
new_host.name + ") added")
|
new_host.name + ") added")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rhk, rhost in self.resource.hosts.iteritems():
|
for rhk, rhost in self.resource.hosts.iteritems():
|
||||||
if rhk not in _hosts.keys():
|
if rhk not in _hosts.keys():
|
||||||
@ -217,23 +231,28 @@ class ComputeManager(threading.Thread):
|
|||||||
rhost.last_update = time.time()
|
rhost.last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: host (" +
|
self.logger.warn("ComputeManager: host (" +
|
||||||
rhost.name + ") disabled")
|
rhost.name + ") disabled")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hk in _hosts.keys():
|
for hk in _hosts.keys():
|
||||||
host = _hosts[hk]
|
host = _hosts[hk]
|
||||||
rhost = self.resource.hosts[hk]
|
rhost = self.resource.hosts[hk]
|
||||||
if self._check_host_config_update(host, rhost) is True:
|
if self._check_host_config_update(host, rhost) is True:
|
||||||
rhost.last_update = time.time()
|
rhost.last_update = time.time()
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hk, h in self.resource.hosts.iteritems():
|
for hk, h in self.resource.hosts.iteritems():
|
||||||
if h.clean_memberships() is True:
|
if h.clean_memberships() is True:
|
||||||
h.last_update = time.time()
|
h.last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: host (" + h.name +
|
self.logger.warn("ComputeManager: host (" + h.name +
|
||||||
") updated (delete EX/AFF/DIV membership)")
|
") updated (delete EX/AFF/DIV membership)")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hk, host in self.resource.hosts.iteritems():
|
for hk, host in self.resource.hosts.iteritems():
|
||||||
if host.last_update > self.resource.current_timestamp:
|
if host.last_update >= self.resource.current_timestamp:
|
||||||
self.resource.update_rack_resource(host)
|
self.resource.update_rack_resource(host)
|
||||||
|
|
||||||
|
return updated
|
||||||
|
|
||||||
def _check_host_config_update(self, _host, _rhost):
|
def _check_host_config_update(self, _host, _rhost):
|
||||||
topology_updated = False
|
topology_updated = False
|
||||||
|
|
||||||
@ -388,19 +407,23 @@ class ComputeManager(threading.Thread):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
self.data_lock.acquire()
|
self.data_lock.acquire()
|
||||||
self._check_flavor_update(flavors)
|
if self._check_flavor_update(flavors) is True:
|
||||||
|
self.resource.update_topology(store=False)
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _check_flavor_update(self, _flavors):
|
def _check_flavor_update(self, _flavors):
|
||||||
|
updated = False
|
||||||
|
|
||||||
for fk in _flavors.keys():
|
for fk in _flavors.keys():
|
||||||
if fk not in self.resource.flavors.keys():
|
if fk not in self.resource.flavors.keys():
|
||||||
self.resource.flavors[fk] = deepcopy(_flavors[fk])
|
self.resource.flavors[fk] = deepcopy(_flavors[fk])
|
||||||
|
|
||||||
self.resource.flavors[fk].last_update = time.time()
|
self.resource.flavors[fk].last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: new flavor (" +
|
self.logger.warn("ComputeManager: new flavor (" +
|
||||||
fk + ") added")
|
fk + ":" + _flavors[fk].flavor_id + ") added")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rfk in self.resource.flavors.keys():
|
for rfk in self.resource.flavors.keys():
|
||||||
rf = self.resource.flavors[rfk]
|
rf = self.resource.flavors[rfk]
|
||||||
@ -410,6 +433,7 @@ class ComputeManager(threading.Thread):
|
|||||||
rf.last_update = time.time()
|
rf.last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: flavor (" + rfk + ":" +
|
self.logger.warn("ComputeManager: flavor (" + rfk + ":" +
|
||||||
rf.flavor_id + ") removed")
|
rf.flavor_id + ") removed")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for fk in _flavors.keys():
|
for fk in _flavors.keys():
|
||||||
f = _flavors[fk]
|
f = _flavors[fk]
|
||||||
@ -419,6 +443,9 @@ class ComputeManager(threading.Thread):
|
|||||||
rf.last_update = time.time()
|
rf.last_update = time.time()
|
||||||
self.logger.warn("ComputeManager: flavor (" + fk + ":" +
|
self.logger.warn("ComputeManager: flavor (" + fk + ":" +
|
||||||
rf.flavor_id + ") spec updated")
|
rf.flavor_id + ") spec updated")
|
||||||
|
updated = True
|
||||||
|
|
||||||
|
return updated
|
||||||
|
|
||||||
def _check_flavor_spec_update(self, _f, _rf):
|
def _check_flavor_spec_update(self, _f, _rf):
|
||||||
spec_updated = False
|
spec_updated = False
|
||||||
|
@ -207,7 +207,7 @@ class Resource(object):
|
|||||||
self.host_groups[hgk] = host_group
|
self.host_groups[hgk] = host_group
|
||||||
|
|
||||||
if len(self.host_groups) == 0:
|
if len(self.host_groups) == 0:
|
||||||
self.logger.error("fail loading host_groups")
|
self.logger.warn("fail loading host_groups")
|
||||||
|
|
||||||
dc = _resource_status.get("datacenter")
|
dc = _resource_status.get("datacenter")
|
||||||
if dc:
|
if dc:
|
||||||
@ -433,6 +433,8 @@ class Resource(object):
|
|||||||
self.nw_bandwidth_avail += min(avail_nw_bandwidth_list)
|
self.nw_bandwidth_avail += min(avail_nw_bandwidth_list)
|
||||||
|
|
||||||
def store_topology_updates(self):
|
def store_topology_updates(self):
|
||||||
|
store_start_time = time.time()
|
||||||
|
|
||||||
updated = False
|
updated = False
|
||||||
flavor_updates = {}
|
flavor_updates = {}
|
||||||
logical_group_updates = {}
|
logical_group_updates = {}
|
||||||
@ -536,6 +538,8 @@ class Resource(object):
|
|||||||
# self.show_current_logical_groups()
|
# self.show_current_logical_groups()
|
||||||
# self.show_current_host_status()
|
# self.show_current_host_status()
|
||||||
|
|
||||||
|
self.logger.debug("EVAL: total delay for store resource status = " + str(time.time() - store_start_time))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def show_current_logical_groups(self):
|
def show_current_logical_groups(self):
|
||||||
@ -566,12 +570,28 @@ class Resource(object):
|
|||||||
self.logger.error("TEST: membership missing")
|
self.logger.error("TEST: membership missing")
|
||||||
|
|
||||||
def show_current_host_status(self):
|
def show_current_host_status(self):
|
||||||
for hk, host in self.hosts.iteritems():
|
for hk, h in self.hosts.iteritems():
|
||||||
self.logger.debug("TEST: host name = " + hk)
|
self.logger.debug("TEST: host name = " + hk)
|
||||||
self.logger.debug(" status = " + host.status)
|
self.logger.debug(" status = " + h.status + ", " + h.state)
|
||||||
self.logger.debug(" vms = " + str(len(host.vm_list)))
|
self.logger.debug(" vms = " + str(len(h.vm_list)))
|
||||||
|
self.logger.debug(" resources (org, total, avail, used)")
|
||||||
|
cpu_org = str(h.original_vCPUs)
|
||||||
|
cpu_tot = str(h.vCPUs)
|
||||||
|
cpu_avail = str(h.avail_vCPUs)
|
||||||
|
cpu_used = str(h.vCPUs_used)
|
||||||
|
self.logger.debug(" cpu = " + cpu_org + ", " + cpu_tot + ", " + cpu_avail + ", " + cpu_used)
|
||||||
|
mem_org = str(h.original_mem_cap)
|
||||||
|
mem_tot = str(h.mem_cap)
|
||||||
|
mem_avail = str(h.avail_mem_cap)
|
||||||
|
mem_used = str(h.free_mem_mb)
|
||||||
|
self.logger.debug(" mem = " + mem_org + ", " + mem_tot + ", " + mem_avail + ", " + mem_used)
|
||||||
|
dsk_org = str(h.original_local_disk_cap)
|
||||||
|
dsk_tot = str(h.local_disk_cap)
|
||||||
|
dsk_avail = str(h.avail_local_disk_cap)
|
||||||
|
dsk_used = str(h.free_disk_gb)
|
||||||
|
self.logger.debug(" disk = " + dsk_org + ", " + dsk_tot + ", " + dsk_avail + ", " + dsk_used)
|
||||||
self.logger.debug(" memberships")
|
self.logger.debug(" memberships")
|
||||||
for mk in host.memberships.keys():
|
for mk in h.memberships.keys():
|
||||||
self.logger.debug(" " + mk)
|
self.logger.debug(" " + mk)
|
||||||
if mk not in self.logical_groups.keys():
|
if mk not in self.logical_groups.keys():
|
||||||
self.logger.error("TEST: lg missing")
|
self.logger.error("TEST: lg missing")
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2014-2017 AT&T Intellectual Property
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
"""Simulate hosts and flavors."""
|
|
||||||
|
|
||||||
from valet.engine.resource_manager.resource_base \
|
|
||||||
import Host, LogicalGroup, Flavor
|
|
||||||
|
|
||||||
|
|
||||||
class SimCompute(object):
|
|
||||||
"""Simulate Compute class."""
|
|
||||||
|
|
||||||
def __init__(self, _config):
|
|
||||||
"""Init."""
|
|
||||||
self.config = _config
|
|
||||||
|
|
||||||
def set_hosts(self, _hosts, _logical_groups):
|
|
||||||
"""Return success after setting sim hosts and flavors."""
|
|
||||||
self._set_availability_zones(_hosts, _logical_groups)
|
|
||||||
|
|
||||||
self._set_aggregates(_hosts, _logical_groups)
|
|
||||||
|
|
||||||
self._set_placed_vms(_hosts, _logical_groups)
|
|
||||||
|
|
||||||
self._set_resources(_hosts)
|
|
||||||
|
|
||||||
return "success"
|
|
||||||
|
|
||||||
def _set_availability_zones(self, _hosts, _logical_groups):
|
|
||||||
logical_group = LogicalGroup("nova")
|
|
||||||
logical_group.group_type = "AZ"
|
|
||||||
_logical_groups[logical_group.name] = logical_group
|
|
||||||
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
for h_num in range(0, self.config.num_of_hosts_per_rack):
|
|
||||||
host = Host(self.config.mode + "0r" + str(r_num) + "c" +
|
|
||||||
str(h_num))
|
|
||||||
host.tag.append("nova")
|
|
||||||
host.memberships["nova"] = logical_group
|
|
||||||
|
|
||||||
logical_group.vms_per_host[host.name] = []
|
|
||||||
|
|
||||||
_hosts[host.name] = host
|
|
||||||
|
|
||||||
def _set_aggregates(self, _hosts, _logical_groups):
|
|
||||||
for a_num in range(0, self.config.num_of_aggregates):
|
|
||||||
metadata = {}
|
|
||||||
metadata["cpu_allocation_ratio"] = "0.5"
|
|
||||||
|
|
||||||
aggregate = LogicalGroup("aggregate" + str(a_num))
|
|
||||||
aggregate.group_type = "AGGR"
|
|
||||||
aggregate.metadata = metadata
|
|
||||||
|
|
||||||
_logical_groups[aggregate.name] = aggregate
|
|
||||||
|
|
||||||
for a_num in range(0, self.config.num_of_aggregates):
|
|
||||||
aggregate = _logical_groups["aggregate" + str(a_num)]
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
for h_num in range(0, self.config.num_of_hosts_per_rack):
|
|
||||||
host_name = self.config.mode + "0r" + str(r_num) + "c" + \
|
|
||||||
str(h_num)
|
|
||||||
if host_name in _hosts.keys():
|
|
||||||
if (h_num %
|
|
||||||
(self.config.aggregated_ratio + a_num)) == 0:
|
|
||||||
host = _hosts[host_name]
|
|
||||||
host.memberships[aggregate.name] = aggregate
|
|
||||||
|
|
||||||
aggregate.vms_per_host[host.name] = []
|
|
||||||
|
|
||||||
def _set_placed_vms(self, _hosts, _logical_groups):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _set_resources(self, _hosts):
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
for h_num in range(0, self.config.num_of_hosts_per_rack):
|
|
||||||
host_name = self.config.mode + "0r" + str(r_num) + "c" + \
|
|
||||||
str(h_num)
|
|
||||||
if host_name in _hosts.keys():
|
|
||||||
host = _hosts[host_name]
|
|
||||||
host.original_vCPUs = float(self.config.cpus_per_host)
|
|
||||||
host.vCPUs_used = 0.0
|
|
||||||
host.original_mem_cap = float(self.config.mem_per_host)
|
|
||||||
host.free_mem_mb = host.original_mem_cap
|
|
||||||
host.original_local_disk_cap = \
|
|
||||||
float(self.config.disk_per_host)
|
|
||||||
host.free_disk_gb = host.original_local_disk_cap
|
|
||||||
host.disk_available_least = host.original_local_disk_cap
|
|
||||||
|
|
||||||
def set_flavors(self, _flavors):
|
|
||||||
"""Return success after setting passed in flavors."""
|
|
||||||
for f_num in range(0, self.config.num_of_basic_flavors):
|
|
||||||
flavor = Flavor("bflavor" + str(f_num))
|
|
||||||
flavor.vCPUs = float(self.config.base_flavor_cpus * (f_num + 1))
|
|
||||||
flavor.mem_cap = float(self.config.base_flavor_mem * (f_num + 1))
|
|
||||||
flavor.disk_cap = \
|
|
||||||
float(self.config.base_flavor_disk * (f_num + 1)) + \
|
|
||||||
10.0 + 20.0 / 1024.0
|
|
||||||
|
|
||||||
_flavors[flavor.name] = flavor
|
|
||||||
|
|
||||||
for a_num in range(0, self.config.num_of_aggregates):
|
|
||||||
flavor = Flavor("sflavor" + str(a_num))
|
|
||||||
flavor.vCPUs = self.config.base_flavor_cpus * (a_num + 1)
|
|
||||||
flavor.mem_cap = self.config.base_flavor_mem * (a_num + 1)
|
|
||||||
flavor.disk_cap = self.config.base_flavor_disk * (a_num + 1)
|
|
||||||
|
|
||||||
flavor.extra_specs["cpu_allocation_ratio"] = "0.5"
|
|
||||||
|
|
||||||
_flavors[flavor.name] = flavor
|
|
||||||
|
|
||||||
return "success"
|
|
@ -1,153 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2014-2017 AT&T Intellectual Property
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
"""Simulate datacenter configurations (i.e., layout, cabling)."""
|
|
||||||
|
|
||||||
from valet.engine.resource_manager.resource_base \
|
|
||||||
import HostGroup, Host, Switch, Link
|
|
||||||
|
|
||||||
|
|
||||||
class SimTopology(object):
|
|
||||||
"""Simulate Network and Host Topology class."""
|
|
||||||
|
|
||||||
def __init__(self, _config):
|
|
||||||
"""Init."""
|
|
||||||
self.config = _config
|
|
||||||
|
|
||||||
def set_topology(self, _datacenter, _host_groups, _hosts, _switches):
|
|
||||||
"""Return success string after setting network and host topology."""
|
|
||||||
self._set_network_topology(_switches)
|
|
||||||
self._set_host_topology(_datacenter, _host_groups, _hosts, _switches)
|
|
||||||
|
|
||||||
return "success"
|
|
||||||
|
|
||||||
def _set_network_topology(self, _switches):
|
|
||||||
root_switch = Switch("r0")
|
|
||||||
root_switch.switch_type = "root"
|
|
||||||
_switches[root_switch.name] = root_switch
|
|
||||||
|
|
||||||
if self.config.num_of_spine_switches > 0:
|
|
||||||
for s_num in range(0, self.config.num_of_spine_switches):
|
|
||||||
switch = Switch(root_switch.name + "s" + str(s_num))
|
|
||||||
switch.switch_type = "spine"
|
|
||||||
_switches[switch.name] = switch
|
|
||||||
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
switch = Switch(root_switch.name + "t" + str(r_num))
|
|
||||||
switch.switch_type = "ToR"
|
|
||||||
_switches[switch.name] = switch
|
|
||||||
|
|
||||||
for h_num in range(0, self.config.num_of_hosts_per_rack):
|
|
||||||
leaf_switch = Switch(switch.name + "l" + str(h_num))
|
|
||||||
leaf_switch.switch_type = "leaf"
|
|
||||||
_switches[leaf_switch.name] = leaf_switch
|
|
||||||
|
|
||||||
if self.config.num_of_spine_switches > 0:
|
|
||||||
for s_num in range(0, self.config.num_of_spine_switches):
|
|
||||||
s = _switches[root_switch.name + "s" + str(s_num)]
|
|
||||||
|
|
||||||
up_link = Link(s.name + "-" + root_switch.name)
|
|
||||||
up_link.resource = root_switch
|
|
||||||
up_link.nw_bandwidth = self.config.bandwidth_of_spine
|
|
||||||
up_link.avail_nw_bandwidth = up_link.nw_bandwidth
|
|
||||||
s.up_links[up_link.name] = up_link
|
|
||||||
|
|
||||||
if self.config.num_of_spine_switches > 1:
|
|
||||||
ps = None
|
|
||||||
if (s_num % 2) == 0:
|
|
||||||
if (s_num + 1) < self.config.num_of_spine_switches:
|
|
||||||
ps = _switches[root_switch.name + "s" +
|
|
||||||
str(s_num + 1)]
|
|
||||||
else:
|
|
||||||
ps = _switches[root_switch.name + "s" + str(s_num - 1)]
|
|
||||||
if ps is not None:
|
|
||||||
peer_link = Link(s.name + "-" + ps.name)
|
|
||||||
peer_link.resource = ps
|
|
||||||
peer_link.nw_bandwidth = self.config.bandwidth_of_spine
|
|
||||||
peer_link.avail_nw_bandwidth = peer_link.nw_bandwidth
|
|
||||||
s.peer_links[peer_link.name] = peer_link
|
|
||||||
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
s = _switches[root_switch.name + "t" + str(r_num)]
|
|
||||||
|
|
||||||
parent_switch_list = []
|
|
||||||
if self.config.num_of_spine_switches > 0:
|
|
||||||
for s_num in range(0, self.config.num_of_spine_switches):
|
|
||||||
parent_switch_list.append(_switches[root_switch.name +
|
|
||||||
"s" + str(s_num)])
|
|
||||||
else:
|
|
||||||
parent_switch_list.append(_switches[root_switch.name])
|
|
||||||
|
|
||||||
for parent_switch in parent_switch_list:
|
|
||||||
up_link = Link(s.name + "-" + parent_switch.name)
|
|
||||||
up_link.resource = parent_switch
|
|
||||||
up_link.nw_bandwidth = self.config.bandwidth_of_rack
|
|
||||||
up_link.avail_nw_bandwidth = up_link.nw_bandwidth
|
|
||||||
s.up_links[up_link.name] = up_link
|
|
||||||
|
|
||||||
if self.config.num_of_racks > 1:
|
|
||||||
ps = None
|
|
||||||
if (r_num % 2) == 0:
|
|
||||||
if (r_num + 1) < self.config.num_of_racks:
|
|
||||||
ps = _switches[root_switch.name + "t" + str(r_num + 1)]
|
|
||||||
else:
|
|
||||||
ps = _switches[root_switch.name + "t" + str(r_num - 1)]
|
|
||||||
if ps is not None:
|
|
||||||
peer_link = Link(s.name + "-" + ps.name)
|
|
||||||
peer_link.resource = ps
|
|
||||||
peer_link.nw_bandwidth = self.config.bandwidth_of_rack
|
|
||||||
peer_link.avail_nw_bandwidth = peer_link.nw_bandwidth
|
|
||||||
s.peer_links[peer_link.name] = peer_link
|
|
||||||
|
|
||||||
for h_num in range(0, self.config.num_of_hosts_per_rack):
|
|
||||||
ls = _switches[s.name + "l" + str(h_num)]
|
|
||||||
|
|
||||||
l_up_link = Link(ls.name + "-" + s.name)
|
|
||||||
l_up_link.resource = s
|
|
||||||
l_up_link.nw_bandwidth = self.config.bandwidth_of_host
|
|
||||||
l_up_link.avail_nw_bandwidth = l_up_link.nw_bandwidth
|
|
||||||
ls.up_links[l_up_link.name] = l_up_link
|
|
||||||
|
|
||||||
def _set_host_topology(self, _datacenter, _host_groups, _hosts, _switches):
|
|
||||||
root_switch = _switches["r0"]
|
|
||||||
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
host_group = HostGroup(_datacenter.name + "r" + str(r_num))
|
|
||||||
host_group.host_type = "rack"
|
|
||||||
switch = _switches[root_switch.name + "t" + str(r_num)]
|
|
||||||
host_group.switches[switch.name] = switch
|
|
||||||
_host_groups[host_group.name] = host_group
|
|
||||||
|
|
||||||
for h_num in range(0, self.config.num_of_hosts_per_rack):
|
|
||||||
host = Host(host_group.name + "c" + str(h_num))
|
|
||||||
leaf_switch = _switches[switch.name + "l" + str(h_num)]
|
|
||||||
host.switches[leaf_switch.name] = leaf_switch
|
|
||||||
_hosts[host.name] = host
|
|
||||||
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
host_group = _host_groups[_datacenter.name + "r" + str(r_num)]
|
|
||||||
host_group.parent_resource = _datacenter
|
|
||||||
|
|
||||||
for h_num in range(0, self.config.num_of_hosts_per_rack):
|
|
||||||
host = _hosts[host_group.name + "c" + str(h_num)]
|
|
||||||
host.host_group = host_group
|
|
||||||
|
|
||||||
host_group.child_resources[host.name] = host
|
|
||||||
|
|
||||||
_datacenter.root_switches[root_switch.name] = root_switch
|
|
||||||
|
|
||||||
for r_num in range(0, self.config.num_of_racks):
|
|
||||||
host_group = _host_groups[_datacenter.name + "r" + str(r_num)]
|
|
||||||
_datacenter.resources[host_group.name] = host_group
|
|
@ -95,14 +95,8 @@ class TopologyManager(threading.Thread):
|
|||||||
self.logger.info("TopologyManager: --- start topology "
|
self.logger.info("TopologyManager: --- start topology "
|
||||||
"status update ---")
|
"status update ---")
|
||||||
|
|
||||||
if self.set_topology() is True:
|
if self.set_topology() is not True:
|
||||||
self.data_lock.acquire()
|
self.logger.warn("fail to set topology")
|
||||||
update_status = self.resource.update_topology(store=False)
|
|
||||||
self.data_lock.release()
|
|
||||||
|
|
||||||
if update_status is False:
|
|
||||||
# TODO(GY): ignore?
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.logger.info("--- done topology status update ---")
|
self.logger.info("--- done topology status update ---")
|
||||||
|
|
||||||
@ -129,12 +123,15 @@ class TopologyManager(threading.Thread):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
self.data_lock.acquire()
|
self.data_lock.acquire()
|
||||||
self._check_update(datacenter, host_groups, hosts, switches)
|
if self._check_update(datacenter, host_groups, hosts, switches) is True:
|
||||||
|
self.resource.update_topology(store=False)
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _check_update(self, _datacenter, _host_groups, _hosts, _switches):
|
def _check_update(self, _datacenter, _host_groups, _hosts, _switches):
|
||||||
|
updated = False
|
||||||
|
|
||||||
for sk in _switches.keys():
|
for sk in _switches.keys():
|
||||||
if sk not in self.resource.switches.keys():
|
if sk not in self.resource.switches.keys():
|
||||||
new_switch = self._create_new_switch(_switches[sk])
|
new_switch = self._create_new_switch(_switches[sk])
|
||||||
@ -144,6 +141,7 @@ class TopologyManager(threading.Thread):
|
|||||||
|
|
||||||
self.logger.warn("TopologyManager: new switch (" +
|
self.logger.warn("TopologyManager: new switch (" +
|
||||||
new_switch.name + ") added")
|
new_switch.name + ") added")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rsk in self.resource.switches.keys():
|
for rsk in self.resource.switches.keys():
|
||||||
if rsk not in _switches.keys():
|
if rsk not in _switches.keys():
|
||||||
@ -154,6 +152,7 @@ class TopologyManager(threading.Thread):
|
|||||||
|
|
||||||
self.logger.warn("TopologyManager: switch (" +
|
self.logger.warn("TopologyManager: switch (" +
|
||||||
switch.name + ") disabled")
|
switch.name + ") disabled")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hk in _hosts.keys():
|
for hk in _hosts.keys():
|
||||||
if hk not in self.resource.hosts.keys():
|
if hk not in self.resource.hosts.keys():
|
||||||
@ -164,6 +163,7 @@ class TopologyManager(threading.Thread):
|
|||||||
|
|
||||||
self.logger.warn("TopologyManager: new host (" +
|
self.logger.warn("TopologyManager: new host (" +
|
||||||
new_host.name + ") added from configuration")
|
new_host.name + ") added from configuration")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rhk in self.resource.hosts.keys():
|
for rhk in self.resource.hosts.keys():
|
||||||
if rhk not in _hosts.keys():
|
if rhk not in _hosts.keys():
|
||||||
@ -175,6 +175,7 @@ class TopologyManager(threading.Thread):
|
|||||||
|
|
||||||
self.logger.warn("TopologyManager: host (" +
|
self.logger.warn("TopologyManager: host (" +
|
||||||
host.name + ") removed from configuration")
|
host.name + ") removed from configuration")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hgk in _host_groups.keys():
|
for hgk in _host_groups.keys():
|
||||||
if hgk not in self.resource.host_groups.keys():
|
if hgk not in self.resource.host_groups.keys():
|
||||||
@ -185,6 +186,7 @@ class TopologyManager(threading.Thread):
|
|||||||
|
|
||||||
self.logger.warn("TopologyManager: new host_group (" +
|
self.logger.warn("TopologyManager: new host_group (" +
|
||||||
new_host_group.name + ") added")
|
new_host_group.name + ") added")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for rhgk in self.resource.host_groups.keys():
|
for rhgk in self.resource.host_groups.keys():
|
||||||
if rhgk not in _host_groups.keys():
|
if rhgk not in _host_groups.keys():
|
||||||
@ -195,13 +197,14 @@ class TopologyManager(threading.Thread):
|
|||||||
|
|
||||||
self.logger.warn("TopologyManager: host_group (" +
|
self.logger.warn("TopologyManager: host_group (" +
|
||||||
host_group.name + ") disabled")
|
host_group.name + ") disabled")
|
||||||
|
updated = True
|
||||||
|
|
||||||
for sk in _switches.keys():
|
for sk in _switches.keys():
|
||||||
switch = _switches[sk]
|
switch = _switches[sk]
|
||||||
rswitch = self.resource.switches[sk]
|
rswitch = self.resource.switches[sk]
|
||||||
link_updated = self._check_switch_update(switch, rswitch)
|
if self._check_switch_update(switch, rswitch) is True:
|
||||||
if link_updated is True:
|
|
||||||
rswitch.last_update = time.time()
|
rswitch.last_update = time.time()
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hk in _hosts.keys():
|
for hk in _hosts.keys():
|
||||||
host = _hosts[hk]
|
host = _hosts[hk]
|
||||||
@ -210,8 +213,10 @@ class TopologyManager(threading.Thread):
|
|||||||
self._check_host_update(host, rhost)
|
self._check_host_update(host, rhost)
|
||||||
if topology_updated is True:
|
if topology_updated is True:
|
||||||
rhost.last_update = time.time()
|
rhost.last_update = time.time()
|
||||||
|
updated = True
|
||||||
if link_updated is True:
|
if link_updated is True:
|
||||||
rhost.last_link_update = time.time()
|
rhost.last_link_update = time.time()
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hgk in _host_groups.keys():
|
for hgk in _host_groups.keys():
|
||||||
hg = _host_groups[hgk]
|
hg = _host_groups[hgk]
|
||||||
@ -220,24 +225,30 @@ class TopologyManager(threading.Thread):
|
|||||||
self._check_host_group_update(hg, rhg)
|
self._check_host_group_update(hg, rhg)
|
||||||
if topology_updated is True:
|
if topology_updated is True:
|
||||||
rhg.last_update = time.time()
|
rhg.last_update = time.time()
|
||||||
|
updated = True
|
||||||
if link_updated is True:
|
if link_updated is True:
|
||||||
rhg.last_link_update = time.time()
|
rhg.last_link_update = time.time()
|
||||||
|
updated = True
|
||||||
|
|
||||||
(topology_updated, link_updated) = \
|
(topology_updated, link_updated) = \
|
||||||
self._check_datacenter_update(_datacenter)
|
self._check_datacenter_update(_datacenter)
|
||||||
if topology_updated is True:
|
if topology_updated is True:
|
||||||
self.resource.datacenter.last_update = time.time()
|
self.resource.datacenter.last_update = time.time()
|
||||||
|
updated = True
|
||||||
if link_updated is True:
|
if link_updated is True:
|
||||||
self.resource.datacenter.last_link_update = time.time()
|
self.resource.datacenter.last_link_update = time.time()
|
||||||
|
updated = True
|
||||||
|
|
||||||
for hk, host in self.resource.hosts.iteritems():
|
for hk, host in self.resource.hosts.iteritems():
|
||||||
if host.last_update > self.resource.current_timestamp:
|
if host.last_update >= self.resource.current_timestamp:
|
||||||
self.resource.update_rack_resource(host)
|
self.resource.update_rack_resource(host)
|
||||||
|
|
||||||
for hgk, hg in self.resource.host_groups.iteritems():
|
for hgk, hg in self.resource.host_groups.iteritems():
|
||||||
if hg.last_update > self.resource.current_timestamp:
|
if hg.last_update >= self.resource.current_timestamp:
|
||||||
self.resource.update_cluster_resource(hg)
|
self.resource.update_cluster_resource(hg)
|
||||||
|
|
||||||
|
return updated
|
||||||
|
|
||||||
def _create_new_switch(self, _switch):
|
def _create_new_switch(self, _switch):
|
||||||
new_switch = Switch(_switch.name)
|
new_switch = Switch(_switch.name)
|
||||||
new_switch.switch_type = _switch.switch_type
|
new_switch.switch_type = _switch.switch_type
|
||||||
|
Loading…
Reference in New Issue
Block a user