3a0ea9e2bb
Signed-off-by: Satoshi KOBAYASHI <satoshi-k@iij.ad.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
222 lines
8.7 KiB
Python
222 lines
8.7 KiB
Python
# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
|
|
# Copyright (C) 2013 Isaku Yamahata <yamahata at valinux co jp>
|
|
#
|
|
# 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.
|
|
|
|
from __future__ import print_function
|
|
|
|
import time
|
|
import random
|
|
|
|
from ryu.base import app_manager
|
|
from ryu.lib import hub
|
|
from ryu.lib import mac as lib_mac
|
|
from ryu.lib.packet import vrrp
|
|
from ryu.services.protocols.vrrp import api as vrrp_api
|
|
from ryu.services.protocols.vrrp import event as vrrp_event
|
|
|
|
|
|
_VRID = 7
|
|
_PRIMARY_IP_ADDRESS0 = '10.0.0.2'
|
|
_PRIMARY_IP_ADDRESS1 = '10.0.0.3'
|
|
|
|
|
|
class VRRPCommon(app_manager.RyuApp):
|
|
_IFNAME0 = None
|
|
_IFNAME1 = None
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(VRRPCommon, self).__init__(*args, **kwargs)
|
|
|
|
def _main(self):
|
|
self._main_version(vrrp.VRRP_VERSION_V3)
|
|
self._main_version(vrrp.VRRP_VERSION_V2)
|
|
print("done!")
|
|
|
|
def _main_version(self, vrrp_version):
|
|
self._main_version_priority(vrrp_version,
|
|
vrrp.VRRP_PRIORITY_ADDRESS_OWNER)
|
|
self._main_version_priority(vrrp_version,
|
|
vrrp.VRRP_PRIORITY_BACKUP_MAX)
|
|
self._main_version_priority(vrrp_version,
|
|
vrrp.VRRP_PRIORITY_BACKUP_DEFAULT)
|
|
self._main_version_priority(vrrp_version,
|
|
vrrp.VRRP_PRIORITY_BACKUP_MIN)
|
|
|
|
def _main_version_priority(self, vrrp_version, priority):
|
|
self._main_version_priority_sleep(vrrp_version, priority, False)
|
|
self._main_version_priority_sleep(vrrp_version, priority, True)
|
|
|
|
def _check(self, vrrp_api, instances):
|
|
while True:
|
|
while True:
|
|
rep = vrrp_api.vrrp_list(self)
|
|
if len(rep.instance_list) >= len(instances) * 2:
|
|
if any(i.state == vrrp_event.VRRP_STATE_INITIALIZE
|
|
for i in rep.instance_list):
|
|
continue
|
|
break
|
|
print('%s / %s' % (len(rep.instance_list), len(instances) * 2))
|
|
time.sleep(1)
|
|
|
|
# for i in rep.instance_list:
|
|
# print('%s %s %s %s %s' % (i.instance_name,
|
|
# i.monitor_name,
|
|
# i.config,
|
|
# i.interface,
|
|
# i.state))
|
|
assert len(rep.instance_list) == len(instances) * 2
|
|
num_of_master = 0
|
|
d = dict(((i.instance_name, i) for i in rep.instance_list))
|
|
bad = 0
|
|
for i in rep.instance_list:
|
|
assert i.state in (vrrp_event.VRRP_STATE_MASTER,
|
|
vrrp_event.VRRP_STATE_BACKUP)
|
|
if i.state == vrrp_event.VRRP_STATE_MASTER:
|
|
num_of_master += 1
|
|
|
|
vr = instances[i.config.vrid]
|
|
if (vr[0].config.priority > vr[1].config.priority and
|
|
i.instance_name == vr[1].instance_name) or \
|
|
(vr[0].config.priority < vr[1].config.priority and
|
|
i.instance_name == vr[0].instance_name):
|
|
if i.state == vrrp_event.VRRP_STATE_MASTER:
|
|
print("bad master:")
|
|
print('%s %s' % (d[vr[0].instance_name].state,
|
|
d[vr[0].instance_name].config.priority))
|
|
print('%s %s' % (d[vr[1].instance_name].state,
|
|
d[vr[1].instance_name].config.priority))
|
|
bad += 1
|
|
# assert i.state != vrrp_event.VRRP_STATE_MASTER
|
|
if bad > 0:
|
|
# this could be a transient state
|
|
print("%s bad masters" % bad)
|
|
time.sleep(1)
|
|
continue
|
|
if num_of_master >= len(instances):
|
|
assert num_of_master == len(instances)
|
|
break
|
|
print('%s / %s' % (num_of_master, len(instances)))
|
|
time.sleep(1)
|
|
continue
|
|
|
|
def _main_version_priority_sleep(self, vrrp_version, priority, do_sleep):
|
|
app_mgr = app_manager.AppManager.get_instance()
|
|
self.logger.debug('%s', app_mgr.applications)
|
|
vrrp_mgr = app_mgr.applications['VRRPManager']
|
|
|
|
step = 5
|
|
instances = {}
|
|
for vrid in range(1, 256, step):
|
|
if vrid == _VRID:
|
|
continue
|
|
print("vrid %s" % vrid)
|
|
l = {}
|
|
prio = max(vrrp.VRRP_PRIORITY_BACKUP_MIN,
|
|
min(vrrp.VRRP_PRIORITY_BACKUP_MAX, vrid))
|
|
rep0 = self._configure_vrrp_router(vrrp_version,
|
|
prio,
|
|
_PRIMARY_IP_ADDRESS0,
|
|
self._IFNAME0,
|
|
vrid)
|
|
assert rep0.instance_name is not None
|
|
l[0] = rep0
|
|
prio = max(vrrp.VRRP_PRIORITY_BACKUP_MIN,
|
|
min(vrrp.VRRP_PRIORITY_BACKUP_MAX, 256 - vrid))
|
|
rep1 = self._configure_vrrp_router(vrrp_version,
|
|
prio,
|
|
_PRIMARY_IP_ADDRESS1,
|
|
self._IFNAME1,
|
|
vrid)
|
|
assert rep1.instance_name is not None
|
|
l[1] = rep1
|
|
instances[vrid] = l
|
|
|
|
print("vrid %s" % _VRID)
|
|
l = {}
|
|
rep0 = self._configure_vrrp_router(vrrp_version, priority,
|
|
_PRIMARY_IP_ADDRESS0,
|
|
self._IFNAME0, _VRID)
|
|
assert rep0.instance_name is not None
|
|
l[0] = rep0
|
|
rep1 = self._configure_vrrp_router(
|
|
vrrp_version, vrrp.VRRP_PRIORITY_BACKUP_DEFAULT,
|
|
_PRIMARY_IP_ADDRESS1, self._IFNAME1, _VRID)
|
|
assert rep1.instance_name is not None
|
|
l[1] = rep1
|
|
instances[_VRID] = l
|
|
|
|
self.logger.debug('%s', vrrp_mgr._instances)
|
|
|
|
if do_sleep:
|
|
print("priority %s" % priority)
|
|
print("waiting for instances starting")
|
|
|
|
self._check(vrrp_api, instances)
|
|
|
|
for vrid in instances.keys():
|
|
if vrid == _VRID:
|
|
continue
|
|
which = vrid & 1
|
|
new_priority = int(random.uniform(vrrp.VRRP_PRIORITY_BACKUP_MIN,
|
|
vrrp.VRRP_PRIORITY_BACKUP_MAX))
|
|
i = instances[vrid][which]
|
|
vrrp_api.vrrp_config_change(self, i.instance_name,
|
|
priority=new_priority)
|
|
i.config.priority = new_priority
|
|
|
|
if do_sleep:
|
|
print("priority shuffled")
|
|
|
|
self._check(vrrp_api, instances)
|
|
|
|
for vrid in instances.keys():
|
|
if vrid == _VRID:
|
|
continue
|
|
which = vrid & 1
|
|
vrrp_api.vrrp_shutdown(self, instances[vrid][which].instance_name)
|
|
vrrp_api.vrrp_shutdown(self, instances[_VRID][0].instance_name)
|
|
|
|
if do_sleep:
|
|
print("shutting down instances")
|
|
while True:
|
|
rep = vrrp_api.vrrp_list(self)
|
|
if len(rep.instance_list) <= len(instances):
|
|
break
|
|
print("left %s" % len(rep.instance_list))
|
|
time.sleep(1)
|
|
assert len(rep.instance_list) == len(instances)
|
|
print("waiting for the rest becoming master")
|
|
while True:
|
|
rep = vrrp_api.vrrp_list(self)
|
|
if all(i.state == vrrp_event.VRRP_STATE_MASTER
|
|
for i in rep.instance_list):
|
|
break
|
|
time.sleep(1)
|
|
|
|
vrrp_api.vrrp_shutdown(self, instances[_VRID][1].instance_name)
|
|
for vrid in instances.keys():
|
|
if vrid == _VRID:
|
|
continue
|
|
which = 1 - (vrid & 1)
|
|
vrrp_api.vrrp_shutdown(self, instances[vrid][which].instance_name)
|
|
|
|
print("waiting for instances shutting down")
|
|
while True:
|
|
rep = vrrp_api.vrrp_list(self)
|
|
if not rep.instance_list:
|
|
break
|
|
print("left %s" % len(rep.instance_list))
|
|
time.sleep(1)
|