Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move remaining SNAT code from VNC to SVC
Since this commit 4baf65c
the SNAT code has moved from the VNC to SVC. however
there were some remaining code related to the route
table/interfaces association. This patch moves these
remaining codes.

This patch also introduces an agent manager
which handles and forward some evens during
the service instance creation. The goal
of this refactoring is to move the specific
pieces of code that are present in the
instance_manager closer to their related
agent.

Unit-tests have been added for the snat_agent.

Closes-Bug: #1460540
Change-Id: I19502bfa77e4567946e9062be27f97e8766c5c84
  • Loading branch information
Anonymous authored and safchain committed Jul 21, 2015
1 parent d4919ef commit 0914c95
Show file tree
Hide file tree
Showing 12 changed files with 799 additions and 199 deletions.
9 changes: 6 additions & 3 deletions src/config/svc-monitor/SConscript
Expand Up @@ -2,7 +2,7 @@

#
# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
#
#
import os

Import('CfgmEnv')
Expand All @@ -17,6 +17,8 @@ sources = [
'.coveragerc',
'MANIFEST.in',
'svc_monitor/__init__.py',
'svc_monitor/agent.py',
'svc_monitor/agent_manager.py',
'svc_monitor/svc_monitor.py',
'svc_monitor/instance_manager.py',
'svc_monitor/virtual_machine_manager.py',
Expand All @@ -42,6 +44,7 @@ sources = [
'svc_monitor/tests/test_virtual_machine_manager.py',
'svc_monitor/tests/test_dep_track.py',
'svc_monitor/tests/test_snat.py',
'svc_monitor/tests/test_snat_agent.py',
'svc_monitor/tests/scheduler/__init__.py',
'svc_monitor/tests/scheduler/test_vrouter_schedulers.py',
]
Expand Down Expand Up @@ -81,8 +84,8 @@ if 'install' in BUILD_TARGETS:
env.Alias('install', env.Install(env['INSTALL_CONF'], 'contrail-svc-monitor.conf'))
env.Alias('install', env.InstallAs( env['INSTALL_INITD'] +
'/contrail-svc-monitor', 'contrail-svc-monitor.initd.supervisord'))
env.Alias('install', env.Install(env['INSTALL_CONF']+
'/supervisord_config_files', 'contrail-svc-monitor.ini'))
env.Alias('install', env.Install(env['INSTALL_CONF']+
'/supervisord_config_files', 'contrail-svc-monitor.ini'))

buildspace_link = os.environ.get('CONTRAIL_REPO')
if buildspace_link:
Expand Down
40 changes: 40 additions & 0 deletions src/config/svc-monitor/svc_monitor/agent.py
@@ -0,0 +1,40 @@
# Copyright (c) 2015 Redhat
# All Rights Reserved.
#
# 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.
#
# @author: Sylvain Afchain

import abc


class Agent(object):
__metaclass__ = abc.ABCMeta

def __init__(self, svc_mon, vnc_lib, cassandra, config_section):
self._vnc_lib = vnc_lib
self._svc_mon = svc_mon
self._cassandra = cassandra
self._args = config_section

@abc.abstractmethod
def handle_service_type(self):
pass

# method called just before creation of vm and vmi
def pre_create_service_vm(self, instance_index, si, st, vm):
pass

# method called just after creation of vm and vmi
def post_create_service_vm(self, instance_index, si, st, vm):
pass
36 changes: 36 additions & 0 deletions src/config/svc-monitor/svc_monitor/agent_manager.py
@@ -0,0 +1,36 @@
# Copyright (c) 2015 Redhat
# All Rights Reserved.
#
# 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.
#
# @author: Sylvain Afchain


class AgentManager(object):

def __init__(self):
self._agents = {}

def register_agent(self, agent):
type = agent.handle_service_type()
self._agents[type] = agent

def pre_create_service_vm(self, instance_index, si, st, vm):
agent = self._agents.get(st.params.get('service_type'))
if agent:
agent.pre_create_service_vm(instance_index, si, st, vm)

def post_create_service_vm(self, instance_index, si, st, vm):
agent = self._agents.get(st.params.get('service_type'))
if agent:
agent.post_create_service_vm(instance_index, si, st, vm)
1 change: 1 addition & 0 deletions src/config/svc-monitor/svc_monitor/config_db.py
Expand Up @@ -828,6 +828,7 @@ def __init__(self, uuid, obj_dict=None):
self.service_instance = None
self.virtual_network = None
self.virtual_machine_interfaces = set()
self.last_virtual_machine_interfaces = set()
self.update(obj_dict)
# end __init__

Expand Down
73 changes: 12 additions & 61 deletions src/config/svc-monitor/svc_monitor/instance_manager.py
Expand Up @@ -30,11 +30,12 @@
class InstanceManager(object):

def __init__(self, vnc_lib, db, logger, vrouter_scheduler,
nova_client, args=None):
nova_client, agent_manager, args=None):
self.logger = logger
self._vnc_lib = vnc_lib
self._args = args
self._nc = nova_client
self._agent_manager = agent_manager
self.vrouter_scheduler = vrouter_scheduler

@abc.abstractmethod
Expand Down Expand Up @@ -87,7 +88,7 @@ def _get_project_obj(self, proj_fq_name):
break
if not proj_obj:
self.logger.log_error("%s project not found" %
(proj_fq_name.join(':')))
(':'.join(proj_fq_name)))
return proj_obj

def _allocate_iip(self, vn_obj, iip_name):
Expand Down Expand Up @@ -239,18 +240,7 @@ def validate_network_config(self, st, si):
user_visible = True
itf_type = st_if.get('service_interface_type')
vn_fq_str = si_if.get('virtual_network', None)
if (itf_type == svc_info.get_left_if_str() and
(st.params.get('service_type') ==
svc_info.get_snat_service_type())):
vn_id = self._create_snat_vn(si, vn_fq_str, index)
user_visible = False
elif (itf_type == svc_info.get_right_if_str() and
(st.params.get('service_type') ==
svc_info.get_lb_service_type())):
iip_id, vn_id = self._get_vip_vmi_iip(si)
nic['iip-id'] = iip_id
user_visible = False
elif not vn_fq_str or vn_fq_str == '':
if not vn_fq_str:
vn_id = self._check_create_service_vn(itf_type, si)
else:
try:
Expand All @@ -259,7 +249,7 @@ def validate_network_config(self, st, si):
except NoIdError:
config_complete = False

nic['type'] = st_if.get('service_interface_type')
nic['type'] = itf_type
nic['index'] = str(index + 1)
nic['net-id'] = vn_id
nic['shared-ip'] = st_if.get('shared_ip')
Expand Down Expand Up @@ -298,6 +288,9 @@ def cleanup_svc_vm_ports(self, vmi_list, port_delete=True):
pass

def _check_create_netns_vm(self, instance_index, si, st, vm):
# notify all the agents
self._agent_manager.pre_create_service_vm(instance_index, si, st, vm)

instance_name = self._get_instance_name(si, instance_index)
vm_obj = VirtualMachine(instance_name)
vm_obj.set_display_name(instance_name + '__' + st.virtualization_type)
Expand All @@ -319,6 +312,9 @@ def _check_create_netns_vm(self, instance_index, si, st, vm):
local_preference=si.local_preference[instance_index],
vm_obj=vm_obj)

# notify all the agents
self._agent_manager.post_create_service_vm(instance_index, si, st, vm)

return vm

def _create_svc_vm_port(self, nic, instance_name, si, st,
Expand All @@ -343,7 +339,7 @@ def _create_svc_vm_port(self, nic, instance_name, si, st,
vmi_create = False
vmi_updated = False
if_properties = None

port_name = ('__').join([instance_name, nic['type'], nic['index']])
port_fq_name = proj_obj.fq_name + [port_name]
vmi_obj = VirtualMachineInterface(parent_obj=proj_obj, name=port_name)
Expand Down Expand Up @@ -595,51 +591,6 @@ def create_service(self, st, si):
status='CREATE', vms=instances,
st_name=(':').join(st.fq_name))

def _create_snat_vn(self, si, vn_fq_str, index):
vn_name = '%s_%s' % (svc_info.get_snat_left_vn_prefix(),
si.name)
vn_fq_name = si.fq_name[:-1] + [vn_name]
try:
vn_id = self._vnc_lib.fq_name_to_id(
'virtual-network', vn_fq_name)
except NoIdError:
snat_subnet = svc_info.get_snat_left_subnet()
vn_id = self.create_service_vn(vn_name, snat_subnet,
si.fq_name[:-1], user_visible=False)

if vn_fq_str != ':'.join(vn_fq_name):
si_obj = ServiceInstance()
si_obj.uuid = si.uuid
si_obj.fq_name = si.fq_name
si_props = ServiceInstanceType(**si.params)
left_if = ServiceInstanceInterfaceType(
virtual_network=':'.join(vn_fq_name))
si_props.insert_interface_list(index, left_if)
si_obj.set_service_instance_properties(si_props)
self._vnc_lib.service_instance_update(si_obj)
self.logger.log_info("SI %s updated with left vn %s" %
(si_obj.get_fq_name_str(), vn_fq_str))

return vn_id

def _get_vip_vmi_iip(self, si):
if not si.loadbalancer_pool:
return None, None

pool = LoadbalancerPoolSM.get(si.loadbalancer_pool)
if not pool.virtual_ip:
return None, None

vip = VirtualIpSM.get(pool.virtual_ip)
if not vip.virtual_machine_interface:
return None, None

vmi = VirtualMachineInterfaceSM.get(vip.virtual_machine_interface)
if not vmi.instance_ip or not vmi.virtual_network:
return None, None

return vmi.instance_ip, vmi.virtual_network

def add_fip_to_vip_vmi(self, vmi, fip):
iip = InstanceIpSM.get(vmi.instance_ip)
if not iip:
Expand Down
40 changes: 37 additions & 3 deletions src/config/svc-monitor/svc_monitor/loadbalancer_agent.py
Expand Up @@ -2,14 +2,20 @@

from cfgm_common import importutils
from cfgm_common import exceptions as vnc_exc
from cfgm_common import svc_info

from agent import Agent
from config_db import ServiceApplianceSM, ServiceApplianceSetSM, \
LoadbalancerPoolSM, InstanceIpSM, VirtualMachineInterfaceSM
LoadbalancerPoolSM, InstanceIpSM, VirtualMachineInterfaceSM, \
VirtualIpSM


class LoadbalancerAgent(object):
class LoadbalancerAgent(Agent):

def __init__(self, svc_mon, vnc_lib, config_section):
def __init__(self, svc_mon, vnc_lib, cassandra, config_section):
# Loadbalancer
super(LoadbalancerAgent, self).__init__(svc_mon, vnc_lib,
cassandra, config_section)
self._vnc_lib = vnc_lib
self._svc_mon = svc_mon
self._cassandra = self._svc_mon._cassandra
Expand All @@ -24,6 +30,34 @@ def __init__(self, svc_mon, vnc_lib, config_section):
self._default_provider = "opencontrail"
# end __init__

def handle_service_type(self):
return svc_info.get_lb_service_type()

def pre_create_service_vm(self, instance_index, si, st, vm):
for nic in si.vn_info:
if nic['type'] == svc_info.get_right_if_str():
iip_id, vn_id = self._get_vip_vmi_iip(si)
nic['iip-id'] = iip_id
nic['user-visible'] = False

def _get_vip_vmi_iip(self, si):
if not si.loadbalancer_pool:
return None, None

pool = LoadbalancerPoolSM.get(si.loadbalancer_pool)
if not pool.virtual_ip:
return None, None

vip = VirtualIpSM.get(pool.virtual_ip)
if not vip.virtual_machine_interface:
return None, None

vmi = VirtualMachineInterfaceSM.get(vip.virtual_machine_interface)
if not vmi.instance_ip or not vmi.virtual_network:
return None, None

return vmi.instance_ip, vmi.virtual_network

# create default loadbalancer driver
def _create_default_service_appliance_set(self, sa_set_name, driver_name):
default_gsc_name = "default-global-system-config"
Expand Down

0 comments on commit 0914c95

Please sign in to comment.