mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge release branch 4.7 to master
* 4.7: CLOUDSTACK-9154 - Sets the pub interface down when all guest nets are gone CLOUDSTACK-9187 - Makes code ready for more something like ethXXXX, if we ever get that far CLOUDSTACK-9188 - Reads network GC interval and wait from configDao CLOUDSTACK-9187 - Fixes interface allocation to VRRP instances CLOUDSTACK-9187 - Adds test to cover multiple nics and nic removal CLOUDSTACK-9154 - Adds test to cover nics state after GC CLOUDSTACK-9154 - Returns the guest iterface that is marked as added Conflicts: engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
This commit is contained in:
commit
addb26455a
File diff suppressed because it is too large
Load Diff
@ -48,15 +48,19 @@ class CsAddress(CsDataBag):
|
||||
|
||||
def get_guest_if(self):
|
||||
"""
|
||||
Return CsInterface object for the lowest guest interface
|
||||
Return CsInterface object for the lowest in use guest interface
|
||||
"""
|
||||
ipr = []
|
||||
guest_interface = None
|
||||
lowest_device = 1000
|
||||
for ip in self.get_ips():
|
||||
if ip.is_guest():
|
||||
ipr.append(ip)
|
||||
if len(ipr) > 0:
|
||||
return sorted(ipr)[-1]
|
||||
return None
|
||||
if ip.is_guest() and ip.is_added():
|
||||
device = ip.get_device()
|
||||
device_suffix = int(''.join([digit for digit in device if digit.isdigit()]))
|
||||
if device_suffix < lowest_device:
|
||||
lowest_device = device_suffix
|
||||
guest_interface = ip
|
||||
logging.debug("Guest interface will be set on device '%s' and IP '%s'" % (guest_interface.get_device(), guest_interface.get_ip()))
|
||||
return guest_interface
|
||||
|
||||
def get_guest_ip(self):
|
||||
"""
|
||||
@ -189,6 +193,9 @@ class CsInterface:
|
||||
if "nw_type" in self.address and self.address['nw_type'] in ['public']:
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_added(self):
|
||||
return self.get_attr("add")
|
||||
|
||||
def to_str(self):
|
||||
pprint(self.address)
|
||||
|
||||
@ -81,8 +81,10 @@ class CsRedundant(object):
|
||||
|
||||
def _redundant_on(self):
|
||||
guest = self.address.get_guest_if()
|
||||
|
||||
# No redundancy if there is no guest network
|
||||
if guest is None:
|
||||
self.set_backup()
|
||||
self._redundant_off()
|
||||
return
|
||||
|
||||
@ -108,7 +110,6 @@ class CsRedundant(object):
|
||||
CsHelper.service("keepalived", "stop")
|
||||
return
|
||||
|
||||
|
||||
CsHelper.mkdir(self.CS_RAMDISK_DIR, 0755, False)
|
||||
CsHelper.mount_tmpfs(self.CS_RAMDISK_DIR)
|
||||
CsHelper.mkdir(self.CS_ROUTER_DIR, 0755, False)
|
||||
@ -148,7 +149,7 @@ class CsRedundant(object):
|
||||
conntrackd_temp_bkp = "%s/%s" % (self.CS_TEMPLATES_DIR, "conntrackd.conf.templ.bkp")
|
||||
|
||||
CsHelper.copy(conntrackd_template_conf, conntrackd_temp_bkp)
|
||||
|
||||
|
||||
conntrackd_tmpl = CsFile(conntrackd_template_conf)
|
||||
conntrackd_tmpl.section("Multicast {", "}", [
|
||||
"IPv4_address 225.0.0.50\n",
|
||||
@ -164,10 +165,14 @@ class CsRedundant(object):
|
||||
conntrackd_conf = CsFile(self.CONNTRACKD_CONF)
|
||||
|
||||
is_equals = conntrackd_tmpl.compare(conntrackd_conf)
|
||||
|
||||
force_keepalived_restart = False
|
||||
proc = CsProcess(['/etc/conntrackd/conntrackd.conf'])
|
||||
if not proc.find() or not is_equals:
|
||||
|
||||
if not proc.find() and not is_equals:
|
||||
CsHelper.copy(conntrackd_template_conf, self.CONNTRACKD_CONF)
|
||||
CsHelper.service("conntrackd", "restart")
|
||||
force_keepalived_restart = True
|
||||
|
||||
# Restore the template file and remove the backup.
|
||||
CsHelper.copy(conntrackd_temp_bkp, conntrackd_template_conf)
|
||||
@ -185,7 +190,7 @@ class CsRedundant(object):
|
||||
heartbeat_cron.commit()
|
||||
|
||||
proc = CsProcess(['/usr/sbin/keepalived'])
|
||||
if not proc.find() or keepalived_conf.is_changed():
|
||||
if not proc.find() or keepalived_conf.is_changed() or force_keepalived_restart:
|
||||
keepalived_conf.commit()
|
||||
CsHelper.service("keepalived", "restart")
|
||||
|
||||
@ -222,17 +227,21 @@ class CsRedundant(object):
|
||||
|
||||
self.set_lock()
|
||||
logging.info("Router switched to fault mode")
|
||||
ads = [o for o in self.address.get_ips() if o.is_public()]
|
||||
for o in ads:
|
||||
CsHelper.execute("ifconfig %s down" % o.get_device())
|
||||
|
||||
ips = [ip for ip in self.address.get_ips() if ip.is_public()]
|
||||
for ip in ips:
|
||||
CsHelper.execute("ifconfig %s down" % ip.get_device())
|
||||
|
||||
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF)
|
||||
CsHelper.execute("%s -s" % cmd)
|
||||
CsHelper.service("ipsec", "stop")
|
||||
CsHelper.service("xl2tpd", "stop")
|
||||
CsHelper.service("dnsmasq", "stop")
|
||||
ads = [o for o in self.address.get_ips() if o.needs_vrrp()]
|
||||
for o in ads:
|
||||
CsPasswdSvc(o.get_gateway()).stop()
|
||||
|
||||
ips = [ip for ip in self.address.get_ips() if ip.needs_vrrp()]
|
||||
for ip in ips:
|
||||
CsPasswdSvc(ip.get_gateway()).stop()
|
||||
|
||||
self.cl.set_fault_state()
|
||||
self.cl.save()
|
||||
self.release_lock()
|
||||
@ -246,22 +255,25 @@ class CsRedundant(object):
|
||||
|
||||
self.set_lock()
|
||||
logging.debug("Setting router to backup")
|
||||
ads = [o for o in self.address.get_ips() if o.is_public()]
|
||||
|
||||
dev = ''
|
||||
for o in ads:
|
||||
if dev == o.get_device():
|
||||
ips = [ip for ip in self.address.get_ips() if ip.is_public()]
|
||||
for ip in ips:
|
||||
if dev == ip.get_device():
|
||||
continue
|
||||
logging.info("Bringing public interface %s down" % o.get_device())
|
||||
cmd2 = "ip link set %s down" % o.get_device()
|
||||
logging.info("Bringing public interface %s down" % ip.get_device())
|
||||
cmd2 = "ip link set %s down" % ip.get_device()
|
||||
CsHelper.execute(cmd2)
|
||||
dev = o.get_device()
|
||||
dev = ip.get_device()
|
||||
|
||||
cmd = "%s -C %s" % (self.CONNTRACKD_BIN, self.CONNTRACKD_CONF)
|
||||
CsHelper.execute("%s -d" % cmd)
|
||||
CsHelper.service("ipsec", "stop")
|
||||
CsHelper.service("xl2tpd", "stop")
|
||||
ads = [o for o in self.address.get_ips() if o.needs_vrrp()]
|
||||
for o in ads:
|
||||
CsPasswdSvc(o.get_gateway()).stop()
|
||||
|
||||
ips = [ip for ip in self.address.get_ips() if ip.needs_vrrp()]
|
||||
for ip in ips:
|
||||
CsPasswdSvc(ip.get_gateway()).stop()
|
||||
CsHelper.service("dnsmasq", "stop")
|
||||
|
||||
self.cl.set_master_state(False)
|
||||
@ -278,13 +290,13 @@ class CsRedundant(object):
|
||||
self.set_lock()
|
||||
logging.debug("Setting router to master")
|
||||
|
||||
ads = [o for o in self.address.get_ips() if o.is_public()]
|
||||
dev = ''
|
||||
ips = [ip for ip in self.address.get_ips() if ip.is_public()]
|
||||
route = CsRoute()
|
||||
for o in ads:
|
||||
if dev == o.get_device():
|
||||
for ip in ips:
|
||||
if dev == ip.get_device():
|
||||
continue
|
||||
dev = o.get_device()
|
||||
dev = ip.get_device()
|
||||
logging.info("Will proceed configuring device ==> %s" % dev)
|
||||
cmd2 = "ip link set %s up" % dev
|
||||
if CsDevice(dev, self.config).waitfordevice():
|
||||
@ -292,7 +304,7 @@ class CsRedundant(object):
|
||||
logging.info("Bringing public interface %s up" % dev)
|
||||
|
||||
try:
|
||||
gateway = o.get_gateway()
|
||||
gateway = ip.get_gateway()
|
||||
logging.info("Adding gateway ==> %s to device ==> %s" % (gateway, dev))
|
||||
route.add_defaultroute(gateway)
|
||||
except:
|
||||
@ -341,13 +353,15 @@ class CsRedundant(object):
|
||||
that could function as a router and VPC router at the same time
|
||||
"""
|
||||
lines = []
|
||||
for o in self.address.get_ips():
|
||||
if o.needs_vrrp():
|
||||
for ip in self.address.get_ips():
|
||||
if ip.needs_vrrp():
|
||||
cmdline=self.config.get_cmdline_instance()
|
||||
if not ip.is_added():
|
||||
continue
|
||||
if(cmdline.get_type()=='router'):
|
||||
str = " %s brd %s dev %s\n" % (cmdline.get_guest_gw(), o.get_broadcast(), o.get_device())
|
||||
str = " %s brd %s dev %s\n" % (cmdline.get_guest_gw(), ip.get_broadcast(), ip.get_device())
|
||||
else:
|
||||
str = " %s brd %s dev %s\n" % (o.get_gateway_cidr(), o.get_broadcast(), o.get_device())
|
||||
str = " %s brd %s dev %s\n" % (ip.get_gateway_cidr(), ip.get_broadcast(), ip.get_device())
|
||||
lines.append(str)
|
||||
return lines
|
||||
|
||||
|
||||
@ -34,7 +34,8 @@ from marvin.lib.base import (stopRouter,
|
||||
NetworkOffering,
|
||||
Network,
|
||||
VirtualMachine,
|
||||
LoadBalancerRule)
|
||||
LoadBalancerRule,
|
||||
Configurations)
|
||||
from marvin.lib.common import (get_domain,
|
||||
get_zone,
|
||||
get_template,
|
||||
@ -134,7 +135,7 @@ class Services:
|
||||
"vpc": {
|
||||
"name": "TestVPC",
|
||||
"displaytext": "TestVPC",
|
||||
"cidr": '10.0.0.1/24'
|
||||
"cidr": '10.0.0.0/16'
|
||||
},
|
||||
"network": {
|
||||
"name": "Test Network",
|
||||
@ -295,7 +296,7 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
len(self.routers), count,
|
||||
"Check that %s routers were indeed created" % count)
|
||||
|
||||
def check_master_status(self,count=2, showall=False):
|
||||
def check_routers_state(self,count=2, status_to_check="MASTER", expected_count=1, showall=False):
|
||||
vals = ["MASTER", "BACKUP", "UNKNOWN"]
|
||||
cnts = [0, 0, 0]
|
||||
|
||||
@ -345,11 +346,11 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
"Marvin configuration has no host credentials to\
|
||||
check router services")
|
||||
|
||||
if result.count(vals[0]) == 1:
|
||||
cnts[vals.index(vals[0])] += 1
|
||||
if result.count(status_to_check) == 1:
|
||||
cnts[vals.index(status_to_check)] += 1
|
||||
|
||||
if cnts[vals.index('MASTER')] != 1:
|
||||
self.fail("No Master or too many master routers found %s" % cnts[vals.index('MASTER')])
|
||||
if cnts[vals.index(status_to_check)] != expected_count:
|
||||
self.fail("Expected '%s' routers at state '%s', but found '%s'!" % (expected_count, status_to_check, cnts[vals.index(status_to_check)]))
|
||||
|
||||
def stop_router(self, router):
|
||||
self.logger.debug('Stopping router %s' % router.id)
|
||||
@ -364,14 +365,14 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
self.apiclient.rebootRouter(cmd)
|
||||
|
||||
def stop_router_by_type(self, type):
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.logger.debug('Stopping %s router' % type)
|
||||
for router in self.routers:
|
||||
if router.redundantstate == type:
|
||||
self.stop_router(router)
|
||||
|
||||
def reboot_router_by_type(self, type):
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.logger.debug('Rebooting %s router' % type)
|
||||
for router in self.routers:
|
||||
if router.redundantstate == type:
|
||||
@ -387,7 +388,7 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
self.routers = []
|
||||
|
||||
def start_routers(self):
|
||||
self.check_master_status(2, showall=True)
|
||||
self.check_routers_state(showall=True)
|
||||
self.logger.debug('Starting stopped routers')
|
||||
for router in self.routers:
|
||||
self.logger.debug('Router %s has state %s' % (router.id, router.state))
|
||||
@ -397,7 +398,9 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
cmd.id = router.id
|
||||
self.apiclient.startRouter(cmd)
|
||||
|
||||
def create_network(self, net_offerring, gateway='10.1.1.1', vpc=None):
|
||||
def create_network(self, net_offerring, gateway='10.1.1.1', vpc=None, nr_vms=2, mark_net_cleanup=True):
|
||||
if not nr_vms or nr_vms <= 0:
|
||||
self.fail("At least 1 VM has to be created. You informed nr_vms < 1")
|
||||
try:
|
||||
self.logger.debug('Create NetworkOffering')
|
||||
net_offerring["name"] = "NET_OFF-" + str(gateway)
|
||||
@ -427,17 +430,18 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
except Exception, e:
|
||||
self.fail('Unable to create a Network with offering=%s because of %s ' % (net_offerring, e))
|
||||
o = networkO(obj_network)
|
||||
|
||||
vm1 = self.deployvm_in_network(obj_network)
|
||||
vm2 = self.deployvm_in_network(obj_network)
|
||||
self.cleanup.insert(2, obj_network)
|
||||
self.cleanup.insert(3, nw_off)
|
||||
|
||||
o.add_vm(vm1)
|
||||
o.add_vm(vm2)
|
||||
|
||||
self.cleanup.insert(0, nw_off)
|
||||
if mark_net_cleanup:
|
||||
self.cleanup.insert(0, obj_network)
|
||||
|
||||
for i in range(0, nr_vms):
|
||||
vm1 = self.deployvm_in_network(obj_network, mark_vm_cleanup=mark_net_cleanup)
|
||||
o.add_vm(vm1)
|
||||
|
||||
return o
|
||||
|
||||
def deployvm_in_network(self, network, host_id=None):
|
||||
def deployvm_in_network(self, network, host_id=None, mark_vm_cleanup=True):
|
||||
try:
|
||||
self.logger.debug('Creating VM in network=%s' % network.name)
|
||||
vm = VirtualMachine.create(
|
||||
@ -451,7 +455,8 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
)
|
||||
|
||||
self.logger.debug('Created VM=%s in network=%s' % (vm.id, network.name))
|
||||
self.cleanup.insert(0, vm)
|
||||
if mark_vm_cleanup:
|
||||
self.cleanup.insert(0, vm)
|
||||
return vm
|
||||
except:
|
||||
self.fail('Unable to create VM in a Network=%s' % network.name)
|
||||
@ -524,22 +529,22 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
self.query_routers()
|
||||
self.networks.append(self.create_network(self.services["network_offering"], "10.1.1.1"))
|
||||
self.networks.append(self.create_network(self.services["network_offering_no_lb"], "10.1.2.1"))
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.add_nat_rules()
|
||||
self.do_vpc_test(False)
|
||||
|
||||
self.stop_router_by_type("MASTER")
|
||||
self.check_master_status(1)
|
||||
self.check_routers_state(1)
|
||||
self.do_vpc_test(False)
|
||||
|
||||
self.delete_nat_rules()
|
||||
self.check_master_status(1)
|
||||
self.check_routers_state(count=1)
|
||||
self.do_vpc_test(True)
|
||||
self.delete_public_ip()
|
||||
|
||||
self.start_routers()
|
||||
self.add_nat_rules()
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.do_vpc_test(False)
|
||||
|
||||
@attr(tags=["advanced", "intervlan"], required_hardware="true")
|
||||
@ -549,7 +554,7 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
self.query_routers()
|
||||
self.networks.append(self.create_network(self.services["network_offering"], "10.1.1.1"))
|
||||
self.networks.append(self.create_network(self.services["network_offering_no_lb"], "10.1.2.1"))
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.add_nat_rules()
|
||||
self.do_default_routes_test()
|
||||
|
||||
@ -559,18 +564,89 @@ class TestVPCRedundancy(cloudstackTestCase):
|
||||
self.logger.debug("Starting test_01_create_redundant_VPC_2tiers_4VMs_4IPs_4PF_ACL")
|
||||
self.query_routers()
|
||||
self.networks.append(self.create_network(self.services["network_offering"], "10.1.1.1"))
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.add_nat_rules()
|
||||
self.do_vpc_test(False)
|
||||
|
||||
self.reboot_router_by_type("MASTER")
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.do_vpc_test(False)
|
||||
|
||||
self.reboot_router_by_type("MASTER")
|
||||
self.check_master_status(2)
|
||||
self.check_routers_state()
|
||||
self.do_vpc_test(False)
|
||||
|
||||
@attr(tags=["advanced", "intervlan"], required_hardware="true")
|
||||
def test_04_rvpc_network_garbage_collector_nics(self):
|
||||
""" Create a redundant VPC with 1 Tier, 1 VM, 1 ACL, 1 PF and test Network GC Nics"""
|
||||
self.logger.debug("Starting test_04_rvpc_network_garbage_collector_nics")
|
||||
self.query_routers()
|
||||
self.networks.append(self.create_network(self.services["network_offering"], "10.1.1.1", nr_vms=1))
|
||||
self.check_routers_state()
|
||||
self.add_nat_rules()
|
||||
self.do_vpc_test(False)
|
||||
|
||||
self.stop_vm()
|
||||
|
||||
gc_wait = Configurations.list(self.apiclient, name="network.gc.wait")
|
||||
gc_interval = Configurations.list(self.apiclient, name="network.gc.interval")
|
||||
|
||||
self.logger.debug("network.gc.wait is ==> %s" % gc_wait)
|
||||
self.logger.debug("network.gc.interval is ==> %s" % gc_wait)
|
||||
|
||||
total_sleep = 120
|
||||
if gc_wait and gc_interval:
|
||||
total_sleep = int(gc_wait[0].value) + int(gc_interval[0].value)
|
||||
else:
|
||||
self.logger.debug("Could not retrieve the keys 'network.gc.interval' and 'network.gc.wait'. Sleeping for 2 minutes.")
|
||||
|
||||
time.sleep(total_sleep * 3)
|
||||
|
||||
self.check_routers_state(status_to_check="BACKUP", expected_count=2)
|
||||
self.start_vm()
|
||||
self.check_routers_state(status_to_check="MASTER")
|
||||
|
||||
@attr(tags=["advanced", "intervlan"], required_hardware="true")
|
||||
def test_05_rvpc_multi_tiers(self):
|
||||
""" Create a redundant VPC with 1 Tier, 1 VM, 1 ACL, 1 PF and test Network GC Nics"""
|
||||
self.logger.debug("Starting test_04_rvpc_network_garbage_collector_nics")
|
||||
self.query_routers()
|
||||
|
||||
network = self.create_network(self.services["network_offering"], "10.1.1.1", nr_vms=1, mark_net_cleanup=False)
|
||||
self.networks.append(network)
|
||||
self.networks.append(self.create_network(self.services["network_offering_no_lb"], "10.1.2.1", nr_vms=1))
|
||||
self.networks.append(self.create_network(self.services["network_offering_no_lb"], "10.1.3.1", nr_vms=1))
|
||||
|
||||
self.check_routers_state()
|
||||
self.add_nat_rules()
|
||||
self.do_vpc_test(False)
|
||||
|
||||
self.destroy_vm(network)
|
||||
network.get_net().delete(self.apiclient)
|
||||
self.networks.remove(network)
|
||||
|
||||
self.check_routers_state(status_to_check="MASTER")
|
||||
self.do_vpc_test(False)
|
||||
|
||||
def destroy_vm(self, network):
|
||||
vms_to_delete = []
|
||||
for vm in network.get_vms():
|
||||
vm.get_vm().delete(self.apiclient, expunge=True)
|
||||
vms_to_delete.append(vm)
|
||||
|
||||
all_vms = network.get_vms()
|
||||
[all_vms.remove(vm) for vm in vms_to_delete]
|
||||
|
||||
def stop_vm(self):
|
||||
for o in self.networks:
|
||||
for vm in o.get_vms():
|
||||
vm.get_vm().stop(self.apiclient)
|
||||
|
||||
def start_vm(self):
|
||||
for o in self.networks:
|
||||
for vm in o.get_vms():
|
||||
vm.get_vm().start(self.apiclient)
|
||||
|
||||
def delete_nat_rules(self):
|
||||
for o in self.networks:
|
||||
for vm in o.get_vms():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user