mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Implement PVLAN on Xen
Start/stop vm/dhcp server are done. Not done with VM migration. A new command(PvlanSetupCommand) is sent for setting up PVLAN for vms. Currently it's focus on OVS implementation. Need to be more abstruct and add vSwitch part.
This commit is contained in:
parent
9c9e2ec9cc
commit
b64039bafd
130
api/src/com/cloud/agent/api/PvlanSetupCommand.java
Normal file
130
api/src/com/cloud/agent/api/PvlanSetupCommand.java
Normal file
@ -0,0 +1,130 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you 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.
|
||||
package com.cloud.agent.api;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
public class PvlanSetupCommand extends Command {
|
||||
public enum Type {
|
||||
DHCP,
|
||||
VM,
|
||||
VM_IN_DHCP_HOST
|
||||
}
|
||||
private String op;
|
||||
private String bridge;
|
||||
private String primary;
|
||||
private String isolated;
|
||||
private String vmMac;
|
||||
private String dhcpMac;
|
||||
private String dhcpIp;
|
||||
private boolean strict;
|
||||
private Type type;
|
||||
|
||||
protected PvlanSetupCommand() {}
|
||||
|
||||
protected PvlanSetupCommand(Type type, String op, String bridge, URI uri)
|
||||
{
|
||||
this.type = type;
|
||||
this.op = op;
|
||||
this.bridge = bridge;
|
||||
this.primary = NetUtils.getPrimaryPvlanFromUri(uri);
|
||||
this.isolated = NetUtils.getIsolatedPvlanFromUri(uri);
|
||||
this.strict = true;
|
||||
}
|
||||
|
||||
static public PvlanSetupCommand createDhcpSetup(String op, String bridge, URI uri, String dhcpMac, String dhcpIp)
|
||||
{
|
||||
PvlanSetupCommand cmd = new PvlanSetupCommand(Type.DHCP, op, bridge, uri);
|
||||
cmd.setDhcpMac(dhcpMac);
|
||||
cmd.setDhcpIp(dhcpIp);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static public PvlanSetupCommand createVmSetup(String op, String bridge, URI uri, String vmMac)
|
||||
{
|
||||
PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM, op, bridge, uri);
|
||||
cmd.setVmMac(vmMac);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static public PvlanSetupCommand createVmInDhcpHostSetup(String op, String bridge, URI uri, String dhcpMac, String vmMac)
|
||||
{
|
||||
PvlanSetupCommand cmd = new PvlanSetupCommand(Type.VM_IN_DHCP_HOST, op, bridge, uri);
|
||||
cmd.setDhcpMac(dhcpMac);
|
||||
cmd.setVmMac(vmMac);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
public String getBridge() {
|
||||
return bridge;
|
||||
}
|
||||
|
||||
public String getPrimary() {
|
||||
return primary;
|
||||
}
|
||||
|
||||
public String getIsolated() {
|
||||
return isolated;
|
||||
}
|
||||
|
||||
public String getVmMac() {
|
||||
return vmMac;
|
||||
}
|
||||
|
||||
protected void setVmMac(String vmMac) {
|
||||
this.vmMac = vmMac;
|
||||
}
|
||||
|
||||
public String getDhcpMac() {
|
||||
return dhcpMac;
|
||||
}
|
||||
|
||||
protected void setDhcpMac(String dhcpMac) {
|
||||
this.dhcpMac = dhcpMac;
|
||||
}
|
||||
|
||||
public String getDhcpIp() {
|
||||
return dhcpIp;
|
||||
}
|
||||
|
||||
protected void setDhcpIp(String dhcpIp) {
|
||||
this.dhcpIp = dhcpIp;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isStrict() {
|
||||
return strict;
|
||||
}
|
||||
|
||||
public void setStrict(boolean strict) {
|
||||
this.strict = strict;
|
||||
}
|
||||
}
|
||||
@ -604,6 +604,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
return execute((NetworkRulesVmSecondaryIpCommand)cmd);
|
||||
} else if (clazz == ScaleVmCommand.class) {
|
||||
return execute((ScaleVmCommand) cmd);
|
||||
} else if (clazz == PvlanSetupCommand.class) {
|
||||
return execute((PvlanSetupCommand) cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
@ -1054,7 +1056,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
vifr = vif.getRecord(conn);
|
||||
s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId());
|
||||
}
|
||||
|
||||
|
||||
return vif;
|
||||
}
|
||||
|
||||
@ -1465,6 +1467,48 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Answer execute(PvlanSetupCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
|
||||
String primaryPvlan = cmd.getPrimary();
|
||||
String isolatedPvlan = cmd.getIsolated();
|
||||
String op = cmd.getOp();
|
||||
String bridge = cmd.getBridge();
|
||||
String result = null;
|
||||
String dhcpMac = cmd.getDhcpMac();
|
||||
String dhcpIp = cmd.getDhcpIp();
|
||||
String vmMac = cmd.getVmMac();
|
||||
if (cmd.getType() == PvlanSetupCommand.Type.DHCP) {
|
||||
result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-dhcp", "op", op, "bridge", bridge,
|
||||
"primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "dhcp-ip", dhcpIp, "dhcp-mac", dhcpMac);
|
||||
if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
|
||||
s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac);
|
||||
return new Answer(cmd, false, result);
|
||||
} else {
|
||||
s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac);
|
||||
}
|
||||
} else if (cmd.getType() == PvlanSetupCommand.Type.VM) {
|
||||
result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm-alone", "op", op, "bridge", bridge,
|
||||
"primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "vm-mac", vmMac);
|
||||
if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
|
||||
s_logger.warn("Failed to program pvlan for vm with mac " + vmMac);
|
||||
return new Answer(cmd, false, result);
|
||||
} else {
|
||||
s_logger.info("Programmed pvlan for vm with mac " + vmMac);
|
||||
}
|
||||
} else if (cmd.getType() == PvlanSetupCommand.Type.VM_IN_DHCP_HOST) {
|
||||
result = callHostPlugin(conn, "ovs-pvlan", "setup-pvlan-vm-dhcp", "op", op, "bridge", bridge,
|
||||
"primary-pvlan", primaryPvlan, "isolated-pvlan", isolatedPvlan, "vm-mac", vmMac, "dhcp-mac", dhcpMac);
|
||||
if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) {
|
||||
s_logger.warn("Failed to program pvlan for vm in dhcp host with mac " + vmMac);
|
||||
return new Answer(cmd, false, result);
|
||||
} else {
|
||||
s_logger.info("Programmed pvlan for vm in dhcp host with mac " + vmMac);
|
||||
}
|
||||
}
|
||||
return new Answer(cmd, true, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartAnswer execute(StartCommand cmd) {
|
||||
|
||||
168
scripts/vm/hypervisor/xenserver/ovs-pvlan
Executable file
168
scripts/vm/hypervisor/xenserver/ovs-pvlan
Executable file
@ -0,0 +1,168 @@
|
||||
#!/usr/bin/python
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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 cloudstack_pluginlib as lib
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
import XenAPIPlugin
|
||||
|
||||
sys.path.append("/opt/xensource/sm/")
|
||||
import util
|
||||
|
||||
from time import localtime as _localtime, asctime as _asctime
|
||||
|
||||
xePath = "/opt/xensource/bin/xe"
|
||||
lib.setup_logging("/var/log/ovs-pvlan.log")
|
||||
dhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-dhcp-host.sh"
|
||||
vmAloneSetupPath = "/opt/xensource/bin/ovs-pvlan-vm.sh"
|
||||
vmDhcpSetupPath = "/opt/xensource/bin/ovs-pvlan-vm-in-dhcp-host.sh"
|
||||
pvlanCleanupPath = "/opt/xensource/bin/ovs-pvlan-cleanup.sh"
|
||||
|
||||
def echo(fn):
|
||||
def wrapped(*v, **k):
|
||||
name = fn.__name__
|
||||
util.SMlog("#### VMOPS enter %s ####" % name)
|
||||
res = fn(*v, **k)
|
||||
util.SMlog("#### VMOPS exit %s ####" % name)
|
||||
return res
|
||||
return wrapped
|
||||
|
||||
|
||||
@echo
|
||||
def setup_pvlan_dhcp(session, args):
|
||||
op = args.pop("op")
|
||||
bridge = args.pop("bridge")
|
||||
primary = args.pop("primary-pvlan")
|
||||
isolated = args.pop("isolated-pvlan")
|
||||
dhcp_ip = args.pop("dhcp-ip");
|
||||
dhcp_mac = args.pop("dhcp-mac");
|
||||
|
||||
res = lib.check_switch()
|
||||
if res != "SUCCESS":
|
||||
return "FAILURE:%s" % res
|
||||
|
||||
if op == "add":
|
||||
logging.debug("About to setup dhcp vm on the switch:%s" % bridge)
|
||||
res = lib.do_cmd([dhcpSetupPath, "-A", "-b", bridge, "-p", primary,
|
||||
"-i", isolated, "-d", dhcp_ip, "-m", dhcp_mac])
|
||||
if res:
|
||||
result = "FAILURE:%s" % res
|
||||
return result;
|
||||
logging.debug("Setup dhcp vm on switch program done")
|
||||
elif op == "delete":
|
||||
logging.debug("About to remove dhcp the switch:%s" % bridge)
|
||||
res = lib.do_cmd([dhcpSetupPath, "-D", "-b", bridge, "-p", primary,
|
||||
"-i", isolated, "-d", dhcp_ip, "-m", dhcp_mac])
|
||||
if res:
|
||||
result = "FAILURE:%s" % res
|
||||
return result;
|
||||
logging.debug("Remove DHCP on switch program done")
|
||||
|
||||
result = "true"
|
||||
logging.debug("Setup_pvlan_dhcp completed with result:%s" % result)
|
||||
return result
|
||||
|
||||
@echo
|
||||
def setup_pvlan_vm_alone(session, args):
|
||||
op = args.pop("op")
|
||||
bridge = args.pop("bridge")
|
||||
isolated = args.pop("isolated-pvlan")
|
||||
vm_mac = args.pop("vm-mac")
|
||||
trunk_port = 1
|
||||
|
||||
res = lib.check_switch()
|
||||
if res != "SUCCESS":
|
||||
return "FAILURE:%s" % res
|
||||
|
||||
if op == "add":
|
||||
logging.debug("About to setup vm alone on the switch:%s" % bridge)
|
||||
res = lib.do_cmd([vmAloneSetupPath, "-A", "-b", bridge, "-i", isolated, "-v", vm_mac])
|
||||
if res:
|
||||
result = "FAILURE:%s" % res
|
||||
return result;
|
||||
logging.debug("Setup vm alone on switch program done")
|
||||
elif op == "delete":
|
||||
logging.debug("About to remove vm alone on the switch:%s" % bridge)
|
||||
res = lib.do_cmd([vmAloneSetupPath, "-D", "-b", bridge, "-i", isolated, "-v", vm_mac])
|
||||
if res:
|
||||
result = "FAILURE:%s" % res
|
||||
return result;
|
||||
logging.debug("Remove vm alone on switch program done")
|
||||
|
||||
result = "true"
|
||||
logging.debug("Setup_pvlan_vm_alone completed with result:%s" % result)
|
||||
return result
|
||||
|
||||
@echo
|
||||
def setup_pvlan_vm_dhcp(session, args):
|
||||
op = args.pop("op")
|
||||
bridge = args.pop("bridge")
|
||||
isolated = args.pop("isolated-pvlan")
|
||||
vm_mac = args.pop("vm-mac")
|
||||
dhcp_mac = args.pop("dhcp-mac");
|
||||
trunk_port = 1
|
||||
|
||||
res = lib.check_switch()
|
||||
if res != "SUCCESS":
|
||||
return "FAILURE:%s" % res
|
||||
|
||||
if op == "add":
|
||||
logging.debug("About to setup vm dhcp on the switch:%s" % bridge)
|
||||
res = lib.do_cmd([vmDhcpSetupPath, "-A", "-b", bridge, "-i", isolated,
|
||||
"-v", vm_mac, "-m", dhcp_mac])
|
||||
if res:
|
||||
result = "FAILURE:%s" % res
|
||||
return result;
|
||||
logging.debug("Setup vm dhcp on switch program done")
|
||||
elif op == "delete":
|
||||
logging.debug("About to remove vm dhcp on the switch:%s" % bridge)
|
||||
res = lib.do_cmd([vmDhcpSetupPath, "-D", "-b", bridge, "-i", isolated,
|
||||
"-v", vm_mac, "-m", dhcp_mac])
|
||||
if res:
|
||||
result = "FAILURE:%s" % res
|
||||
return result;
|
||||
logging.debug("Remove vm dhcp on switch program done")
|
||||
|
||||
result = "true"
|
||||
logging.debug("Setup_pvlan_vm_dhcp completed with result:%s" % result)
|
||||
return result
|
||||
|
||||
@echo
|
||||
def cleanup(session, args):
|
||||
res = lib.check_switch()
|
||||
if res != "SUCCESS":
|
||||
return "FAILURE:%s" % res
|
||||
|
||||
res = lib.do_cmd([pvlanCleanUpPath])
|
||||
if res:
|
||||
result = "FAILURE:%s" % res
|
||||
return result;
|
||||
|
||||
result = "true"
|
||||
logging.debug("Setup_pvlan_vm_dhcp completed with result:%s" % result)
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
XenAPIPlugin.dispatch({"setup-pvlan-dhcp": setup_pvlan_dhcp,
|
||||
"setup-pvlan-vm-alone": setup_pvlan_vm_alone,
|
||||
"setup-pvlan-vm-dhcp": setup_pvlan_vm_dhcp,
|
||||
"cleanup":cleanup})
|
||||
@ -67,4 +67,8 @@ bumpUpPriority.sh=../../../../network/domr/,0755,/opt/xensource/bin
|
||||
swift=..,0755,/opt/xensource/bin
|
||||
swiftxen=..,0755,/etc/xapi.d/plugins
|
||||
s3xen=..,0755,/etc/xapi.d/plugins
|
||||
|
||||
ovs-pvlan=..,0755,/etc/xapi.d/plugins
|
||||
ovs-pvlan-dhcp-host.sh=../../../network,0755,/opt/xensource/bin
|
||||
ovs-pvlan-vm-in-dhcp-host.sh=../../../network,0755,/opt/xensource/bin
|
||||
ovs-pvlan-vm.sh=../../../network,0755,/opt/xensource/bin
|
||||
ovs-pvlan-cleanup.sh=../../../network,0755,/opt/xensource/bin
|
||||
|
||||
23
scripts/vm/network/ovs-pvlan-cleanup.sh
Executable file
23
scripts/vm/network/ovs-pvlan-cleanup.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
ovs-ofctl del-flows xenbr0
|
||||
ovs-ofctl add-flow xenbr0 priority=0,actions=NORMAL
|
||||
|
||||
104
scripts/vm/network/ovs-pvlan-dhcp-host.sh
Executable file
104
scripts/vm/network/ovs-pvlan-dhcp-host.sh
Executable file
@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
usage() {
|
||||
printf "Usage: %s: (-A|-D) -b <bridge/switch> -p <primary vlan> -i <secondary isolated vlan> -d <DHCP server IP> -m <DHCP server MAC> -v <VM MAC> -h \n" $(basename $0) >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
br=
|
||||
pri_vlan=
|
||||
sec_iso_vlan=
|
||||
dhcp_ip=
|
||||
dhcp_mac=
|
||||
vm_mac=
|
||||
op=
|
||||
|
||||
while getopts 'ADb:p:i:d:m:v:h' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
A) op="add"
|
||||
;;
|
||||
D) op="del"
|
||||
;;
|
||||
b) br="$OPTARG"
|
||||
;;
|
||||
p) pri_vlan="$OPTARG"
|
||||
;;
|
||||
i) sec_iso_vlan="$OPTARG"
|
||||
;;
|
||||
d) dhcp_ip="$OPTARG"
|
||||
;;
|
||||
m) dhcp_mac="$OPTARG"
|
||||
;;
|
||||
v) vm_mac="$OPTARG"
|
||||
;;
|
||||
h) usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$op" ]
|
||||
then
|
||||
echo Missing operation pararmeter!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$br" ]
|
||||
then
|
||||
echo Missing parameter bridge!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$pri_vlan" ]
|
||||
then
|
||||
echo Missing parameter primary vlan!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$sec_iso_vlan" ]
|
||||
then
|
||||
echo Missing parameter secondary isolate vlan!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$dhcp_ip" ]
|
||||
then
|
||||
echo Missing parameter DHCP IP!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$dhcp_mac" ]
|
||||
then
|
||||
echo Missing parameter DHCP MAC!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$op" == "add" ]
|
||||
then
|
||||
ovs-ofctl add-flow $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip,actions=mod_vlan_vid:$pri_vlan,NORMAL
|
||||
ovs-ofctl add-flow $br priority=180,arp,nw_dst=$dhcp_ip,actions=NORMAL
|
||||
ovs-ofctl add-flow $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac,actions=mod_vlan_vid:$pri_vlan,NORMAL
|
||||
ovs-ofctl add-flow $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67,actions=mod_vlan_vid:$pri_vlan,NORMAL
|
||||
else
|
||||
ovs-ofctl del-flows --strict $br priority=200,arp,dl_vlan=$sec_iso_vlan,nw_dst=$dhcp_ip
|
||||
ovs-ofctl del-flows --strict $br priority=180,arp,nw_dst=$dhcp_ip
|
||||
ovs-ofctl del-flows --strict $br priority=150,dl_vlan=$sec_iso_vlan,dl_dst=$dhcp_mac
|
||||
ovs-ofctl del-flows --strict $br priority=100,udp,dl_vlan=$sec_iso_vlan,nw_dst=255.255.255.255,tp_dst=67
|
||||
fi
|
||||
88
scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh
Executable file
88
scripts/vm/network/ovs-pvlan-vm-in-dhcp-host.sh
Executable file
@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
usage() {
|
||||
printf "Usage: %s: (-A|-D) -b <bridge/switch> -p <primary vlan> -i <secondary isolated vlan> -d <DHCP server IP> -m <DHCP server MAC> -v <VM MAC> -h \n" $(basename $0) >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
br=
|
||||
pri_vlan=
|
||||
sec_iso_vlan=
|
||||
dhcp_ip=
|
||||
dhcp_mac=
|
||||
vm_mac=
|
||||
op=
|
||||
|
||||
while getopts 'ADb:p:i:d:m:v:h' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
A) op="add"
|
||||
;;
|
||||
D) op="del"
|
||||
;;
|
||||
b) br="$OPTARG"
|
||||
;;
|
||||
p) pri_vlan="$OPTARG"
|
||||
;;
|
||||
i) sec_iso_vlan="$OPTARG"
|
||||
;;
|
||||
d) dhcp_ip="$OPTARG"
|
||||
;;
|
||||
m) dhcp_mac="$OPTARG"
|
||||
;;
|
||||
v) vm_mac="$OPTARG"
|
||||
;;
|
||||
h) usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$op" ]
|
||||
then
|
||||
echo Missing operation pararmeter!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$br" ]
|
||||
then
|
||||
echo Missing parameter bridge!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$vm_mac" ]
|
||||
then
|
||||
echo Missing parameter VM MAC!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$dhcp_mac" ]
|
||||
then
|
||||
echo Missing parameter DHCP MAC!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$op" == "add" ]
|
||||
then
|
||||
ovs-ofctl add-flow $br priority=120,dl_src=$vm_mac,dl_dst=$dhcp_mac,actions=NORMAL
|
||||
ovs-ofctl add-flow $br priority=80,udp,dl_src=$vm_mac,nw_dst=255.255.255.255,tp_dst=67,actions=NORMAL
|
||||
else
|
||||
ovs-ofctl del-flows --strict $br priority=120,dl_src=$vm_mac,dl_dst=$dhcp_mac
|
||||
ovs-ofctl del-flows --strict $br priority=80,udp,dl_src=$vm_mac,nw_dst=255.255.255.255,tp_dst=67
|
||||
fi
|
||||
90
scripts/vm/network/ovs-pvlan-vm.sh
Executable file
90
scripts/vm/network/ovs-pvlan-vm.sh
Executable file
@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
usage() {
|
||||
printf "Usage: %s: (-A|-D) -b <bridge/switch> -p <primary vlan> -i <secondary isolated vlan> -d <DHCP server IP> -m <DHCP server MAC> -v <VM MAC> -h \n" $(basename $0) >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
br=
|
||||
pri_vlan=
|
||||
sec_iso_vlan=
|
||||
dhcp_ip=
|
||||
dhcp_mac=
|
||||
vm_mac=
|
||||
op=
|
||||
|
||||
while getopts 'ADb:p:i:d:m:v:h' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
A) op="add"
|
||||
;;
|
||||
D) op="del"
|
||||
;;
|
||||
b) br="$OPTARG"
|
||||
;;
|
||||
p) pri_vlan="$OPTARG"
|
||||
;;
|
||||
i) sec_iso_vlan="$OPTARG"
|
||||
;;
|
||||
d) dhcp_ip="$OPTARG"
|
||||
;;
|
||||
m) dhcp_mac="$OPTARG"
|
||||
;;
|
||||
v) vm_mac="$OPTARG"
|
||||
;;
|
||||
h) usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$op" ]
|
||||
then
|
||||
echo Missing operation pararmeter!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$br" ]
|
||||
then
|
||||
echo Missing parameter bridge!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$vm_mac" ]
|
||||
then
|
||||
echo Missing parameter VM MAC!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$sec_iso_vlan" ]
|
||||
then
|
||||
echo Missing parameter secondary isolate vlan!
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trunk_port=1
|
||||
|
||||
if [ "$op" == "add" ]
|
||||
then
|
||||
ovs-ofctl add-flow $br priority=50,dl_src=$vm_mac,actions=mod_vlan_vid:$sec_iso_vlan,output:$trunk_port
|
||||
else
|
||||
# it would delete any rule related to this vm, not only the rule added above
|
||||
ovs-ofctl del-flows $br dl_src=$vm_mac
|
||||
fi
|
||||
|
||||
@ -31,6 +31,7 @@ import org.apache.cloudstack.api.command.admin.router.CreateVirtualRouterElement
|
||||
import org.apache.cloudstack.api.command.admin.router.ListVirtualRouterElementsCmd;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.PvlanSetupCommand;
|
||||
import com.cloud.agent.api.to.LoadBalancerTO;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
@ -48,6 +49,7 @@ import com.cloud.network.Network.Capability;
|
||||
import com.cloud.network.Network.Provider;
|
||||
import com.cloud.network.Network.Service;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||
import com.cloud.network.PublicIpAddress;
|
||||
@ -214,6 +216,15 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
|
||||
DataCenter.class, network.getDataCenterId());
|
||||
}
|
||||
|
||||
// Setup PVlan for vm if necessary
|
||||
if (network.getTrafficType() == TrafficType.Guest && network.getBroadcastDomainType() == BroadcastDomainType.Pvlan) {
|
||||
assert routers.size() == 1;
|
||||
DomainRouterVO router = routers.get(0);
|
||||
if (router.getHostId() == dest.getHost().getId()) {
|
||||
_routerMgr.setupVmWithDhcpHostForPvlan(true, router, nic);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ package com.cloud.network.router;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.agent.api.PvlanSetupCommand;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
@ -35,6 +36,7 @@ import com.cloud.user.User;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import com.cloud.vm.Nic;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@ -103,4 +105,6 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
|
||||
|
||||
boolean applyUserData(Network config, NicProfile nic, VirtualMachineProfile<UserVm> vm, DeployDestination dest,
|
||||
List<DomainRouterVO> routers) throws ResourceUnavailableException;
|
||||
|
||||
void setupVmWithDhcpHostForPvlan(boolean add, DomainRouterVO router, NicProfile profile) throws ResourceUnavailableException;
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ import com.cloud.agent.api.GetDomRVersionCmd;
|
||||
import com.cloud.agent.api.ModifySshKeysCommand;
|
||||
import com.cloud.agent.api.NetworkUsageAnswer;
|
||||
import com.cloud.agent.api.NetworkUsageCommand;
|
||||
import com.cloud.agent.api.PvlanSetupCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||
@ -2210,6 +2211,72 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
|
||||
return dhcpRange;
|
||||
}
|
||||
|
||||
private boolean setupDhcpForPvlanOnHost(boolean add, DomainRouterVO router, Nic routerNic) {
|
||||
if (!routerNic.getBroadcastUri().getScheme().equals("pvlan")) {
|
||||
return false;
|
||||
}
|
||||
setupDhcpForPvlan(add, router, routerNic);
|
||||
Long hostId = router.getHostId();
|
||||
List<UserVmVO> vms = _userVmDao.listByHostId(hostId);
|
||||
for (UserVmVO vm : vms) {
|
||||
if (vm.getState() != State.Running) {
|
||||
continue;
|
||||
}
|
||||
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
||||
for (NicVO nic : nics) {
|
||||
if (nic.getNetworkId() == routerNic.getNetworkId()) {
|
||||
try {
|
||||
Network network = _networkDao.findById(routerNic.getNetworkId());
|
||||
NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(),
|
||||
null, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network));
|
||||
setupVmWithDhcpHostForPvlan(add, router, profile);
|
||||
} catch (ResourceUnavailableException e) {
|
||||
s_logger.warn("Fail to program pvlan on nic " + nic.getMacAddress(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Nic nic) {
|
||||
if (!nic.getBroadcastUri().getScheme().equals("pvlan")) {
|
||||
return false;
|
||||
}
|
||||
String op = "add";
|
||||
if (!add) {
|
||||
op = "delete";
|
||||
}
|
||||
PvlanSetupCommand cmd = PvlanSetupCommand.createDhcpSetup(op, "xenbr0", nic.getBroadcastUri(), nic.getMacAddress(), nic.getIp4Address());
|
||||
Commands cmds = new Commands(cmd);
|
||||
// In fact we send command to the host of router, we're not programming router but the host
|
||||
try {
|
||||
sendCommandsToRouter(router, cmds);
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Agent Unavailable ", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVmWithDhcpHostForPvlan(boolean add, DomainRouterVO router, NicProfile profile) throws ResourceUnavailableException
|
||||
{
|
||||
if (!profile.getBroadCastUri().getScheme().equals("pvlan")) {
|
||||
return;
|
||||
}
|
||||
String op = "add";
|
||||
if (!add) {
|
||||
op = "delete";
|
||||
}
|
||||
NicVO routerNic = _nicDao.findByInstanceIdAndNetworkId(profile.getNetworkId(), router.getId());
|
||||
PvlanSetupCommand cmd = PvlanSetupCommand.createVmInDhcpHostSetup(op, "xenbr0", profile.getBroadCastUri(), routerNic.getMacAddress(), profile.getMacAddress());
|
||||
Commands cmds = new Commands(cmd);
|
||||
// In fact we send command to the host of router, we're not programming router but the host
|
||||
sendCommandsToRouter(router, cmds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<DomainRouterVO> profile,
|
||||
DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
|
||||
@ -2505,11 +2572,18 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
|
||||
List<Network> guestNetworks = new ArrayList<Network>();
|
||||
|
||||
List<? extends Nic> routerNics = _nicDao.listByVmId(profile.getId());
|
||||
for (Nic routerNic : routerNics) {
|
||||
Network network = _networkModel.getNetwork(routerNic.getNetworkId());
|
||||
for (Nic nic : routerNics) {
|
||||
Network network = _networkModel.getNetwork(nic.getNetworkId());
|
||||
if (network.getTrafficType() == TrafficType.Guest) {
|
||||
guestNetworks.add(network);
|
||||
}
|
||||
if (nic.getBroadcastUri().getScheme().equals("pvlan")) {
|
||||
result = setupDhcpForPvlanOnHost(true, router, nic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
answer = cmds.getAnswer("getDomRVersion");
|
||||
@ -2537,6 +2611,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
|
||||
VMInstanceVO vm = profile.getVirtualMachine();
|
||||
DomainRouterVO domR = _routerDao.findById(vm.getId());
|
||||
processStopOrRebootAnswer(domR, answer);
|
||||
List<? extends Nic> routerNics = _nicDao.listByVmId(profile.getId());
|
||||
for (Nic nic : routerNics) {
|
||||
Network network = _networkModel.getNetwork(nic.getNetworkId());
|
||||
if (network.getTrafficType() == TrafficType.Guest && nic.getBroadcastUri().getScheme().equals("pvlan")) {
|
||||
setupDhcpForPvlanOnHost(false, domR, nic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -69,6 +69,7 @@ import com.cloud.agent.api.GetVmStatsAnswer;
|
||||
import com.cloud.agent.api.GetVmStatsCommand;
|
||||
import com.cloud.agent.api.PlugNicAnswer;
|
||||
import com.cloud.agent.api.PlugNicCommand;
|
||||
import com.cloud.agent.api.PvlanSetupCommand;
|
||||
import com.cloud.agent.api.StartAnswer;
|
||||
import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.UnPlugNicAnswer;
|
||||
@ -2751,6 +2752,34 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setupVmForPvlan(boolean add, Long hostId, NicVO nic) {
|
||||
if (!nic.getBroadcastUri().getScheme().equals("pvlan")) {
|
||||
return false;
|
||||
}
|
||||
String op = "add";
|
||||
if (!add) {
|
||||
// "delete" would remove all the rules(if using ovs) related to this vm
|
||||
op = "delete";
|
||||
}
|
||||
PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, "xenbr0", nic.getBroadcastUri(), nic.getMacAddress());
|
||||
Answer answer = null;
|
||||
try {
|
||||
answer = _agentMgr.send(hostId, cmd);
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Timed Out", e);
|
||||
return false;
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Agent Unavailable ", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
if (answer == null || !answer.getResult()) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finalizeDeployment(Commands cmds,
|
||||
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest,
|
||||
@ -2812,6 +2841,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
originalIp = nic.getIp4Address();
|
||||
guestNic = nic;
|
||||
guestNetwork = network;
|
||||
if (nic.getBroadcastUri().getScheme().equals("pvlan")) {
|
||||
if (!setupVmForPvlan(true, hostId, nic)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean ipChanged = false;
|
||||
@ -2942,6 +2976,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
+ " stop due to exception ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
VMInstanceVO vm = profile.getVirtualMachine();
|
||||
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
||||
for (NicVO nic : nics) {
|
||||
NetworkVO network = _networkDao.findById(nic.getNetworkId());
|
||||
if (network.getTrafficType() == TrafficType.Guest) {
|
||||
if (nic.getBroadcastUri().getScheme().equals("pvlan")) {
|
||||
setupVmForPvlan(false, vm.getHostId(), nic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String generateRandomPassword() {
|
||||
|
||||
@ -402,4 +402,11 @@ VpcVirtualNetworkApplianceService {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVmWithDhcpHostForPvlan(boolean add,
|
||||
DomainRouterVO router, NicProfile nic) throws ResourceUnavailableException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user