OpenvSwitch.rb

Modified file /var/lib/one/remotes/vnm/ovswitch/OpenvSwitch.rb - Oriol Marti, 03/02/2013 10:39 PM

Download (4.9 KB)

 
1
# -------------------------------------------------------------------------- #
2
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)             #
3
#                                                                            #
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
5
# not use this file except in compliance with the License. You may obtain    #
6
# a copy of the License at                                                   #
7
#                                                                            #
8
# http://www.apache.org/licenses/LICENSE-2.0                                 #
9
#                                                                            #
10
# Unless required by applicable law or agreed to in writing, software        #
11
# distributed under the License is distributed on an "AS IS" BASIS,          #
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
13
# See the License for the specific language governing permissions and        #
14
# limitations under the License.                                             #
15
#--------------------------------------------------------------------------- #
16

    
17
require 'OpenNebulaNetwork'
18

    
19
class OpenvSwitchVLAN < OpenNebulaNetwork
20
    FIREWALL_PARAMS =  [:black_ports_tcp,
21
                        :black_ports_udp,
22
                        :icmp]
23

    
24
    XPATH_FILTER = "TEMPLATE/NIC"
25

    
26
    def initialize(vm, deploy_id = nil, hypervisor = nil)
27
        super(vm,XPATH_FILTER,deploy_id,hypervisor)
28
    end
29

    
30
    def activate
31
        process do |nic|
32
            @nic = nic
33

    
34
            # Apply VLAN
35
            tag_vlan if @nic[:vlan] == "YES"
36

    
37
            # Prevent Mac-spoofing
38
            mac_spoofing
39

    
40
            # Apply Firewall
41
            configure_fw if FIREWALL_PARAMS & @nic.keys != []
42
        end
43
        return 0
44
    end
45

    
46
    def deactivate
47
        process do |nic|
48
            @nic = nic
49

    
50
            # Remove flows
51
            del_flows
52
        end
53
    end
54

    
55
    def tag_vlan
56
        cmd =  "#{COMMANDS[:ovs_vsctl]} set Port #{@nic[:tap]} "
57
        cmd << "tag=#{vlan}"
58

    
59
        run cmd
60
    end
61

    
62
    def mac_spoofing
63
        add_flow("in_port=#{port},dl_src=#{@nic[:mac]}",:normal,40000)
64
        add_flow("in_port=#{port}",:drop,39000)
65
    end
66

    
67
    def configure_fw
68
        # TCP
69
        if range = @nic[:black_ports_tcp]
70
            if range? range
71
                range.split(",").each do |p|
72
                    if @nic[:vlan] == "YES"
73
                        add_flow("tcp,dl_dst=#{@nic[:mac]},tp_dst=#{p},dl_vlan=#{vlan}",:drop)
74
                    else
75
                        add_flow("tcp,dl_dst=#{@nic[:mac]},tp_dst=#{p}",:drop)
76
                    end
77
                end
78
            end
79
        end
80

    
81
        # UDP
82
        if range = @nic[:black_ports_udp]
83
            if range? range
84
                range.split(",").each do |p|
85
                    if @nic[:vlan] == "YES"
86
                        add_flow("udp,dl_dst=#{@nic[:mac]},tp_dst=#{p},dl_vlan=#{vlan}",:drop)
87
                    else
88
                        add_flow("udp,dl_dst=#{@nic[:mac]},tp_dst=#{p}",:drop)
89
                    end
90
                end
91
            end
92
        end
93

    
94
        # ICMP
95
        if @nic[:icmp]
96
            if %w(no drop).include? @nic[:icmp].downcase
97
                if @nic[:vlan] == "YES"
98
                    add_flow("icmp,dl_dst=#{@nic[:mac]},dl_vlan=#{vlan}",:drop)
99
                else
100
                    add_flow("icmp,dl_dst=#{@nic[:mac]}",:drop)
101
                end
102
            end
103
        end
104
    end
105

    
106
    def del_flows
107
        in_port = ""
108

    
109
        dump_flows = "#{COMMANDS[:ovs_ofctl]} dump-flows #{@nic[:bridge]}"
110
        `#{dump_flows}`.lines do |flow|
111
            next unless flow.match("#{@nic[:mac]}")
112
            flow = flow.split.select{|e| e.match(@nic[:mac])}.first
113
            if in_port.empty? and (m = flow.match(/in_port=(\d+)/))
114
                in_port = m[1]
115
            end
116
            del_flow flow
117
        end
118

    
119
        del_flow "in_port=#{in_port}" if !in_port.empty?
120
    end
121

    
122
    def add_flow(filter,action,priority=nil)
123
        priority = (priority.to_s.empty? ? "" : "priority=#{priority},")
124

    
125
        run "#{COMMANDS[:ovs_ofctl]} add-flow " <<
126
            "#{@nic[:bridge]} #{filter},#{priority}actions=#{action}"
127
    end
128

    
129
    def del_flow(filter)
130
        filter.gsub!(/priority=(\d+)/,"")
131
        run "#{COMMANDS[:ovs_ofctl]} del-flows " <<
132
            "#{@nic[:bridge]} #{filter}"
133
    end
134

    
135
    def run(cmd)
136
        OpenNebula.exec_and_log(cmd)
137
    end
138

    
139
    def port
140
        return @nic[:port] if @nic[:port]
141

    
142
        dump_ports = `#{COMMANDS[:ovs_ofctl]} \
143
                      dump-ports #{@nic[:bridge]} #{@nic[:tap]}`
144

    
145
        @nic[:port] = dump_ports.scan(/^\s*port\s*(\d+):/).flatten.first
146
    end
147

    
148
    def vlan
149
        if @nic[:vlan_id]
150
            return @nic[:vlan_id] 
151
        else
152
            return CONF[:start_vlan] + @nic[:network_id].to_i
153
        end
154
    end 
155

    
156
    def range?(range)
157
        !range.match(/^\d+(,\d+)*$/).nil?
158
    end
159
end