Skip to content

Commit 8268635

Browse files
author
Salvatore Orlando
committed
Adding Missing file to source control
1 parent 9f321ff commit 8268635

9 files changed

Lines changed: 648 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Copyright (C) 2012 Cloud.com, Inc. All rights reserved.
3+
*
4+
* This software is licensed under the GNU General Public License v3 or later.
5+
*
6+
* It is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or any later version.
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*
17+
*/
18+
package com.cloud.network.ovs;
19+
20+
import com.cloud.agent.api.Command;
21+
22+
public class OvsDestroyBridgeCommand extends Command {
23+
24+
long networkId;
25+
26+
public OvsDestroyBridgeCommand(long networkId) {
27+
this.networkId = networkId;
28+
}
29+
30+
public long getNetworkId() {
31+
return networkId;
32+
}
33+
34+
@Override
35+
public boolean executeInSequence() {
36+
return true;
37+
}
38+
39+
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# Common function for Cloudstack's XenAPI plugins
2+
#
3+
# Copyright (C) 2012 Citrix Systems
4+
5+
import ConfigParser
6+
import logging
7+
import os
8+
import subprocess
9+
10+
from time import localtime, asctime
11+
12+
DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s"
13+
DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
14+
DEFAULT_LOG_FILE = "/var/log/cloudstack_plugins.log"
15+
16+
PLUGIN_CONFIG_PATH='/etc/xensource/cloudstack_plugins.conf'
17+
OVSDB_PID_PATH = "/var/run/openvswitch/ovsdb-server.pid"
18+
OVSDB_DAEMON_PATH = "ovsdb-server"
19+
OVS_PID_PATH = "/var/run/openvswitch/ovs-vswitchd.pid"
20+
OVS_DAEMON_PATH = "ovs-vswitchd"
21+
VSCTL_PATH='/usr/bin/ovs-vsctl'
22+
OFCTL_PATH='/usr/bin/ovs-ofctl'
23+
XE_PATH= "/opt/xensource/bin/xe"
24+
25+
class PluginError(Exception):
26+
"""Base Exception class for all plugin errors."""
27+
def __init__(self, *args):
28+
Exception.__init__(self, *args)
29+
30+
def setup_logging(log_file=None):
31+
debug = False
32+
verbose = False
33+
log_format = DEFAULT_LOG_FORMAT
34+
log_date_format = DEFAULT_LOG_DATE_FORMAT
35+
# try to read plugin configuration file
36+
if os.path.exists(PLUGIN_CONFIG_PATH):
37+
config = ConfigParser.ConfigParser()
38+
config.read(PLUGIN_CONFIG_PATH)
39+
try:
40+
options = config.options('LOGGING')
41+
if 'debug' in options:
42+
debug = config.getboolean('LOGGING','debug')
43+
if 'verbose' in options:
44+
verbose = config.getboolean('LOGGING','verbose')
45+
if 'format' in options:
46+
log_format = config.get('LOGGING','format')
47+
if 'date_format' in options:
48+
log_date_format = config.get('LOGGING','date_format')
49+
if 'file' in options:
50+
log_file_2 = config.get('LOGGING','file')
51+
except ValueError:
52+
# configuration file contained invalid attributes
53+
# ignore them
54+
pass
55+
except ConfigParser.NoSectionError:
56+
# Missing 'Logging' section in configuration file
57+
pass
58+
59+
root_logger = logging.root
60+
if debug:
61+
root_logger.setLevel(logging.DEBUG)
62+
elif verbose:
63+
root_logger.setLevel(logging.INFO)
64+
else:
65+
root_logger.setLevel(logging.WARNING)
66+
formatter = logging.Formatter(log_format, log_date_format)
67+
68+
log_filename = log_file or log_file_2 or DEFAULT_LOG_FILE
69+
70+
logfile_handler = logging.FileHandler(log_filename)
71+
logfile_handler.setFormatter(formatter)
72+
root_logger.addHandler(logfile_handler)
73+
74+
75+
def do_cmd(cmd):
76+
"""Abstracts out the basics of issuing system commands. If the command
77+
returns anything in stderr, a PluginError is raised with that information.
78+
Otherwise, the output from stdout is returned.
79+
"""
80+
81+
pipe = subprocess.PIPE
82+
logging.debug("Executing:%s", cmd)
83+
proc = subprocess.Popen(cmd, shell=False, stdin=pipe, stdout=pipe,
84+
stderr=pipe, close_fds=True)
85+
ret_code = proc.wait()
86+
err = proc.stderr.read()
87+
if ret_code:
88+
logging.debug("The command exited with the error code: " +
89+
"%s (stderr output:%s)" % (ret_code, err))
90+
raise PluginError(err)
91+
output = proc.stdout.read()
92+
if output.endswith('\n'):
93+
output = output[:-1]
94+
return output
95+
96+
97+
def _is_process_run (pidFile, name):
98+
try:
99+
fpid = open (pidFile, "r")
100+
pid = fpid.readline ()
101+
fpid.close ()
102+
except IOError, e:
103+
return -1
104+
105+
pid = pid[:-1]
106+
ps = os.popen ("ps -ae")
107+
for l in ps:
108+
if pid in l and name in l:
109+
ps.close ()
110+
return 0
111+
112+
ps.close ()
113+
return -2
114+
115+
def _is_tool_exist (name):
116+
if os.path.exists(name):
117+
return 0
118+
return -1
119+
120+
121+
def check_switch ():
122+
global result
123+
124+
ret = _is_process_run (OVSDB_PID_PATH, OVSDB_DAEMON_PATH)
125+
if ret < 0:
126+
if ret == -1: return "NO_DB_PID_FILE"
127+
if ret == -2: return "DB_NOT_RUN"
128+
129+
ret = _is_process_run (OVS_PID_PATH, OVS_DAEMON_PATH)
130+
if ret < 0:
131+
if ret == -1: return "NO_SWITCH_PID_FILE"
132+
if ret == -2: return "SWITCH_NOT_RUN"
133+
134+
if _is_tool_exist (VSCTL_PATH) < 0:
135+
return "NO_VSCTL"
136+
137+
if _is_tool_exist (OFCTL_PATH) < 0:
138+
return "NO_OFCTL"
139+
140+
return "SUCCESS"
141+
142+
143+
def _build_flow_expr(**kwargs):
144+
is_delete_expr = kwargs.get('delete', False)
145+
flow = ""
146+
if not is_delete_expr:
147+
flow = "hard_timeout=%s,idle_timeout=%s,priority=%s"\
148+
% (kwargs.get('hard_timeout','0'),
149+
kwargs.get('idle_timeout','0'),
150+
kwargs.get('priority','1'))
151+
in_port = 'in_port' in kwargs and ",in_port=%s" % kwargs['in_port'] or ''
152+
dl_type = 'dl_type' in kwargs and ",dl_type=%s" % kwargs['dl_type'] or ''
153+
dl_src = 'dl_src' in kwargs and ",dl_src=%s" % kwargs['dl_src'] or ''
154+
dl_dst = 'dl_dst' in kwargs and ",dl_dst=%s" % kwargs['dl_dst'] or ''
155+
nw_src = 'nw_src' in kwargs and ",nw_src=%s" % kwargs['nw_src'] or ''
156+
nw_dst = 'nw_dst' in kwargs and ",nw_dst=%s" % kwargs['nw_dst'] or ''
157+
proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or ''
158+
ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or ''
159+
flow = (flow + in_port + dl_type + dl_src + dl_dst +
160+
(ip or proto) + nw_src + nw_dst)
161+
return flow
162+
163+
164+
def add_flow(bridge, **kwargs):
165+
"""
166+
Builds a flow expression for **kwargs and adds the flow entry
167+
to an Open vSwitch instance
168+
"""
169+
flow = _build_flow_expr(**kwargs)
170+
actions = 'actions' in kwargs and ",actions=%s" % kwargs['actions'] or ''
171+
flow = flow + actions
172+
addflow = [OFCTL_PATH, "add-flow", bridge, flow]
173+
do_cmd(addflow)
174+
175+
176+
def del_flows(bridge, **kwargs):
177+
"""
178+
Removes flows according to criteria passed as keyword.
179+
"""
180+
flow = _build_flow_expr(delete=True, **kwargs)
181+
# out_port condition does not exist for all flow commands
182+
out_port = 'out_port' in kwargs and ",out_port=%s" % kwargs['out_port'] or ''
183+
flow = flow + out_port
184+
delFlow = [OFCTL_PATH, 'del-flows', bridge, flow]
185+
do_cmd(delFlow)
186+
187+
188+
def del_all_flows(bridge):
189+
delFlow = [OFCTL_PATH, "del-flows", bridge]
190+
do_cmd(delFlow)
191+
192+
normalFlow = "priority=0 idle_timeout=0 hard_timeout=0 actions=normal"
193+
add_flow(bridge, normalFlow)
194+
195+
196+
def del_port(bridge, port):
197+
delPort = [VSCTL_PATH, "del-port", bridge, port]
198+
do_cmd(delPort)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[LOGGING]
2+
# Logging options for Cloudstack plugins
3+
debug = True
4+
verbose = True
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Adds or removes per-VIF flows
2+
SUBSYSTEM=="xen-backend", KERNEL=="vif*", RUN+="/usr/bin/python /etc/xapi.d/plugins/ovs-vif-flows.py $env{ACTION} %k"
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# A simple script for enabling and disabling per-vif rules for explicitly
2+
# allowing broadcast/multicast traffic on the port where the VIF is attached
3+
#
4+
# Copyright (C) 2012 Citrix Systems
5+
6+
import os
7+
import sys
8+
9+
import cloudstack_pluginlib as pluginlib
10+
11+
12+
def clear_flows(bridge, this_vif_ofport, vif_ofports):
13+
# Remove flow entries originating from given ofport
14+
pluginlib.del_flows(bridge, in_port=this_vif_ofport)
15+
# The following will remove the port being delete from actions
16+
pluginlib.add_flow(bridge, priority=1100,
17+
dl_dst='ff:ff:ff:ff:ff:ff', actions=action)
18+
pluginlib.add_flow(bridge, priority=1100,
19+
nw_dst='224.0.0.0/24', actions=action)
20+
21+
22+
def apply_flows(bridge, this_vif_ofport, vif_ofports):
23+
action = "".join("output:%s," %ofport
24+
for ofport in vif_ofports)[:-1]
25+
# Ensure {b|m}casts sent from VIF ports are always allowed
26+
pluginlib.add_flow(bridge, priority=1200,
27+
in_port=this_vif_ofport,
28+
dl_dst='ff:ff:ff:ff:ff:ff',
29+
actions='NORMAL')
30+
pluginlib.add_flow(bridge, priority=1200,
31+
in_port=this_vif_ofport,
32+
nw_dst='224.0.0.0/24',
33+
actions='NORMAL')
34+
# Ensure {b|m}casts are always propagated to VIF ports
35+
pluginlib.add_flow(bridge, priority=1100,
36+
dl_dst='ff:ff:ff:ff:ff:ff', actions=action)
37+
pluginlib.add_flow(bridge, priority=1100,
38+
nw_dst='224.0.0.0/24', actions=action)
39+
40+
41+
def main(command, vif_raw):
42+
if command not in ('online', 'offline'):
43+
return
44+
# TODO (very important)
45+
# Quit immediately if networking is NOT being managed by the OVS tunnel manager
46+
vif_name, dom_id, vif_index = vif_raw.split('-')
47+
# validate vif and dom-id
48+
this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index)
49+
50+
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif])
51+
52+
# find xs network for this bridge, verify is used for ovs tunnel network
53+
xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list",
54+
"bridge=%s" % bridge, "--minimal"])
55+
result = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get",
56+
"uuid=%s" % xs_nw_uuid,
57+
"param-name=other-config",
58+
"param-key=is-ovs-tun-network", "--minimal"])
59+
60+
if result != 'True':
61+
return
62+
63+
vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge])
64+
if vlan != '0':
65+
# We need the REAL bridge name
66+
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
67+
'br-to-parent', bridge])
68+
# For the OVS version shipped with XS56FP1 we need to retrieve
69+
# the ofport number for all interfaces
70+
vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
71+
'list-ports', bridge])
72+
vifs = vsctl_output.split('\n')
73+
vif_ofports = []
74+
for vif in vifs:
75+
vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get',
76+
'Interface', vif, 'ofport'])
77+
if this_vif == vif:
78+
this_vif_ofport = vif_ofport
79+
vif_ofports.append(vif_ofport)
80+
# So regardless of whether the VIF is brought online or offline we
81+
# will always execute the same action
82+
if command == 'offline':
83+
clear_flows(bridge, this_vif_ofport, vif_ofports)
84+
85+
if command == 'online':
86+
apply_flows(bridge, this_vif_ofport, vif_ofports)
87+
88+
89+
90+
91+
if __name__ == "__main__":
92+
if len(sys.argv) != 3:
93+
print "usage: %s [online|offline] vif-domid-idx" % \
94+
os.path.basename(sys.argv[0])
95+
sys.exit(1)
96+
else:
97+
command, vif_raw = sys.argv[1:3]
98+
main(command, vif_raw)

0 commit comments

Comments
 (0)