Adding Missing file to source control

This commit is contained in:
Salvatore Orlando 2012-03-14 14:03:28 +00:00
parent 9f321ffeac
commit 8268635846
9 changed files with 648 additions and 0 deletions

View File

@ -0,0 +1,39 @@
/**
* Copyright (C) 2012 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs;
import com.cloud.agent.api.Command;
public class OvsDestroyBridgeCommand extends Command {
long networkId;
public OvsDestroyBridgeCommand(long networkId) {
this.networkId = networkId;
}
public long getNetworkId() {
return networkId;
}
@Override
public boolean executeInSequence() {
return true;
}
}

View File

@ -0,0 +1,198 @@
# Common function for Cloudstack's XenAPI plugins
#
# Copyright (C) 2012 Citrix Systems
import ConfigParser
import logging
import os
import subprocess
from time import localtime, asctime
DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s"
DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
DEFAULT_LOG_FILE = "/var/log/cloudstack_plugins.log"
PLUGIN_CONFIG_PATH='/etc/xensource/cloudstack_plugins.conf'
OVSDB_PID_PATH = "/var/run/openvswitch/ovsdb-server.pid"
OVSDB_DAEMON_PATH = "ovsdb-server"
OVS_PID_PATH = "/var/run/openvswitch/ovs-vswitchd.pid"
OVS_DAEMON_PATH = "ovs-vswitchd"
VSCTL_PATH='/usr/bin/ovs-vsctl'
OFCTL_PATH='/usr/bin/ovs-ofctl'
XE_PATH= "/opt/xensource/bin/xe"
class PluginError(Exception):
"""Base Exception class for all plugin errors."""
def __init__(self, *args):
Exception.__init__(self, *args)
def setup_logging(log_file=None):
debug = False
verbose = False
log_format = DEFAULT_LOG_FORMAT
log_date_format = DEFAULT_LOG_DATE_FORMAT
# try to read plugin configuration file
if os.path.exists(PLUGIN_CONFIG_PATH):
config = ConfigParser.ConfigParser()
config.read(PLUGIN_CONFIG_PATH)
try:
options = config.options('LOGGING')
if 'debug' in options:
debug = config.getboolean('LOGGING','debug')
if 'verbose' in options:
verbose = config.getboolean('LOGGING','verbose')
if 'format' in options:
log_format = config.get('LOGGING','format')
if 'date_format' in options:
log_date_format = config.get('LOGGING','date_format')
if 'file' in options:
log_file_2 = config.get('LOGGING','file')
except ValueError:
# configuration file contained invalid attributes
# ignore them
pass
except ConfigParser.NoSectionError:
# Missing 'Logging' section in configuration file
pass
root_logger = logging.root
if debug:
root_logger.setLevel(logging.DEBUG)
elif verbose:
root_logger.setLevel(logging.INFO)
else:
root_logger.setLevel(logging.WARNING)
formatter = logging.Formatter(log_format, log_date_format)
log_filename = log_file or log_file_2 or DEFAULT_LOG_FILE
logfile_handler = logging.FileHandler(log_filename)
logfile_handler.setFormatter(formatter)
root_logger.addHandler(logfile_handler)
def do_cmd(cmd):
"""Abstracts out the basics of issuing system commands. If the command
returns anything in stderr, a PluginError is raised with that information.
Otherwise, the output from stdout is returned.
"""
pipe = subprocess.PIPE
logging.debug("Executing:%s", cmd)
proc = subprocess.Popen(cmd, shell=False, stdin=pipe, stdout=pipe,
stderr=pipe, close_fds=True)
ret_code = proc.wait()
err = proc.stderr.read()
if ret_code:
logging.debug("The command exited with the error code: " +
"%s (stderr output:%s)" % (ret_code, err))
raise PluginError(err)
output = proc.stdout.read()
if output.endswith('\n'):
output = output[:-1]
return output
def _is_process_run (pidFile, name):
try:
fpid = open (pidFile, "r")
pid = fpid.readline ()
fpid.close ()
except IOError, e:
return -1
pid = pid[:-1]
ps = os.popen ("ps -ae")
for l in ps:
if pid in l and name in l:
ps.close ()
return 0
ps.close ()
return -2
def _is_tool_exist (name):
if os.path.exists(name):
return 0
return -1
def check_switch ():
global result
ret = _is_process_run (OVSDB_PID_PATH, OVSDB_DAEMON_PATH)
if ret < 0:
if ret == -1: return "NO_DB_PID_FILE"
if ret == -2: return "DB_NOT_RUN"
ret = _is_process_run (OVS_PID_PATH, OVS_DAEMON_PATH)
if ret < 0:
if ret == -1: return "NO_SWITCH_PID_FILE"
if ret == -2: return "SWITCH_NOT_RUN"
if _is_tool_exist (VSCTL_PATH) < 0:
return "NO_VSCTL"
if _is_tool_exist (OFCTL_PATH) < 0:
return "NO_OFCTL"
return "SUCCESS"
def _build_flow_expr(**kwargs):
is_delete_expr = kwargs.get('delete', False)
flow = ""
if not is_delete_expr:
flow = "hard_timeout=%s,idle_timeout=%s,priority=%s"\
% (kwargs.get('hard_timeout','0'),
kwargs.get('idle_timeout','0'),
kwargs.get('priority','1'))
in_port = 'in_port' in kwargs and ",in_port=%s" % kwargs['in_port'] or ''
dl_type = 'dl_type' in kwargs and ",dl_type=%s" % kwargs['dl_type'] or ''
dl_src = 'dl_src' in kwargs and ",dl_src=%s" % kwargs['dl_src'] or ''
dl_dst = 'dl_dst' in kwargs and ",dl_dst=%s" % kwargs['dl_dst'] or ''
nw_src = 'nw_src' in kwargs and ",nw_src=%s" % kwargs['nw_src'] or ''
nw_dst = 'nw_dst' in kwargs and ",nw_dst=%s" % kwargs['nw_dst'] or ''
proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or ''
ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or ''
flow = (flow + in_port + dl_type + dl_src + dl_dst +
(ip or proto) + nw_src + nw_dst)
return flow
def add_flow(bridge, **kwargs):
"""
Builds a flow expression for **kwargs and adds the flow entry
to an Open vSwitch instance
"""
flow = _build_flow_expr(**kwargs)
actions = 'actions' in kwargs and ",actions=%s" % kwargs['actions'] or ''
flow = flow + actions
addflow = [OFCTL_PATH, "add-flow", bridge, flow]
do_cmd(addflow)
def del_flows(bridge, **kwargs):
"""
Removes flows according to criteria passed as keyword.
"""
flow = _build_flow_expr(delete=True, **kwargs)
# out_port condition does not exist for all flow commands
out_port = 'out_port' in kwargs and ",out_port=%s" % kwargs['out_port'] or ''
flow = flow + out_port
delFlow = [OFCTL_PATH, 'del-flows', bridge, flow]
do_cmd(delFlow)
def del_all_flows(bridge):
delFlow = [OFCTL_PATH, "del-flows", bridge]
do_cmd(delFlow)
normalFlow = "priority=0 idle_timeout=0 hard_timeout=0 actions=normal"
add_flow(bridge, normalFlow)
def del_port(bridge, port):
delPort = [VSCTL_PATH, "del-port", bridge, port]
do_cmd(delPort)

View File

@ -0,0 +1,4 @@
[LOGGING]
# Logging options for Cloudstack plugins
debug = True
verbose = True

View File

@ -0,0 +1,2 @@
# Adds or removes per-VIF flows
SUBSYSTEM=="xen-backend", KERNEL=="vif*", RUN+="/usr/bin/python /etc/xapi.d/plugins/ovs-vif-flows.py $env{ACTION} %k"

View File

@ -0,0 +1,98 @@
# A simple script for enabling and disabling per-vif rules for explicitly
# allowing broadcast/multicast traffic on the port where the VIF is attached
#
# Copyright (C) 2012 Citrix Systems
import os
import sys
import cloudstack_pluginlib as pluginlib
def clear_flows(bridge, this_vif_ofport, vif_ofports):
# Remove flow entries originating from given ofport
pluginlib.del_flows(bridge, in_port=this_vif_ofport)
# The following will remove the port being delete from actions
pluginlib.add_flow(bridge, priority=1100,
dl_dst='ff:ff:ff:ff:ff:ff', actions=action)
pluginlib.add_flow(bridge, priority=1100,
nw_dst='224.0.0.0/24', actions=action)
def apply_flows(bridge, this_vif_ofport, vif_ofports):
action = "".join("output:%s," %ofport
for ofport in vif_ofports)[:-1]
# Ensure {b|m}casts sent from VIF ports are always allowed
pluginlib.add_flow(bridge, priority=1200,
in_port=this_vif_ofport,
dl_dst='ff:ff:ff:ff:ff:ff',
actions='NORMAL')
pluginlib.add_flow(bridge, priority=1200,
in_port=this_vif_ofport,
nw_dst='224.0.0.0/24',
actions='NORMAL')
# Ensure {b|m}casts are always propagated to VIF ports
pluginlib.add_flow(bridge, priority=1100,
dl_dst='ff:ff:ff:ff:ff:ff', actions=action)
pluginlib.add_flow(bridge, priority=1100,
nw_dst='224.0.0.0/24', actions=action)
def main(command, vif_raw):
if command not in ('online', 'offline'):
return
# TODO (very important)
# Quit immediately if networking is NOT being managed by the OVS tunnel manager
vif_name, dom_id, vif_index = vif_raw.split('-')
# validate vif and dom-id
this_vif = "%s%s.%s" % (vif_name, dom_id, vif_index)
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif])
# find xs network for this bridge, verify is used for ovs tunnel network
xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list",
"bridge=%s" % bridge, "--minimal"])
result = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=is-ovs-tun-network", "--minimal"])
if result != 'True':
return
vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge])
if vlan != '0':
# We need the REAL bridge name
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'br-to-parent', bridge])
# For the OVS version shipped with XS56FP1 we need to retrieve
# the ofport number for all interfaces
vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'list-ports', bridge])
vifs = vsctl_output.split('\n')
vif_ofports = []
for vif in vifs:
vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get',
'Interface', vif, 'ofport'])
if this_vif == vif:
this_vif_ofport = vif_ofport
vif_ofports.append(vif_ofport)
# So regardless of whether the VIF is brought online or offline we
# will always execute the same action
if command == 'offline':
clear_flows(bridge, this_vif_ofport, vif_ofports)
if command == 'online':
apply_flows(bridge, this_vif_ofport, vif_ofports)
if __name__ == "__main__":
if len(sys.argv) != 3:
print "usage: %s [online|offline] vif-domid-idx" % \
os.path.basename(sys.argv[0])
sys.exit(1)
else:
command, vif_raw = sys.argv[1:3]
main(command, vif_raw)

View File

@ -0,0 +1,79 @@
# A simple script for enabling and disabling per-vif rules for explicitly
# allowing broadcast/multicast traffic on the port where the VIF is attached
#
# Copyright (C) 2012 Citrix Systems
import os
import sys
import cloudstack_pluginlib as pluginlib
def clear_flows(bridge, vif_ofport):
# Remove flow entries originating from given ofport
pluginlib.del_flows(bridge, in_port=vif_ofport)
# Leverage out_port option for removing flows based on actions
pluginlib.del_flows(bridge, out_port=vif_ofport)
def apply_flows(bridge, vif_ofport):
action = "output:%s," % vif_ofport
# Ensure {b|m}casts sent from VIF ports are always allowed
pluginlib.add_flow(bridge, priority=1200,
in_port=vif_ofport,
dl_dst='ff:ff:ff:ff:ff:ff',
actions='NORMAL')
pluginlib.add_flow(bridge, priority=1200,
in_port=vif_ofport,
nw_dst='224.0.0.0/24',
actions='NORMAL')
# Ensure {b|m}casts are always propagated to VIF ports
pluginlib.add_flow(bridge, priority=1100,
dl_dst='ff:ff:ff:ff:ff:ff', actions=action)
pluginlib.add_flow(bridge, priority=1100,
nw_dst='224.0.0.0/24', actions=action)
def main(command, vif_raw):
if command not in ('online', 'offline'):
return
# TODO (very important)
# Quit immediately if networking is NOT being managed by the OVS tunnel manager
vif_name, dom_id, vif_index = vif_raw.split('-')
# validate vif and dom-id
vif = "%s%s.%s" % (vif_name, dom_id, vif_index)
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', vif])
# find xs network for this bridge, verify is used for ovs tunnel network
xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list",
"bridge=%s" % bridge, "--minimal"])
result = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=is-ovs-tun-network", "--minimal"])
if result != 'True':
return
vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge])
if vlan != '0':
# We need the REAL bridge name
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-parent', bridge])
vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface',
vif, 'ofport'])
if command == 'offline':
clear_flows(bridge, vif_ofport)
if command == 'online':
apply_flows(bridge, vif_ofport)
if __name__ == "__main__":
if len(sys.argv) != 3:
print "usage: %s [online|offline] vif-domid-idx" % \
os.path.basename(sys.argv[0])
sys.exit(1)
else:
command, vif_raw = sys.argv[1:3]
main(command, vif_raw)

View File

@ -0,0 +1,31 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs.dao;
import java.util.List;
import com.cloud.utils.db.GenericDao;
public interface OvsTunnelNetworkDao extends
GenericDao<OvsTunnelNetworkVO, Long> {
OvsTunnelNetworkVO getByFromToNetwork(long from, long to, long networkId);
void removeByFromNetwork(long from, long networkId);
void removeByFromToNetwork(long from, long to, long networkId);
List<OvsTunnelNetworkVO> listByToNetwork(long to, long networkId);
}

View File

@ -0,0 +1,91 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs.dao;
import java.util.List;
import javax.ejb.Local;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
@Local(value = { OvsTunnelNetworkDao.class })
public class OvsTunnelNetworkDaoImpl extends
GenericDaoBase<OvsTunnelNetworkVO, Long> implements OvsTunnelNetworkDao {
protected final SearchBuilder<OvsTunnelNetworkVO> fromToNetworkSearch;
protected final SearchBuilder<OvsTunnelNetworkVO> fromNetworkSearch;
protected final SearchBuilder<OvsTunnelNetworkVO> toNetworkSearch;
public OvsTunnelNetworkDaoImpl() {
fromToNetworkSearch = createSearchBuilder();
fromToNetworkSearch.and("from", fromToNetworkSearch.entity().getFrom(), Op.EQ);
fromToNetworkSearch.and("to", fromToNetworkSearch.entity().getTo(), Op.EQ);
fromToNetworkSearch.and("network_id", fromToNetworkSearch.entity().getNetworkId(), Op.EQ);
fromToNetworkSearch.done();
fromNetworkSearch = createSearchBuilder();
fromNetworkSearch.and("from", fromNetworkSearch.entity().getFrom(), Op.EQ);
fromNetworkSearch.and("network_id", fromNetworkSearch.entity().getNetworkId(), Op.EQ);
fromNetworkSearch.done();
toNetworkSearch = createSearchBuilder();
toNetworkSearch.and("to", toNetworkSearch.entity().getTo(), Op.EQ);
toNetworkSearch.and("network_id", toNetworkSearch.entity().getNetworkId(), Op.EQ);
toNetworkSearch.done();
}
@Override
public OvsTunnelNetworkVO getByFromToNetwork(long from, long to,
long networkId) {
SearchCriteria<OvsTunnelNetworkVO> sc = fromToNetworkSearch.create();
sc.setParameters("from", from);
sc.setParameters("to", to);
sc.setParameters("network_id", networkId);
return findOneBy(sc);
}
@Override
public void removeByFromNetwork(long from, long networkId) {
SearchCriteria<OvsTunnelNetworkVO> sc = fromNetworkSearch.create();
sc.setParameters("from", from);
sc.setParameters("network_id", networkId);
remove(sc);
}
@Override
public List<OvsTunnelNetworkVO> listByToNetwork(long to, long networkId) {
SearchCriteria<OvsTunnelNetworkVO> sc = toNetworkSearch.create();
sc.setParameters("to", to);
sc.setParameters("network_id", networkId);
return listBy(sc);
}
@Override
public void removeByFromToNetwork(long from, long to, long networkId) {
SearchCriteria<OvsTunnelNetworkVO> sc = fromToNetworkSearch.create();
sc.setParameters("from", from);
sc.setParameters("to", to);
sc.setParameters("network_id", networkId);
remove(sc);
}
}

View File

@ -0,0 +1,106 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.ovs.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name=("ovs_tunnel_network"))
public class OvsTunnelNetworkVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "from")
private long from;
@Column(name = "to")
private long to;
@Column(name = "key")
private int key;
@Column(name = "network_id")
private long networkId;
@Column(name = "port_name")
private String portName;
@Column(name = "state")
private String state;
public OvsTunnelNetworkVO() {
}
public OvsTunnelNetworkVO(long from, long to, int key, long networkId) {
this.from = from;
this.to = to;
this.key = key;
this.networkId = networkId;
this.portName = "[]";
this.state = "FAILED";
}
public void setKey(int key) {
this.key = key;
}
public long getFrom() {
return from;
}
public long getTo() {
return to;
}
public int getKey() {
return key;
}
public long getId() {
return id;
}
public long getNetworkId() {
return networkId;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public void setPortName(String name) {
this.portName = name;
}
public String getPortName() {
return portName;
}
}