Tunnel loadbalancing policy: phase1 support
diff --git a/cli/c_actions.py b/cli/c_actions.py
index 2273709..b2ab1f8 100755
--- a/cli/c_actions.py
+++ b/cli/c_actions.py
@@ -93,6 +93,66 @@
if error_type:
raise error.CommandRestError(result, message)
+tunnelset_id=None
+tunnelset_dict=[]
+def tunnelset_create(data=None):
+ global tunnelset_id,tunnelset_dict
+ if sdnsh.description: # description debugging
+ print "tunnelset_create:" , data
+ if data.has_key('tunnelset-id'):
+ if (tunnelset_id != None):
+ if sdnsh.description: # description debugging
+ print "tunnelset_create: previous data is not cleaned up"
+ tunnelset_id=None
+ tunnelset_dict=[]
+ tunnelset_id=data['tunnelset-id']
+ tunnelset_dict=[]
+ if sdnsh.description: # description debugging
+ print "tunnelset_create:" , tunnelset_id
+
+def tunnelset_config_exit():
+ global tunnelset_id,tunnelset_dict
+ if sdnsh.description: # description debugging
+ print "tunnelset_config_exit entered", tunnelset_dict
+ if tunnelset_dict:
+ url_str = ""
+ entries = tunnelset_dict
+ url_str = "http://%s/rest/v1/tunnelset/" % (sdnsh.controller)
+ obj_data = {}
+ obj_data['tunnelset_id']=tunnelset_id
+ obj_data['tunnel_params']=entries
+ result = "fail"
+ try:
+ result = sdnsh.store.rest_post_request(url_str,obj_data)
+ except Exception, e:
+ errors = sdnsh.rest_error_to_dict(e)
+ print sdnsh.rest_error_dict_to_message(errors)
+ # LOOK! successful stuff should be returned in json too.
+ tunnelset_dict = []
+ tunnelset_id = None
+ curr_tunnel_id = None
+ if result != "success":
+ print "command failed"
+ else:
+ print "empty command"
+ #Clear the transit information
+
+def tunnelset_remove(data=None):
+ if sdnsh.description: # description debugging
+ print "tunnelset_remove:" , data
+ tunnelset_id=data['tunnelset-id']
+ url_str = "http://%s/rest/v1/tunnel/" % (sdnsh.controller)
+ obj_data = {}
+ obj_data['tunnelset_id']=data['tunnelset-id']
+ result = "fail"
+ try:
+ result = sdnsh.store.rest_post_request(url_str,obj_data,'DELETE')
+ except Exception, e:
+ errors = sdnsh.rest_error_to_dict(e)
+ print sdnsh.rest_error_dict_to_message(errors)
+ if not result.startswith("SUCCESS"):
+ print result
+
tunnel_id=None
tunnel_dict={}
def tunnel_create(data=None):
@@ -118,13 +178,18 @@
global tunnel_id,tunnel_dict
if sdnsh.description: # description debugging
print "tunnel_config_exit entered", tunnel_dict
- if tunnel_dict:
+
+ entries = tunnel_dict[tunnel_id]
+ obj_data = {}
+ obj_data['tunnel_id']=tunnel_id
+ obj_data['label_path']=entries
+ if tunnelset_id:
+ tunnelset_dict.append(obj_data)
+ tunnel_dict = {}
+ tunnel_id = None
+ elif tunnel_dict:
url_str = ""
- entries = tunnel_dict[tunnel_id]
url_str = "http://%s/rest/v1/tunnel/" % (sdnsh.controller)
- obj_data = {}
- obj_data['tunnel_id']=tunnel_id
- obj_data['label_path']=entries
result = "fail"
try:
result = sdnsh.store.rest_post_request(url_str,obj_data)
@@ -156,6 +221,7 @@
if not result.startswith("SUCCESS"):
print result
+
policy_obj_data = {}
def policy_create(data=None):
global policy_obj_data
@@ -174,7 +240,15 @@
if data.has_key('priority'):
policy_obj_data['priority'] = data['priority']
if data.has_key('tunnel-id'):
+ if policy_obj_data.has_key('tunnelset_id'):
+ print "ERROR: Policy can not point to both tunnelset and tunnel"
+ return
policy_obj_data['tunnel_id'] = data['tunnel-id']
+ if data.has_key('tunnelset-id'):
+ if policy_obj_data.has_key('tunnel_id'):
+ print "ERROR: Policy can not point to both tunnelset and tunnel"
+ return
+ policy_obj_data['tunnelset_id'] = data['tunnelset-id']
if sdnsh.description: # description debugging
print policy_obj_data
@@ -744,6 +818,9 @@
# and additional config modes must also have the same prefix as the
# current mode.
current_mode = sdnsh.current_mode()
+ if (mode_name == 'config-tunnel'):
+ if (current_mode == 'config-tunnelset'):
+ mode_name = 'config-tunnelset-tunnel'
if sdnsh.description: # description debugging
print "push_mode: ", mode_name, obj_type, data, parent_field, parent_id
@@ -855,7 +932,9 @@
if sdnsh.description: # description debugging
print "push_mode: ", mode_name, obj_type, pk_name, key
exitCallback = None
- if (mode_name == 'config-tunnel'):
+ if (mode_name == 'config-tunnelset'):
+ exitCallback = tunnelset_config_exit
+ if ((mode_name == 'config-tunnel') or (mode_name == 'config-tunnelset-tunnel')):
exitCallback = tunnel_config_exit
if (mode_name == 'config-policy'):
exitCallback = policy_config_exit
@@ -2218,6 +2297,7 @@
# labelStackString = labelStackString[:-1]
# labelStackString += ']'
tunnelId = tunnel.get('tunnelId')
+ tunnelsetId = tunnel.get('tunnelsetId')
tunnelPath = tunnel.get('tunnelPath')
dpidGroup = str(tunnel.get('dpidGroup'))
dpidGroup= remove_unicodes(dpidGroup)
@@ -2228,9 +2308,37 @@
'dpidGroup' : dpidGroup,
'tunnelPath' : tunnelPath,
'policies' : policies,
+ 'tunnelset' : tunnelsetId,
})
entries = combResult
+ if 'showtunnelset' in data and (data['showtunnelset'] == 'tunnelset' or data['detail'] == 'details'):
+ #eraise error.ArgumentValidationError('\n\n\n %s' % (entries))
+ combResult = []
+ tunnelsetList = entries
+ for tunnelset in tunnelsetList:
+ tunnelsetId = tunnelset.get('tunnelsetId')
+ policies = tunnelset.get('policies')
+ tunnelList = tunnelset.get('constituentTunnels')
+ for tunnel in tunnelList:
+ labelStackList = (tunnel.get('labelStack'))
+ labelStackString = str(labelStackList)
+ labelStackString = remove_unicodes(labelStackString)
+ tunnelId = tunnel.get('tunnelId')
+ tunnelPath = tunnel.get('tunnelPath')
+ dpidGroup = str(tunnel.get('dpidGroup'))
+ dpidGroup= remove_unicodes(dpidGroup)
+ combResult.append({
+ 'tunnelsetId' : tunnelsetId,
+ 'policies' : policies,
+ 'tunnelId' : tunnelId,
+ 'labelStack' : labelStackString,
+ 'dpidGroup' : dpidGroup,
+ 'tunnelPath' : tunnelPath,
+ 'tunnelset' : tunnelsetId,
+ })
+ entries = combResult
+
if 'showpolicy' in data and data['showpolicy'] == 'policy':
#raise error.ArgumentValidationError('\n\n\n %s' % (data))
combResult = []
@@ -3882,6 +3990,14 @@
tunnel_remove,
{'kwargs': {'data' : '$data',}})
+ command.add_action('create-tunnelset',
+ tunnelset_create,
+ {'kwargs': {'data' : '$data',}})
+
+ command.add_action('remove-tunnelset',
+ tunnelset_remove,
+ {'kwargs': {'data' : '$data',}})
+
command.add_action('create-policy',
policy_create,
{'kwargs': {'data' : '$data',}})
diff --git a/cli/climodelinfo.py b/cli/climodelinfo.py
index 438eda8..523ece1 100755
--- a/cli/climodelinfo.py
+++ b/cli/climodelinfo.py
@@ -265,6 +265,24 @@
},
},
},
+
+ 'tunnelset-config' : {
+ 'source' : 'user-config',
+ 'source' : 'display',
+ 'url' : 'tunnelset-config',
+ 'config-obj-type' : 'tunnelset-config',
+
+ 'fields' : {
+ 'tunnelset-id' : {
+ 'edit' : False,
+ 'max_length': 32,
+ 'null': False,
+ 'primary_key': True,
+ 'type': 'CharField',
+ 'edit' : False,
+ },
+ },
+ },
'policy-config' : {
'source' : 'user-config',
diff --git a/cli/command.py b/cli/command.py
index b1fa227..d99ed41 100755
--- a/cli/command.py
+++ b/cli/command.py
@@ -1750,16 +1750,34 @@
command_mode = command.get('mode')
if command_mode and command_mode[-1] == '*':
command_mode = command_mode[:-1]
- if command_mode and sdnsh.current_mode() != command_mode:
+ if (command_mode == 'config-tunnel' and
+ sdnsh.current_mode() == 'config-tunnelset-tunnel'):
+ command_mode = 'config-tunnelset-tunnel'
+ if (command_mode and
+ ((_is_list(command_mode) and not sdnsh.current_mode() in command_mode)
+ or (sdnsh.current_mode() != command_mode))):
+
# this is completing a different item on the stack.
# XXX needs better api's here.
found_in_mode_stack = False
- for x in sdnsh.mode_stack:
- if x['mode_name'] == command_mode:
- found_in_mode_stack = True
- curr_obj_type = x['obj_type']
- curr_obj_id = x['obj']
- break
+
+ if _is_list(command_mode):
+ for cmd_mode in command_mode:
+ for x in sdnsh.mode_stack:
+ if x['mode_name'] == cmd_mode:
+ found_in_mode_stack = True
+ curr_obj_type = x['obj_type']
+ curr_obj_id = x['obj']
+ break
+ if found_in_mode_stack == True:
+ break
+ else:
+ for x in sdnsh.mode_stack:
+ if x['mode_name'] == command_mode:
+ found_in_mode_stack = True
+ curr_obj_type = x['obj_type']
+ curr_obj_id = x['obj']
+ break
if not found_in_mode_stack:
raise error.CommandDescriptionError(
'Unable to find mode %s' % command_mode,
@@ -3865,6 +3883,14 @@
'no-action': 'delete-objects',
})
+ add_command_type('create-tunnelset', {
+ 'action': 'create-tunnelset'
+ })
+
+ add_command_type('remove-tunnelset', {
+ 'action': 'remove-tunnelset'
+ })
+
add_command_type('create-tunnel', {
'action': 'create-tunnel'
})
diff --git a/cli/desc/version200/core.py b/cli/desc/version200/core.py
index 0e0f3c1..9a8b8bc 100755
--- a/cli/desc/version200/core.py
+++ b/cli/desc/version200/core.py
@@ -2399,12 +2399,37 @@
SHOW_TUNNEL_FORMAT = {
'show_tunnel' : {
'field-orderings' : {
- 'default' : [ 'Idx', 'tunnelId', 'policies','tunnelPath','labelStack',],
- 'details' : [ 'Idx', 'tunnelId', 'policies','tunnelPath','labelStack', 'dpidGroup',],
+ 'default' : [ 'Idx', 'tunnelId', 'policies','tunnelset','tunnelPath','labelStack',],
+ 'details' : [ 'Idx', 'tunnelId', 'policies','tunnelset','tunnelPath','labelStack', 'dpidGroup',],
},
'fields': {
'tunnelId' : { 'verbose-name' : 'Id',
},
+ 'tunnelset' : { 'verbose-name' : 'tunnelset',
+ },
+ 'dpidGroup' : { 'verbose-name' : 'Dpid(Node Id)/Group',
+ },
+ 'labelStack' : { 'verbose-name' : 'Label Stack [Outer-->Inner]',
+ },
+ 'tunnelPath' : { 'verbose-name' : 'Tunnel Path [Head-->Tail]',
+ },
+ }
+ },
+}
+
+SHOW_TUNNELSET_FORMAT = {
+ 'show_tunnelset' : {
+ 'field-orderings' : {
+ 'default' : [ 'Idx', 'tunnelsetId', 'policies','tunnelId','tunnelPath','labelStack',],
+ 'details' : [ 'Idx', 'tunnelsetId', 'policies','tunnelId','tunnelPath','labelStack', 'dpidGroup',],
+ },
+ 'fields': {
+ 'tunnelsetId' : { 'verbose-name' : 'Id',
+ },
+ 'tunnelId' : { 'verbose-name' : 'tunnelId',
+ },
+ 'tunnelset' : { 'verbose-name' : 'tunnelset',
+ },
'dpidGroup' : { 'verbose-name' : 'Dpid(Node Id)/Group',
},
'labelStack' : { 'verbose-name' : 'Label Stack [Outer-->Inner]',
diff --git a/cli/desc/version200/policy.py b/cli/desc/version200/policy.py
index eac0209..ad99363 100644
--- a/cli/desc/version200/policy.py
+++ b/cli/desc/version200/policy.py
@@ -254,7 +254,7 @@
'proc' : 'create-policy',
},
),
- 'completion' : 'tunnelid-completion',
+ 'completion' : 'tunnel-id-completion',
'field' : 'tunnel-id',
'type' : 'identifier',
'syntax-help' : 'Enter tunnel id',
@@ -263,6 +263,30 @@
}
}
+POLICY_TUNNELSET_ID_COMMAND_DESCRIPTION = {
+ 'name' : 'tunnelset',
+ 'mode' : 'config-policy',
+ #'obj-type' : 'policy-config',
+ 'command-type' : 'config',
+ 'short-help' : 'Configure tunnelset id',
+ #'doc' : 'policy|tunnel',
+ #'doc-example' : 'policy|policy-tunnel-example',
+ 'parent-field' : 'policy',
+ 'args' : {
+ 'action' : (
+ {
+ 'proc' : 'create-policy',
+ },
+ ),
+ 'completion' : 'tunnelset-id-completion',
+ 'field' : 'tunnelset-id',
+ 'type' : 'identifier',
+ 'syntax-help' : 'Enter tunnelset id',
+ 'doc' : 'policy|tunnelset-id',
+ 'doc-include' : [ 'type-doc' ],
+ }
+}
+
POLICY_PRIORITY_COMMAND_DESCRIPTION = {
'name' : 'priority',
'mode' : 'config-policy',
@@ -322,6 +346,19 @@
'completions' : '$completions',
}})
+def tunnelset_id_completion(prefix, completions):
+ query_url = "http://127.0.0.1:8000/rest/v1/showtunnelset"
+ result = command.sdnsh.store.rest_simple_request(query_url)
+ entries = json.loads(result)
+ for entry in entries:
+ if entry['tunnelsetId'].startswith(prefix):
+ completions[entry['tunnelsetId']+' '] = entry['tunnelsetId']
+ return
+
+command.add_completion('tunnelset-id-completion', tunnelset_id_completion,
+ {'kwargs': { 'prefix' : '$text',
+ 'completions' : '$completions',
+ }})
def policy_id_completion(prefix, completions):
query_url = "http://127.0.0.1:8000/rest/v1/showpolicy"
diff --git a/cli/desc/version200/tunnel.py b/cli/desc/version200/tunnel.py
index d79b012..a2bc0cd 100644
--- a/cli/desc/version200/tunnel.py
+++ b/cli/desc/version200/tunnel.py
@@ -2,12 +2,56 @@
import json
import fmtcnv
+TUNNELSET_SUBMODE_COMMAND_DESCRIPTION = {
+ 'name' : 'tunnelset',
+ 'short-help' : 'Enter tunnelset submode, configure tunnelset details',
+ 'mode' : 'config',
+ 'parent-field' : None,
+ 'command-type' : 'config-submode',
+ 'obj-type' : 'tunnelset-config',
+ 'submode-name' : 'config-tunnelset',
+ 'doc' : 'tunnelset|tunnelset',
+ 'doc-example' : 'tunnelset|tunnelset-example',
+ 'args' : (
+ {
+ 'field' : 'tunnelset-id',
+ 'type' : 'identifier',
+ #'completion' : 'complete-object-field',
+ 'syntax-help' : 'Enter a tunnelset name',
+ 'doc' : 'tunnelset|tunnelset',
+ 'doc-include' : [ 'type-doc' ],
+ #'completion' : 'tunnelset-id-completion',
+ 'action' : (
+ {
+ 'proc' : 'create-tunnelset',
+ },
+ {
+ 'proc' : 'push-mode-stack',
+ },
+ ),
+ 'no-action': (
+ {
+ 'proc' : 'remove-tunnelset',
+ }
+ ),
+ }
+ )
+}
+
+TUNNELSET_CONFIG_FORMAT = {
+ 'tunnelset-config' : {
+ 'field-orderings' : {
+ 'default' : [
+ 'tunnelset-id',
+ ],
+ },
+ },
+}
TUNNEL_SUBMODE_COMMAND_DESCRIPTION = {
'name' : 'tunnel',
'short-help' : 'Enter tunnel submode, configure tunnel details',
- 'mode' : 'config',
- 'parent-field' : None,
+ 'mode' : ['config', 'config-tunnelset'],
'command-type' : 'config-submode',
'obj-type' : 'tunnel-config',
'submode-name' : 'config-tunnel',
@@ -115,7 +159,7 @@
# obj_type flow-entry field hard-timeout
TUNNEL_NODE_ENTRY_COMMAND_DESCRIPTION = {
'name' : 'node',
- 'mode' : 'config-tunnel',
+ 'mode' : 'config-tunnel*',
'short-help' : 'Set node for this tunnel',
'doc' : 'tunnel|node',
'doc-example' : 'tunnel|node',
@@ -143,7 +187,7 @@
)
}
-SWITCH_TUNNEL_COMMAND_DESCRIPTION = {
+SHOW_TUNNEL_COMMAND_DESCRIPTION = {
'name' : 'show',
'mode' : 'login',
'command-type' : 'display-table',
@@ -180,6 +224,42 @@
)
}
+SHOW_TUNNELSET_COMMAND_DESCRIPTION = {
+ 'name' : 'show',
+ 'mode' : 'login',
+ 'command-type' : 'display-table',
+ 'all-help' : 'Show tunnelset information',
+ 'short-help' : 'Show tunnelset summary',
+ #'obj-type' : 'switches',
+ 'doc' : 'tunnelset|show',
+ 'doc-example' : 'tunnelset|show-example',
+ 'args' : (
+ {
+ 'token' : 'tunnelset',
+ 'field' : 'showtunnelset',
+ 'sort' : ['tunnelsetId',],
+ 'action' : 'display-rest',
+ 'doc' : 'tunnelset|show',
+ 'url' : [
+ 'showtunnelset',
+ ],
+ 'format' : 'show_tunnelset',
+ },
+ {
+ 'optional' : True,
+ 'choices' : (
+ {
+ 'field' : 'showtunnelset',
+ 'type' : 'enum',
+ 'values' : ('details',),
+ 'optional' : True,
+ 'format' : 'show_tunnelset',
+ 'data' : { 'detail' : 'details' },
+ },
+ ),
+ }
+ )
+}
def tunnel_id_completion(prefix, completions):
query_url = "http://127.0.0.1:8000/rest/v1/showtunnel"