Fixup Augmentable and Identifiable methods changing
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronSecurityRuleListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netvirt.neutronvpn;
9
10 import com.google.common.collect.ImmutableBiMap;
11 import javax.annotation.PostConstruct;
12 import javax.inject.Inject;
13 import javax.inject.Singleton;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
17 import org.opendaylight.genius.mdsalutil.MDSALUtil;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.ActionsBuilder;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.MatchesBuilder;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6Builder;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionBase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolBase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmp;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmpV6;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 @Singleton
54 public class NeutronSecurityRuleListener
55         extends AsyncDataTreeChangeListenerBase<SecurityRule, NeutronSecurityRuleListener> {
56     private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleListener.class);
57     private static final ImmutableBiMap<Class<? extends DirectionBase>,
58         Class<?extends org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase>>
59         DIRECTION_MAP = ImmutableBiMap.of(
60             DirectionEgress.class, NeutronSecurityRuleConstants.DIRECTION_EGRESS,
61             DirectionIngress.class, NeutronSecurityRuleConstants.DIRECTION_INGRESS);
62     private static final ImmutableBiMap<Class<? extends ProtocolBase>, Short> PROTOCOL_MAP = ImmutableBiMap.of(
63             ProtocolIcmp.class, NeutronSecurityRuleConstants.PROTOCOL_ICMP,
64             ProtocolTcp.class, NeutronSecurityRuleConstants.PROTOCOL_TCP,
65             ProtocolUdp.class, NeutronSecurityRuleConstants.PROTOCOL_UDP,
66             ProtocolIcmpV6.class, NeutronSecurityRuleConstants.PROTOCOL_ICMPV6);
67
68     private final DataBroker dataBroker;
69
70     @Inject
71     public NeutronSecurityRuleListener(final DataBroker dataBroker) {
72         super(SecurityRule.class, NeutronSecurityRuleListener.class);
73         this.dataBroker = dataBroker;
74     }
75
76     @Override
77     @PostConstruct
78     public void init() {
79         LOG.info("{} init", getClass().getSimpleName());
80         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
81     }
82
83     @Override
84     protected InstanceIdentifier<SecurityRule> getWildCardPath() {
85         return InstanceIdentifier.create(Neutron.class).child(SecurityRules.class).child(SecurityRule.class);
86     }
87
88     @Override
89     // TODO Clean up the exception handling
90     @SuppressWarnings("checkstyle:IllegalCatch")
91     protected void add(InstanceIdentifier<SecurityRule> instanceIdentifier, SecurityRule securityRule) {
92         LOG.trace("added securityRule: {}", securityRule);
93         try {
94             Ace ace = toAceBuilder(securityRule).build();
95             InstanceIdentifier<Ace> identifier = getAceInstanceIdentifier(securityRule);
96             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, identifier, ace);
97         } catch (Exception ex) {
98             LOG.error("Exception occured while adding acl for security rule: {}. ", securityRule, ex);
99         }
100     }
101
102     private InstanceIdentifier<Ace> getAceInstanceIdentifier(SecurityRule securityRule) {
103         return InstanceIdentifier
104                 .builder(AccessLists.class)
105                 .child(Acl.class,
106                         new AclKey(securityRule.getSecurityGroupId().getValue(), NeutronSecurityRuleConstants.ACLTYPE))
107                 .child(AccessListEntries.class)
108                 .child(Ace.class,
109                         new AceKey(securityRule.getUuid().getValue()))
110                 .build();
111     }
112
113     private AceBuilder toAceBuilder(SecurityRule securityRule) {
114         AceIpBuilder aceIpBuilder = new AceIpBuilder();
115         SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
116         DestinationPortRangeBuilder destinationPortRangeBuilder = new DestinationPortRangeBuilder();
117         boolean isDirectionIngress = false;
118         if (securityRule.getDirection() != null) {
119             securityRuleAttrBuilder.setDirection(DIRECTION_MAP.get(securityRule.getDirection()));
120             isDirectionIngress = securityRule.getDirection().equals(DirectionIngress.class);
121         }
122         if (securityRule.getPortRangeMax() != null) {
123             destinationPortRangeBuilder.setUpperPort(new PortNumber(securityRule.getPortRangeMax()));
124
125         }
126         if (securityRule.getPortRangeMin() != null) {
127             destinationPortRangeBuilder.setLowerPort(new PortNumber(securityRule.getPortRangeMin()));
128             // set destination port range if lower port is specified as it is mandatory parameter in acl model
129             aceIpBuilder.setDestinationPortRange(destinationPortRangeBuilder.build());
130         }
131         aceIpBuilder = handleRemoteIpPrefix(securityRule, aceIpBuilder, isDirectionIngress);
132         if (securityRule.getRemoteGroupId() != null) {
133             securityRuleAttrBuilder.setRemoteGroupId(securityRule.getRemoteGroupId());
134         }
135         if (securityRule.getProtocol() != null) {
136             SecurityRuleAttributes.Protocol protocol = securityRule.getProtocol();
137             if (protocol.getUint8() != null) {
138                 // uint8
139                 aceIpBuilder.setProtocol(protocol.getUint8());
140             } else {
141                 // symbolic protocol name
142                 aceIpBuilder.setProtocol(PROTOCOL_MAP.get(protocol.getIdentityref()));
143             }
144         }
145
146         MatchesBuilder matchesBuilder = new MatchesBuilder();
147         matchesBuilder.setAceType(aceIpBuilder.build());
148         // set acl action as permit for the security rule
149         ActionsBuilder actionsBuilder = new ActionsBuilder();
150         actionsBuilder.setPacketHandling(new PermitBuilder().setPermit(true).build());
151
152         AceBuilder aceBuilder = new AceBuilder();
153         aceBuilder.withKey(new AceKey(securityRule.getUuid().getValue()));
154         aceBuilder.setRuleName(securityRule.getUuid().getValue());
155         aceBuilder.setMatches(matchesBuilder.build());
156         aceBuilder.setActions(actionsBuilder.build());
157         aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
158         return aceBuilder;
159     }
160
161     private AceIpBuilder handleEtherType(SecurityRule securityRule, AceIpBuilder aceIpBuilder) {
162         if (NeutronSecurityRuleConstants.ETHERTYPE_IPV4.equals(securityRule.getEthertype())) {
163             AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
164             aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(
165                 NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
166             aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(
167                 NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
168             aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
169         } else {
170             AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
171             aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
172                 NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
173             aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
174                 NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
175             aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
176
177         }
178         return aceIpBuilder;
179     }
180
181     private AceIpBuilder handleRemoteIpPrefix(SecurityRule securityRule, AceIpBuilder aceIpBuilder,
182                                               boolean isDirectionIngress) {
183         if (securityRule.getRemoteIpPrefix() != null) {
184             if (securityRule.getRemoteIpPrefix().getIpv4Prefix() != null) {
185                 AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
186                 if (isDirectionIngress) {
187                     aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(securityRule
188                         .getRemoteIpPrefix().getIpv4Prefix().getValue()));
189                 } else {
190                     aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(securityRule
191                         .getRemoteIpPrefix().getIpv4Prefix().getValue()));
192                 }
193                 aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
194             } else {
195                 AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
196                 if (isDirectionIngress) {
197                     aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
198                         securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
199                 } else {
200                     aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
201                         securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
202                 }
203                 aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
204             }
205         } else {
206             if (securityRule.getEthertype() != null) {
207                 handleEtherType(securityRule, aceIpBuilder);
208             }
209         }
210
211         return aceIpBuilder;
212     }
213
214     @Override
215     // TODO Clean up the exception handling
216     @SuppressWarnings("checkstyle:IllegalCatch")
217     protected void remove(InstanceIdentifier<SecurityRule> instanceIdentifier, SecurityRule securityRule) {
218         LOG.trace("removed securityRule: {}", securityRule);
219         try {
220             InstanceIdentifier<Ace> identifier = getAceInstanceIdentifier(securityRule);
221             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, identifier);
222         } catch (Exception ex) {
223             LOG.error("Exception occured while removing acl for security rule: {}. ", securityRule, ex);
224         }
225     }
226
227     @Override
228     protected void update(InstanceIdentifier<SecurityRule> instanceIdentifier,
229                           SecurityRule oldSecurityRule, SecurityRule updatedSecurityRule) {
230         // security rule updation is not supported from openstack, so no need to handle update.
231         LOG.trace("updates on security rules not supported.");
232     }
233
234     @Override
235     protected NeutronSecurityRuleListener getDataTreeChangeListener() {
236         return this;
237     }
238 }