6a84485b0c
The patch adds NVP advanced LBaaS service support for NVP with VCNS: * NVP LBaaS is an advanced Service of NVP depending on NVP advanced service router - Once an advanced router id created, one corresponding vshield edge will be deployed, and then we can configure LB service On the vshield edge * NVP LBaaS service plugin still uses LBaaS DB service logic, while finally calling vShield Edge to support FWaaS service - When creating VIP object, service attaches the object to the advanced router with routedserviceinsertion service. Then before pushing VIP VCNS call, the server would first pushing associated POOL VCNS call and associated Monitor VCNS call to vShield Edge. Deleting VIP is opposite operation - Refering to CUD operation of other objects, service would first find the associated VIP object and then find the edge bound to the router which vip inserted. Then service would push corresponding VCNS call to Vshield Edge * on driver part, the driver will first convert the object to VSM known object input, and then send a synchronous JSON calling to VSM, and receive the result Implements: blueprint nvp-lbaas-plugin Change-Id: Iec41f2dc103daddf3bed4d09c147df3865b3dccd
559 lines
20 KiB
Python
559 lines
20 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
#
|
|
# Copyright 2013 VMware, Inc
|
|
#
|
|
# 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: linb, VMware
|
|
|
|
import copy
|
|
import json
|
|
|
|
from neutron.openstack.common import uuidutils
|
|
from neutron.plugins.nicira.vshield.common import exceptions
|
|
|
|
|
|
class FakeVcns(object):
|
|
|
|
errors = {
|
|
303: exceptions.ResourceRedirect,
|
|
400: exceptions.RequestBad,
|
|
403: exceptions.Forbidden,
|
|
404: exceptions.ResourceNotFound,
|
|
415: exceptions.MediaTypeUnsupport,
|
|
503: exceptions.ServiceUnavailable
|
|
}
|
|
|
|
def __init__(self, unique_router_name=True):
|
|
self._jobs = {}
|
|
self._job_idx = 0
|
|
self._edges = {}
|
|
self._edge_idx = 0
|
|
self._lswitches = {}
|
|
self._unique_router_name = unique_router_name
|
|
self._fake_nvpapi = None
|
|
self.fake_firewall_dict = {}
|
|
self.temp_firewall = {
|
|
"firewallRules": {
|
|
"firewallRules": []
|
|
}
|
|
}
|
|
self._fake_virtualservers_dict = {}
|
|
self._fake_pools_dict = {}
|
|
self._fake_monitors_dict = {}
|
|
self._fake_app_profiles_dict = {}
|
|
self._fake_loadbalancer_config = {}
|
|
|
|
def set_fake_nvpapi(self, fake_nvpapi):
|
|
self._fake_nvpapi = fake_nvpapi
|
|
|
|
def _validate_edge_name(self, name):
|
|
for edge_id, edge in self._edges.iteritems():
|
|
if edge['name'] == name:
|
|
return False
|
|
return True
|
|
|
|
def deploy_edge(self, request):
|
|
if (self._unique_router_name and
|
|
not self._validate_edge_name(request['name'])):
|
|
header = {
|
|
'status': 400
|
|
}
|
|
msg = ('Edge name should be unique for tenant. Edge %s '
|
|
'already exists for default tenant.') % request['name']
|
|
response = {
|
|
'details': msg,
|
|
'errorCode': 10085,
|
|
'rootCauseString': None,
|
|
'moduleName': 'vShield Edge',
|
|
'errorData': None
|
|
}
|
|
return (header, json.dumps(response))
|
|
|
|
self._job_idx = self._job_idx + 1
|
|
job_id = "jobdata-%d" % self._job_idx
|
|
self._edge_idx = self._edge_idx + 1
|
|
edge_id = "edge-%d" % self._edge_idx
|
|
self._jobs[job_id] = edge_id
|
|
self._edges[edge_id] = {
|
|
'name': request['name'],
|
|
'request': request,
|
|
'nat_rules': None,
|
|
'nat_rule_id': 0
|
|
}
|
|
header = {
|
|
'status': 200,
|
|
'location': 'https://host/api/4.0/jobs/%s' % job_id
|
|
}
|
|
response = ''
|
|
return (header, response)
|
|
|
|
def get_edge_id(self, job_id):
|
|
if job_id not in self._jobs:
|
|
raise Exception(_("Job %s does not nexist") % job_id)
|
|
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = {
|
|
'edgeId': self._jobs[job_id]
|
|
}
|
|
return (header, response)
|
|
|
|
def get_edge_deploy_status(self, edge_id):
|
|
if edge_id not in self._edges:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
header = {
|
|
'status': 200,
|
|
}
|
|
response = {
|
|
'systemStatus': 'good'
|
|
}
|
|
return (header, response)
|
|
|
|
def delete_edge(self, edge_id):
|
|
if edge_id not in self._edges:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
del self._edges[edge_id]
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = ''
|
|
return (header, response)
|
|
|
|
def update_interface(self, edge_id, vnic):
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = ''
|
|
return (header, response)
|
|
|
|
def get_nat_config(self, edge_id):
|
|
if edge_id not in self._edges:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
edge = self._edges[edge_id]
|
|
rules = edge['nat_rules']
|
|
if rules is None:
|
|
rules = {
|
|
'rules': {
|
|
'natRulesDtos': []
|
|
},
|
|
'version': 1
|
|
}
|
|
header = {
|
|
'status': 200
|
|
}
|
|
rules['version'] = 1
|
|
return (header, rules)
|
|
|
|
def update_nat_config(self, edge_id, nat):
|
|
if edge_id not in self._edges:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
edge = self._edges[edge_id]
|
|
max_rule_id = edge['nat_rule_id']
|
|
rules = copy.deepcopy(nat)
|
|
for rule in rules['rules']['natRulesDtos']:
|
|
rule_id = rule.get('ruleId', 0)
|
|
if rule_id > max_rule_id:
|
|
max_rule_id = rule_id
|
|
for rule in rules['rules']['natRulesDtos']:
|
|
if 'ruleId' not in rule:
|
|
max_rule_id = max_rule_id + 1
|
|
rule['ruleId'] = max_rule_id
|
|
edge['nat_rules'] = rules
|
|
edge['nat_rule_id'] = max_rule_id
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = ''
|
|
return (header, response)
|
|
|
|
def delete_nat_rule(self, edge_id, rule_id):
|
|
if edge_id not in self._edges:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
|
|
edge = self._edges[edge_id]
|
|
rules = edge['nat_rules']
|
|
rule_to_delete = None
|
|
for rule in rules['rules']['natRulesDtos']:
|
|
if rule_id == rule['ruleId']:
|
|
rule_to_delete = rule
|
|
break
|
|
if rule_to_delete is None:
|
|
raise Exception(_("Rule id %d doest not exist") % rule_id)
|
|
|
|
rules['rules']['natRulesDtos'].remove(rule_to_delete)
|
|
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = ''
|
|
return (header, response)
|
|
|
|
def get_edge_status(self, edge_id):
|
|
if edge_id not in self._edges:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = {
|
|
'edgeStatus': 'GREEN'
|
|
}
|
|
return (header, response)
|
|
|
|
def get_edges(self):
|
|
header = {
|
|
'status': 200
|
|
}
|
|
edges = []
|
|
for edge_id in self._edges:
|
|
edges.append({
|
|
'id': edge_id,
|
|
'edgeStatus': 'GREEN'
|
|
})
|
|
response = {
|
|
'edgePage': {
|
|
'data': edges
|
|
}
|
|
}
|
|
return (header, response)
|
|
|
|
def update_routes(self, edge_id, routes):
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = ''
|
|
return (header, response)
|
|
|
|
def create_lswitch(self, lsconfig):
|
|
# The lswitch is created via VCNS API so the fake nvpapi wont
|
|
# see it. Added to fake nvpapi here.
|
|
if self._fake_nvpapi:
|
|
lswitch = self._fake_nvpapi._add_lswitch(json.dumps(lsconfig))
|
|
else:
|
|
lswitch = lsconfig
|
|
lswitch['uuid'] = uuidutils.generate_uuid()
|
|
self._lswitches[lswitch['uuid']] = lswitch
|
|
header = {
|
|
'status': 200
|
|
}
|
|
lswitch['_href'] = '/api/ws.v1/lswitch/%s' % lswitch['uuid']
|
|
return (header, lswitch)
|
|
|
|
def delete_lswitch(self, id):
|
|
if id not in self._lswitches:
|
|
raise Exception(_("Lswitch %s does not exist") % id)
|
|
del self._lswitches[id]
|
|
if self._fake_nvpapi:
|
|
# TODO(fank): fix the hack
|
|
del self._fake_nvpapi._fake_lswitch_dict[id]
|
|
header = {
|
|
'status': 200
|
|
}
|
|
response = ''
|
|
return (header, response)
|
|
|
|
def update_firewall(self, edge_id, fw_req):
|
|
self.fake_firewall_dict[edge_id] = fw_req
|
|
rules = self.fake_firewall_dict[edge_id][
|
|
'firewallRules']['firewallRules']
|
|
index = 10
|
|
for rule in rules:
|
|
rule['ruleId'] = index
|
|
index += 10
|
|
header = {'status': 204}
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def delete_firewall(self, edge_id):
|
|
header = {'status': 404}
|
|
if edge_id in self.fake_firewall_dict:
|
|
header = {'status': 204}
|
|
del self.fake_firewall_dict[edge_id]
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def update_firewall_rule(self, edge_id, vcns_rule_id, fwr_req):
|
|
if edge_id not in self.fake_firewall_dict:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
header = {'status': 404}
|
|
rules = self.fake_firewall_dict[edge_id][
|
|
'firewallRules']['firewallRules']
|
|
for rule in rules:
|
|
if rule['ruleId'] == int(vcns_rule_id):
|
|
header['status'] = 204
|
|
rule.update(fwr_req)
|
|
break
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def delete_firewall_rule(self, edge_id, vcns_rule_id):
|
|
if edge_id not in self.fake_firewall_dict:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
header = {'status': 404}
|
|
rules = self.fake_firewall_dict[edge_id][
|
|
'firewallRules']['firewallRules']
|
|
for index in range(len(rules)):
|
|
if rules[index]['ruleId'] == int(vcns_rule_id):
|
|
header['status'] = 204
|
|
del rules[index]
|
|
break
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def add_firewall_rule_above(self, edge_id, ref_vcns_rule_id, fwr_req):
|
|
if edge_id not in self.fake_firewall_dict:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
header = {'status': 404}
|
|
rules = self.fake_firewall_dict[edge_id][
|
|
'firewallRules']['firewallRules']
|
|
pre = 0
|
|
for index in range(len(rules)):
|
|
if rules[index]['ruleId'] == int(ref_vcns_rule_id):
|
|
rules.insert(index, fwr_req)
|
|
rules[index]['ruleId'] = (int(ref_vcns_rule_id) + pre) / 2
|
|
header = {
|
|
'status': 204,
|
|
'location': "https://host/api/4.0/edges/edge_id/firewall"
|
|
"/config/rules/%s" % rules[index]['ruleId']}
|
|
break
|
|
pre = int(rules[index]['ruleId'])
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def add_firewall_rule(self, edge_id, fwr_req):
|
|
if edge_id not in self.fake_firewall_dict:
|
|
self.fake_firewall_dict[edge_id] = self.temp_firewall
|
|
rules = self.fake_firewall_dict[edge_id][
|
|
'firewallRules']['firewallRules']
|
|
rules.append(fwr_req)
|
|
index = len(rules)
|
|
rules[index - 1]['ruleId'] = index * 10
|
|
header = {
|
|
'status': 204,
|
|
'location': "https://host/api/4.0/edges/edge_id/firewall"
|
|
"/config/rules/%s" % rules[index - 1]['ruleId']}
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def get_firewall(self, edge_id):
|
|
if edge_id not in self.fake_firewall_dict:
|
|
self.fake_firewall_dict[edge_id] = self.temp_firewall
|
|
header = {'status': 204}
|
|
response = self.fake_firewall_dict[edge_id]
|
|
return self.return_helper(header, response)
|
|
|
|
def get_firewall_rule(self, edge_id, vcns_rule_id):
|
|
if edge_id not in self.fake_firewall_dict:
|
|
raise Exception(_("Edge %s does not exist") % edge_id)
|
|
header = {'status': 404}
|
|
response = ""
|
|
rules = self.fake_firewall_dict[edge_id][
|
|
'firewallRules']['firewallRules']
|
|
for rule in rules:
|
|
if rule['ruleId'] == int(vcns_rule_id):
|
|
header['status'] = 204
|
|
response = rule
|
|
break
|
|
return self.return_helper(header, response)
|
|
|
|
#
|
|
#Fake Edge LBAAS call
|
|
#
|
|
def create_vip(self, edge_id, vip_new):
|
|
if not self._fake_virtualservers_dict.get(edge_id):
|
|
self._fake_virtualservers_dict[edge_id] = {}
|
|
vip_vseid = uuidutils.generate_uuid()
|
|
self._fake_virtualservers_dict[edge_id][vip_vseid] = vip_new
|
|
header = {
|
|
'status': 204,
|
|
'location': "https://host/api/4.0/edges/edge_id"
|
|
"/loadbalancer/config/%s" % vip_vseid}
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def get_vip(self, edge_id, vip_vseid):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_virtualservers_dict.get(edge_id) or (
|
|
not self._fake_virtualservers_dict[edge_id].get(vip_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
response = self._fake_virtualservers_dict[edge_id][vip_vseid]
|
|
return self.return_helper(header, response)
|
|
|
|
def update_vip(self, edge_id, vip_vseid, vip_new):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_virtualservers_dict.get(edge_id) or (
|
|
not self._fake_virtualservers_dict[edge_id].get(vip_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
self._fake_virtualservers_dict[edge_id][vip_vseid].update(
|
|
vip_new)
|
|
return self.return_helper(header, response)
|
|
|
|
def delete_vip(self, edge_id, vip_vseid):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_virtualservers_dict.get(edge_id) or (
|
|
not self._fake_virtualservers_dict[edge_id].get(vip_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
del self._fake_virtualservers_dict[edge_id][vip_vseid]
|
|
return self.return_helper(header, response)
|
|
|
|
def create_pool(self, edge_id, pool_new):
|
|
if not self._fake_pools_dict.get(edge_id):
|
|
self._fake_pools_dict[edge_id] = {}
|
|
pool_vseid = uuidutils.generate_uuid()
|
|
self._fake_pools_dict[edge_id][pool_vseid] = pool_new
|
|
header = {
|
|
'status': 204,
|
|
'location': "https://host/api/4.0/edges/edge_id"
|
|
"/loadbalancer/config/%s" % pool_vseid}
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def get_pool(self, edge_id, pool_vseid):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_pools_dict.get(edge_id) or (
|
|
not self._fake_pools_dict[edge_id].get(pool_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
response = self._fake_pools_dict[edge_id][pool_vseid]
|
|
return self.return_helper(header, response)
|
|
|
|
def update_pool(self, edge_id, pool_vseid, pool_new):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_pools_dict.get(edge_id) or (
|
|
not self._fake_pools_dict[edge_id].get(pool_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
self._fake_pools_dict[edge_id][pool_vseid].update(
|
|
pool_new)
|
|
return self.return_helper(header, response)
|
|
|
|
def delete_pool(self, edge_id, pool_vseid):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_pools_dict.get(edge_id) or (
|
|
not self._fake_pools_dict[edge_id].get(pool_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
del self._fake_pools_dict[edge_id][pool_vseid]
|
|
return self.return_helper(header, response)
|
|
|
|
def create_health_monitor(self, edge_id, monitor_new):
|
|
if not self._fake_monitors_dict.get(edge_id):
|
|
self._fake_monitors_dict[edge_id] = {}
|
|
monitor_vseid = uuidutils.generate_uuid()
|
|
self._fake_monitors_dict[edge_id][monitor_vseid] = monitor_new
|
|
header = {
|
|
'status': 204,
|
|
'location': "https://host/api/4.0/edges/edge_id"
|
|
"/loadbalancer/config/%s" % monitor_vseid}
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def get_health_monitor(self, edge_id, monitor_vseid):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_monitors_dict.get(edge_id) or (
|
|
not self._fake_monitors_dict[edge_id].get(monitor_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
response = self._fake_monitors_dict[edge_id][monitor_vseid]
|
|
return self.return_helper(header, response)
|
|
|
|
def update_health_monitor(self, edge_id, monitor_vseid, monitor_new):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_monitors_dict.get(edge_id) or (
|
|
not self._fake_monitors_dict[edge_id].get(monitor_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
self._fake_monitors_dict[edge_id][monitor_vseid].update(
|
|
monitor_new)
|
|
return self.return_helper(header, response)
|
|
|
|
def delete_health_monitor(self, edge_id, monitor_vseid):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_monitors_dict.get(edge_id) or (
|
|
not self._fake_monitors_dict[edge_id].get(monitor_vseid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
del self._fake_monitors_dict[edge_id][monitor_vseid]
|
|
return self.return_helper(header, response)
|
|
|
|
def create_app_profile(self, edge_id, app_profile):
|
|
if not self._fake_app_profiles_dict.get(edge_id):
|
|
self._fake_app_profiles_dict[edge_id] = {}
|
|
app_profileid = uuidutils.generate_uuid()
|
|
self._fake_app_profiles_dict[edge_id][app_profileid] = app_profile
|
|
header = {
|
|
'status': 204,
|
|
'location': "https://host/api/4.0/edges/edge_id"
|
|
"/loadbalancer/config/%s" % app_profileid}
|
|
response = ""
|
|
return self.return_helper(header, response)
|
|
|
|
def delete_app_profile(self, edge_id, app_profileid):
|
|
header = {'status': 404}
|
|
response = ""
|
|
if not self._fake_app_profiles_dict.get(edge_id) or (
|
|
not self._fake_app_profiles_dict[edge_id].get(app_profileid)):
|
|
return self.return_helper(header, response)
|
|
header = {'status': 204}
|
|
del self._fake_app_profiles_dict[edge_id][app_profileid]
|
|
return self.return_helper(header, response)
|
|
|
|
def get_loadbalancer_config(self, edge_id):
|
|
header = {'status': 204}
|
|
response = {'config': False}
|
|
if self._fake_loadbalancer_config[edge_id]:
|
|
response['config'] = self._fake_loadbalancer_config[edge_id]
|
|
return self.return_helper(header, response)
|
|
|
|
def enable_service_loadbalancer(self, edge_id, config):
|
|
header = {'status': 204}
|
|
response = ""
|
|
self._fake_loadbalancer_config[edge_id] = True
|
|
return self.return_helper(header, response)
|
|
|
|
def return_helper(self, header, response):
|
|
status = int(header['status'])
|
|
if 200 <= status <= 300:
|
|
return (header, response)
|
|
if status in self.errors:
|
|
cls = self.errors[status]
|
|
else:
|
|
cls = exceptions.VcnsApiException
|
|
raise cls(
|
|
status=status, header=header, uri='fake_url', response=response)
|
|
|
|
def reset_all(self):
|
|
self._jobs.clear()
|
|
self._edges.clear()
|
|
self._lswitches.clear()
|
|
self.fake_firewall_dict = {}
|
|
self._fake_virtualservers_dict = {}
|
|
self._fake_pools_dict = {}
|
|
self._fake_monitors_dict = {}
|
|
self._fake_app_profiles_dict = {}
|
|
self._fake_loadbalancer_config = {}
|