More fixes to ovs modules

Because this code deserves to be beautiful.

Change-Id: I0cc85d9a1103d4d4d7a19bf617838179197f9c90
This commit is contained in:
Arie
2016-09-27 12:18:57 +03:00
parent b2555a6ca8
commit 4f7d1de85e
12 changed files with 321 additions and 186 deletions

View File

@@ -1,23 +1,36 @@
# 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
#
# analyzer.py:
# 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.
# This file implements the following:
# 1. Analysis of the collected info
# 2. Report any problems
# 3. Report what is correct
#
import pprint
import re
import argparse
import subprocess
from itertools import combinations
import json
import os
from itertools import combinations
from common import settings, debug, get_router
from common import load_json, get_subnet, is_network_public
import pprint
import re
import subprocess
import yaml
from openstack_dashboard.don.ovs.common import debug
from openstack_dashboard.don.ovs.common import get_router
from openstack_dashboard.don.ovs.common import get_subnet
from openstack_dashboard.don.ovs.common import is_network_public
from openstack_dashboard.don.ovs.common import load_json
from openstack_dashboard.don.ovs.common import settings
tick = '✔'
cross = '✘'
@@ -146,9 +159,8 @@ def get_vm_credentials(config_file='credentials.yaml'):
try:
with open(config_file, 'r') as s:
return yaml.safe_load(s)
except IOError, e:
print '%s :%s' % (e.args[1], config_file)
raise
except IOError as e:
raise '%s :%s' % (e.args[1], config_file)
def test_ping(info):
@@ -203,7 +215,8 @@ def run_ovs_command(cmd, comment=''):
return subprocess.check_output(cmd,
shell=True,
stderr=subprocess.STDOUT,
universal_newlines=True).replace('\t', ' ')
universal_newlines=True).replace(
'\t', ' ')
def process_ovs_output(output):
@@ -361,8 +374,9 @@ def analyze(json_filename, params):
def check_args():
parser = argparse.ArgumentParser(description='Static analysis of output of commands',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser = argparse.ArgumentParser(
description='Static analysis of output of commands',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--debug', dest='debug',
help='Enable debugging',
default=True, action='store_true')

View File

@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
# 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

View File

@@ -1,10 +1,22 @@
# common.py: Common functions and data structures used by multiple modules.
# 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.
# common.py: Common functions and data structures used by multiple modules.
import json
import paramiko
import sys
import re
import pprint
import re
import subprocess
import sys
import yaml
# Program settings
@@ -17,7 +29,7 @@ settings = {
def debug(msg):
if settings['debug']:
if not sys.stdout == sys.__stdout__:
if sys.stdout != sys.__stdout__:
tmp = sys.stdout
sys.stdout = sys.__stdout__
print('DEBUG: ' + msg)
@@ -27,7 +39,7 @@ def debug(msg):
def error(msg):
if not sys.stdout == sys.__stdout__:
if sys.stdout != sys.__stdout__:
tmp = sys.stdout
sys.stdout = sys.__stdout__
print('ERROR: ' + msg)
@@ -37,7 +49,7 @@ def error(msg):
def warning(msg):
if not sys.stdout == sys.__stdout__:
if sys.stdout != sys.__stdout__:
tmp = sys.stdout
sys.stdout = sys.__stdout__
print('WARNING: ' + msg)
@@ -49,7 +61,7 @@ def warning(msg):
def status_update(msg):
# storing in log file for interactive display on UI
log = open('collector_log.txt', 'w')
if not sys.stdout == sys.__stdout__:
if sys.stdout != sys.__stdout__:
tmp = sys.stdout
sys.stdout = sys.__stdout__
print('STATUS: ' + msg)
@@ -61,12 +73,11 @@ def status_update(msg):
def dump_json(json_info, json_filename):
import json
try:
outfile = open(json_filename, "w")
except IOError, e:
print e
print 'Couldn\'t open <%s>; Redirecting output to stdout' % json_filename
except IOError as e:
print(e)
print('Couldn\'t open <%s>; Redirecting output to stdout' % json_filename)
outfile = sys.stdout
json.dump(json_info, outfile)
@@ -75,12 +86,11 @@ def dump_json(json_info, json_filename):
def load_json(json_filename):
import json
try:
infile = open(json_filename, "r")
except IOError, e:
print e
print 'Couldn\'t open <%s>; Error!' % json_filename
except IOError as e:
print(e)
print('Couldn\'t open <%s>; Error!' % json_filename)
return None
tmp = json.load(infile)
@@ -94,7 +104,7 @@ def connect_to_box(server, username, password, timeout=3):
try:
ssh.connect(server, username=username,
password=password, timeout=timeout)
except:
except Exception:
return None
return ssh
# def connect_to_box (server, username, password,timeout=3) :
@@ -108,7 +118,7 @@ def ssh_cmd(ssh, cmd):
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmd)
error = ssh_stderr.read()
if len(error):
print 'ERROR: ' + error
print('ERROR: ' + error)
output = ssh_stdout.read()
ssh_stdout.flush()
return output
@@ -230,13 +240,15 @@ def execute_cmd(cmd, sudo=False, shell=False, env=None):
shell=shell,
stderr=subprocess.STDOUT,
env=env,
universal_newlines=True).replace('\t', ' ')
universal_newlines=True).replace(
'\t', ' ')
def get_instance_ips(objs):
ip_list = []
for line in objs:
if re.search('^\+', line) or re.search('^$', line) or re.search('Networks', line):
if re.search('^\+', line) or re.search('^$', line) or re.search(
'Networks', line):
continue
parts = line.split('|')
parts = [x.strip() for x in parts]
@@ -247,7 +259,8 @@ def get_instance_ips(objs):
# excluding ipv6 ip
if len(entry.split(',')) > 1:
# network = entry.split('=')[0]
ip = filter(lambda a: re.search("(\d+\.\d+\.\d+\.\d+)", a) is not None,
ip = filter(lambda a: re.search("(\d+\.\d+\.\d+\.\d+)",
a) is not None,
entry.split('=')[1].split(','))[0].strip()
ip_list.append(ip)
else:
@@ -259,7 +272,8 @@ def get_router_names(objs):
routers = []
for line in objs:
if re.search('^\+', line) or re.search('^$', line) or re.search('external_gateway_info', line):
if re.search('^\+', line) or re.search('^$', line) or re.search(
'external_gateway_info', line):
continue
parts = line.split('|')
parts = [x.strip() for x in parts]
@@ -272,9 +286,8 @@ def get_router_names(objs):
def get_env(file_path):
try:
lines = open(file_path, 'r').read().splitlines()
except IOError, e:
print "%s :%s" % (e.args[1], file_path)
raise
except IOError as e:
raise "%s :%s" % (e.args[1], file_path)
env = {}
for line in lines:
if line.startswith('export'):
@@ -290,6 +303,5 @@ def get_vm_credentials(config_file='credentials.yaml'):
try:
with open(config_file, 'r') as s:
return yaml.safe_load(s)
except IOError, e:
print '%s :%s' % (e.args[1], config_file)
raise
except IOError as e:
raise '%s :%s' % (e.args[1], config_file)

View File

@@ -1,3 +1,15 @@
# 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 django import forms

View File

@@ -1,7 +1,19 @@
# 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.
import pprint
import sys
from common import load_json
from openstack_dashboard.don.ovs.common import load_json
if len(sys.argv) != 2:
print ('Usage: ' + sys.argv[0] + ' <json file to display>')

View File

@@ -1,12 +1,23 @@
# 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.
# ovs.py: Runs ovs-appctl command to check if A -> B flow is working fine.
#
#
import re
import argparse
import json
from common import debug, settings
from common import execute_cmd
import re
from openstack_dashboard.don.ovs.common import debug
from openstack_dashboard.don.ovs.common import execute_cmd
from openstack_dashboard.don.ovs.common import settings
params = {}
@@ -74,7 +85,8 @@ def ovs_test(src_port_id, dst_port_id, tag, ovs_bridge):
if vlan != tag:
output_dict['errors'].append(
'%s learnt on vlan %s but should have been learnt on vlan %s on port %s' % (smac, vlan, tag, port))
'%s learnt on vlan %s but should have been learnt on vlan %s on port %s' % (
smac, vlan, tag, port))
output_dict['pass'] = False
return False
output_dict['debugs'].append(
@@ -116,12 +128,14 @@ def ovs_test(src_port_id, dst_port_id, tag, ovs_bridge):
output_dict['debugs'].append(
'Packet forwarded to correct port %s' % egress_port)
else:
output_dict['errors'].append('Packet forwarded to incorrect port %s, expected %s' %
(egress_port, src_port_id))
output_dict['errors'].append(
'Packet forwarded to incorrect port %s, expected %s' %
(egress_port, src_port_id))
result = False
else:
output_dict['errors'].append('No egress port assigned to packet! Expected %s' %
src_port_id)
output_dict['errors'].append(
'No egress port assigned to packet! Expected %s' %
src_port_id)
result = False
output_dict['pass'] = result
@@ -132,17 +146,23 @@ def check_args():
global params
parser = argparse.ArgumentParser(
description='OVS test', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
description='OVS test',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--debug', dest='debug',
help='Enable debugging', default=False, action='store_true')
help='Enable debugging',
default=False, action='store_true')
parser.add_argument('--src_port_id', dest='src_port_id',
help='OVS src port id (required)', type=str, required=True)
help='OVS src port id (required)',
type=str, required=True)
parser.add_argument('--dst_port_id', dest='dst_port_id',
help='OVS dst port id (required)', type=str, required=True)
help='OVS dst port id (required)',
type=str, required=True)
parser.add_argument(
'--tag', dest='tag', help='VLAN tag of port (required)', type=str, required=True)
'--tag', dest='tag', help='VLAN tag of port (required)',
type=str, required=True)
parser.add_argument('--ovs_bridge', dest='ovs_bridge',
help='OVS bridge to be tested (required)', type=str, required=True)
help='OVS bridge to be tested (required)',
type=str, required=True)
args = parser.parse_args()
settings['debug'] = args.debug
@@ -165,12 +185,12 @@ def main():
ovs_success = ovs_test(src_port_id, dst_port_id, tag, ovs_bridge)
output_dict[
'comment'] = 'ovs %s port %s --> %s' % (ovs_bridge, src_port_id, dst_port_id)
'comment'] = 'ovs %s port %s --> %s' % (
ovs_bridge, src_port_id, dst_port_id)
output_dict['pass'] = ovs_success
a = json.dumps(output_dict, sort_keys=True, indent=4)
print a
pass
print(a)
if __name__ == "__main__":
main()

View File

@@ -1,19 +1,35 @@
# 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.
# path.py: Figures out a path between two IP addresses and then traces it
#
# HOWTO:
#
import re
import pprint
import subprocess
import argparse
import os.path
import signal
import json
import os.path
import pprint
import re
import signal
import subprocess
import time
from common import error, settings, debug, status_update
from common import load_json, execute_cmd, dump_json
from common import ip_to_intf, intf_to_namespace, router_to_namespace
from openstack_dashboard.don.ovs.common import debug
from openstack_dashboard.don.ovs.common import dump_json
from openstack_dashboard.don.ovs.common import error
from openstack_dashboard.don.ovs.common import execute_cmd
from openstack_dashboard.don.ovs.common import intf_to_namespace
from openstack_dashboard.don.ovs.common import ip_to_intf
from openstack_dashboard.don.ovs.common import load_json
from openstack_dashboard.don.ovs.common import router_to_namespace
from openstack_dashboard.don.ovs.common import settings
from openstack_dashboard.don.ovs.common import status_update
COUNT = 10 # how many packets to be captured by tcpdump
@@ -63,7 +79,8 @@ def qrouter_usable(qrouter, src_ip, dst_ip, username, passwd):
return False
def launch_ping(src_ip, dst_ip, username, passwd, count, timeout, qrouter, filename):
def launch_ping(src_ip, dst_ip, username, passwd,
count, timeout, qrouter, filename):
cmd = 'sudo ip netns exec ' + str(qrouter)
cmd += ' python ping.py --src_ip %s --dst_ip %s --username "%s" --passwd "%s" --count %d --timeout %d' % \
(src_ip, dst_ip, username, passwd, count, timeout)
@@ -95,7 +112,6 @@ def capture_network_packets(params, hop_list):
net_info['pids'].append(pid)
status_update(
'net: tcpdump launched with pid %d for interface %s' % (pid, dev))
pass
def capture_packets(params, tag='src', src_tag=None):
@@ -481,8 +497,6 @@ def path(params):
(src_ip, dst_ip))
path_same_network(params, next_hop_list)
pass
def main():

View File

@@ -1,19 +1,30 @@
# 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.
# ping.py: Runs a ping test from src_ip to dst_ip. Also provides analysis if
# things are not okay (TBD).
#
# HOWTO:
#
# For OpenStack, this program must be run from inside the correct namespace
#
# sudo ip netns exec qrouter-ac41aab2-f9c3-4a06-8eef-f909ee1e6e50 python ping.py 10.0.3.3 10.0.2.4 cirros "cubswin:)"
#
import re
import argparse
import json
from common import connect_to_box, ssh_cmd
from common import settings
import re
from openstack_dashboard.don.ovs.common import connect_to_box
from openstack_dashboard.don.ovs.common import settings
from openstack_dashboard.don.ovs.common import ssh_cmd
params = {}
@@ -56,8 +67,8 @@ def ping_test(src_ip, dst_ip, username, passwd, count, timeout):
result = True
break
except (KeyboardInterrupt, SystemExit):
print '\nkeyboardinterrupt caught (again)'
print '\n...Program Stopped Manually!'
print('\nkeyboardinterrupt caught (again)')
print('\n...Program Stopped Manually!')
raise
cmd_dict['pass'] = result
output_dict['command_list'].append(cmd_dict)
@@ -115,8 +126,7 @@ def main():
output_dict['comment'] = 'PING %s to %s' % (src_ip, dst_ip)
output_dict['pass'] = ping_success
a = json.dumps(output_dict, sort_keys=True, indent=4)
print a
print(json.dumps(output_dict, sort_keys=True, indent=4))
if __name__ == "__main__":
main()

View File

@@ -1,19 +1,36 @@
# 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
#
# plot.py: Generates an SVG file showing the networking internals of a compute node.
# http://www.apache.org/licenses/LICENSE-2.0
#
import pprint
import subprocess
import re
# 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.
import argparse
import sys
import pprint
import random
import re
import subprocess
import sys
from common import settings, debug, warning
from common import load_json, get_subnet
from common import get_vlan_tag, get_intf_ip, get_ip_network
from common import debug
from common import get_intf_ip
from common import get_ip_network
from common import get_subnet
from common import get_vlan_tag
from common import load_json
from common import settings
from common import warning
class DotGenerator:
class DotGenerator(object):
"""Generates an SVG file showing the network internals of
a compute node.
"""
def __init__(self, in_json_filename,
compute_dot_file, compute_svg_file,
@@ -236,34 +253,34 @@ class DotGenerator:
return port_count
def __html_row_open(self):
print '<TR>'
print('<TR>')
def __html_row_close(self):
print '</TR>'
print('</TR>')
def __html_row(self, name, rspan, cspan, color, tag=None):
# tags do not allow "-" (dash) in DOT language. Convert to "_"
# (underscore)
if tag:
print '<TD ROWSPAN="%d" COLSPAN="%d" BGCOLOR="%s" PORT="%s">%s</TD>' % (rspan, cspan, color, tag.replace('-', '_'), name)
print('<TD ROWSPAN="%d" COLSPAN="%d" BGCOLOR="%s" PORT="%s">%s</TD>' % (rspan, cspan, color, tag.replace('-', '_'), name))
else:
print '<TD ROWSPAN="%d" COLSPAN="%d" BGCOLOR="%s">%s</TD>' % (rspan, cspan, color, name)
print('<TD ROWSPAN="%d" COLSPAN="%d" BGCOLOR="%s">%s</TD>' % (rspan, cspan, color, name))
pass
def __html_edge(selft, src_tag, dst_tag, color, penwidth="4", style=None):
src_tag = src_tag.replace('-', '_')
dst_tag = dst_tag.replace('-', '_')
if not style:
print '%s:s -> %s:n [color = "%s", penwidth = "%s"]' % (src_tag,
print('%s:s -> %s:n [color = "%s", penwidth = "%s"]' % (src_tag,
dst_tag,
color,
penwidth)
penwidth))
else:
print '%s:s -> %s:n [color = "%s", penwidth = "%s", style="%s"]' % (src_tag,
print('%s:s -> %s:n [color = "%s", penwidth = "%s", style="%s"]' % (src_tag,
dst_tag,
color,
penwidth,
style)
style))
def __digraph_open(self, tag):
msg = 'digraph DON_' + tag + ' {' + \
@@ -276,36 +293,36 @@ concentrate = true;
compound = true;
edge [dir=none]
'''
print msg
print(msg)
def __digraph_close(self):
msg = '\n}\n'
print msg
print(msg)
def __cluster_name(self, tag, col_span, color="white"):
self.__html_row_open()
port = tag.replace(' ', '').replace('-', '_')
print '<TD COLSPAN="%d" BORDER="0" BGCOLOR="%s" PORT="%s">%s</TD>' % (col_span, color, port, tag)
print('<TD COLSPAN="%d" BORDER="0" BGCOLOR="%s" PORT="%s">%s</TD>' % (col_span, color, port, tag))
self.__html_row_close()
def __cluster_open_plain(self, tag, label=None):
print 'subgraph cluster_%s {' % (tag)
print 'style=filled'
print('subgraph cluster_%s {' % (tag))
print('style=filled')
if label:
print 'label="%s"' % (label)
print('label="%s"' % (label))
def __cluster_close_plain(self):
print '}\n'
print('}\n')
def __cluster_open(self, tag, color="white"):
print 'subgraph cluster_%s {' % (tag)
print '%s [ shape = plaintext, label = <' % (tag)
print '<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="5" CELLPADDING="5" BGCOLOR="%s">' % (color)
print('subgraph cluster_%s {' % (tag))
print('%s [ shape = plaintext, label = <' % (tag))
print('<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="5" CELLPADDING="5" BGCOLOR="%s">' % (color))
pass
def __cluster_close(self):
print '</TABLE>>];\n'
print '}\n'
print('</TABLE>>];\n')
print('}\n')
pass
def __plot_title_edges(self, tag):
@@ -451,7 +468,8 @@ edge [dir=none]
if br_int['ports'].has_key(qvo_port):
tag = br_int['ports'][qvo_port]['tag']
self.__html_row('VLAN tag:' + tag, row_span, col_span,
self.__get_vlan_color(tag), qvo_port + 'tag_' + tag)
self.__get_vlan_color(tag),
qvo_port + 'tag_' + tag)
self.__html_row_close()
col_span = self.__get_total_vm_port_count()
@@ -468,9 +486,7 @@ edge [dir=none]
self.__html_row_close()
self.__cluster_close()
pass
# TODO
def __plot_br_ex_to_br_int(self):
namespaces = self.info['namespaces']
@@ -492,7 +508,6 @@ edge [dir=none]
dst_tag = 'network_br_int:' + intf
self.__html_edge(src_tag, dst_tag,
self.__get_color('edge'))
pass
def __plot_br_ex_network(self):
routers = self.info['routers']
@@ -571,9 +586,11 @@ edge [dir=none]
port_id = '[' + br_int['ports'][intf]['id'] + '] '
color = self.__get_vlan_color(tag, intf)
self.__html_row(
port_id + intf, row_span, col_span, color, intf)
port_id + intf, row_span,
col_span, color, intf)
# now plot the corresponding tap interface
(tap_nms, tap) = self.__get_tap_interface(nms, intf)
(tap_nms, tap) = self.__get_tap_interface(nms,
intf)
tag = br_int['ports'][tap]['tag']
color = self.__get_vlan_color(tag, tap)
port_id = '[' + br_int['ports'][tap]['id'] + '] '
@@ -602,7 +619,8 @@ edge [dir=none]
tag = br_int['ports'][tap_intf]['tag']
self.__html_row('VLAN tag:' + tag, row_span, col_span,
self.__get_vlan_color(tag), tap_intf + 'tag_' + tag)
self.__get_vlan_color(tag),
tap_intf + 'tag_' + tag)
self.__html_row_close()
@@ -695,7 +713,6 @@ edge [dir=none]
color = self.__get_edge_color(src_tag, dst_tag)
self.__html_edge(src_tag, dst_tag, color)
break
pass
def __plot_linuxbridge_to_br_int(self):
brctl = self.info['brctl']
@@ -713,7 +730,6 @@ edge [dir=none]
color = self.__get_edge_color(src_tag, dst_tag)
self.__html_edge(src_tag, dst_tag, color)
break
pass
def __plot_br_int_to_br_tun(self, tag):
br_int = self.info['bridges']['br-int']['ports']
@@ -734,7 +750,6 @@ edge [dir=none]
self.__html_edge(src_tag, dst_tag,
self.__get_color('edge'))
return
pass
def plot_combined(self):
self.outfile = open(self.combined_dot_file, 'w')
@@ -845,12 +860,15 @@ edge [dir=none]
def check_args():
parser = argparse.ArgumentParser(description='Plot the compute node network internals',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser = argparse.ArgumentParser(
description='Plot the compute node network internals',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--debug', dest='debug',
help='Enable debugging', default=True, action='store_true')
help='Enable debugging',
default=True, action='store_true')
parser.add_argument('--info_file', dest='info_file',
help='Info is read in JSON format in this file', default="don.json", type=str)
help='Info is read in JSON format in this file',
default="don.json", type=str)
parser.add_argument('--compute_file', dest='compute_file',
help='[compute_file].dot and [compute_file].svg will be generated for compute node', default="compute", type=str)
parser.add_argument('--network_file', dest='network_file',
@@ -858,7 +876,8 @@ def check_args():
parser.add_argument('--combined_file', dest='combined_file',
help='[combined_file].dot and [combined_file].svg will be generated', default="don", type=str)
parser.add_argument('--highlight_file', dest='highlight_file',
help='pass and fail node are specified in this file', default=None, type=str)
help='pass and fail node are specified in this file',
default=None, type=str)
args = parser.parse_args()

View File

@@ -1,13 +1,23 @@
# 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.
# run_nms_cmd.py: This needs to be run from inside appropriate namespace
#
# sudo ip netns exec qrouter-ac41aab2-f9c3-4a06-8eef-f909ee1e6e50 python # run_nms_cmd.py "command"
#
import argparse
import json
from common import connect_to_box, ssh_cmd
from common import settings
from openstack_dashboard.don.ovs.common import connect_to_box
from openstack_dashboard.don.ovs.common import settings
from openstack_dashboard.don.ovs.common import ssh_cmd
params = {}
@@ -45,8 +55,8 @@ def run_nms_cmd(args):
cmd_dict['cmd'] = cmd
cmd_dict['output'] = output
except (KeyboardInterrupt, SystemExit):
print '\nkeyboardinterrupt caught (again)'
print '\n...Program Stopped Manually!'
print('\nkeyboardinterrupt caught (again)')
print('\n...Program Stopped Manually!')
result = False
raise
cmd_dict['pass'] = result
@@ -58,17 +68,23 @@ def check_args():
global params
parser = argparse.ArgumentParser(
description='Run command from inside nms', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
description='Run command from inside nms',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--debug', dest='debug',
help='Enable debugging', default=False, action='store_true')
help='Enable debugging',
default=False, action='store_true')
parser.add_argument('--host_ip', dest='host_ip',
help='IP where the command will be run', type=str, required=True)
help='IP where the command will be run',
type=str, required=True)
parser.add_argument('--username', dest='username',
help='SSH login username (required)', type=str, required=True)
help='SSH login username (required)',
type=str, required=True)
parser.add_argument('--passwd', dest='passwd',
help='SSH login passwd (required)', type=str, required=True)
help='SSH login passwd (required)',
type=str, required=True)
parser.add_argument('--cmd', dest='cmd',
help='cmd to be run', type=str, required=True)
help='cmd to be run',
type=str, required=True)
args = parser.parse_args()
settings['debug'] = args.debug
@@ -85,8 +101,7 @@ def main():
output_dict['pass'] = run_nms_cmd(params)
a = json.dumps(output_dict, sort_keys=True, indent=4)
print a
print(json.dumps(output_dict, sort_keys=True, indent=4))
if __name__ == "__main__":
main()

View File

@@ -1,11 +1,19 @@
# 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 django.conf.urls import patterns
from django.conf.urls import url
from don.ovs.views \
import IndexView
from . import views
from don.ovs.views import IndexView
import openstack_dashboard.don.ovs.views as views
urlpatterns = patterns(
'',

View File

@@ -1,20 +1,33 @@
from horizon import views
from django.http import HttpResponse
# 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 django.conf import settings
from plot import DotGenerator
import os
import subprocess
from .forms import PingForm
# from django.shortcuts import render_to_response
from horizon import messages
import analyzer
import path
from common import execute_cmd, get_instance_ips, get_env, get_router_names
import json
import shlex
from django.http import HttpResponse
from django.shortcuts import render
from forms import PingForm
from horizon import messages
from horizon import views
import json
import os
import shlex
import subprocess
import openstack_dashboard.don.ovs.analyzer as analyzer
from openstack_dashboard.don.ovs.common import execute_cmd
from openstack_dashboard.don.ovs.common import get_env
from openstack_dashboard.don.ovs.common import get_instance_ips
from openstack_dashboard.don.ovs.common import get_router_names
import openstack_dashboard.don.ovs.path as path
from openstack_dashboard.don.ovs.plot import DotGenerator
class IndexView(views.APIView):
@@ -31,8 +44,6 @@ def index(request):
def view(request):
# import pdb
# pdb.set_trace()
pwd = settings.ROOT_PATH # +'/openstack_dashboard/dashboards/admin/don/'
JSON_FILE = pwd + '/don/ovs/don.json'
@@ -53,7 +64,6 @@ def view(request):
COMBINED_SVG_FILE = static_path + '/don/don.svg'
macro = {}
# return HttpResponseRedirect('static/view.html')
plotter = DotGenerator(JSON_FILE,
COMPUTE_DOT_FILE,
@@ -72,12 +82,11 @@ def view(request):
plotter.plot_combined()
plotter.generate_combined_svg()
# return HttpResponseRedirect('static/view.html')
return render(request, "don/ovs/views.html", macro)
def analyze(request):
# pwd = settings.BASE_DIR
pwd = settings.ROOT_PATH
JSON_FILE = pwd + '/don/ovs/don.json'
@@ -89,14 +98,9 @@ def analyze(request):
'test:ovs': True,
'test:report_file': pwd + '/don/templates/don/don.report.html',
}
print "params ====> ", params
print("params ====> ", params)
analyzer.analyze(JSON_FILE, params)
# output = analyzer.analyze(JSON_FILE, params)
# html = '<html><body>Output: %s</body></html>' % output
# return HttpResponse(html)
# return HttpResponseRedirect('/static/don.report.html')
return render(request, "don/ovs/analyze.html")
# return render_to_response('don/ovs/analyze.html')
def test(request):
@@ -111,13 +115,10 @@ def ping(request):
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
src_ip = form.cleaned_data['src_ip']
dst_ip = form.cleaned_data['dst_ip']
router = form.cleaned_data['router']
# html = '<html><body>SIP: %s DIP: %s router: %s</body></html>' % (src_ip, dst_ip, router)
# return HttpResponse(html)
static_path = settings.STATIC_ROOT
pwd = settings.ROOT_PATH
JSON_FILE = pwd + '/don/ovs/don.json'
@@ -148,7 +149,6 @@ def ping(request):
NETWORK_SVG_FILE = None
COMBINED_DOT_FILE = static_path + '/don/ping.dot'
COMBINED_SVG_FILE = static_path + '/don/ping.svg'
# HIGHLIGHT_FILE = pwd + '/don/ovs/static/ping.html'
HIGHLIGHT_FILE = static_path + '/don/ping.html'
plotter = DotGenerator(JSON_FILE,
@@ -163,7 +163,6 @@ def ping(request):
plotter.plot_combined()
plotter.generate_combined_svg()
# return HttpResponseRedirect('/static/path.html')
return render(request, 'don/ovs/path.html')
# if a GET (or any other method) we'll create a blank form
@@ -177,7 +176,8 @@ def ping(request):
ip_list = get_instance_ips(output)
ip_list.sort()
router_op = execute_cmd(
['neutron', 'router-list'], sudo=False, shell=False, env=myenv).split('\n')
['neutron', 'router-list'],
sudo=False, shell=False, env=myenv).split('\n')
router_list = get_router_names(router_op)
router_list.sort()
# insert first value of select menu
@@ -197,11 +197,11 @@ def collect(request):
status = 0
BASE_DIR = settings.ROOT_PATH
# CUR_DIR = os.getcwd()
os.chdir(BASE_DIR + '/don/ovs')
cmd = 'sudo python collector.py'
for line in run_command(cmd):
if line.startswith('STATUS:') and line.find('Writing collected info') != -1:
if line.startswith('STATUS:') and line.find(
'Writing collected info') != -1:
status = 1
macro['collect_status'] = \
"Collecton successful. Click visualize to display"
@@ -230,4 +230,5 @@ def get_status(request):
BASE_DIR = settings.ROOT_PATH + '/don/ovs/'
status = open(BASE_DIR + 'collector_log.txt', 'r').readline()
if status != " " and status != '\n':
return HttpResponse(json.dumps({'status': status}), content_type="application/json")
return HttpResponse(json.dumps(
{'status': status}), content_type="application/json")