/* * Copyright (c) 2015 Inocybe inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.ovsdb.southbound.transactions.md; import static org.opendaylight.ovsdb.southbound.SouthboundUtil.schemaMismatchLog; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException; import org.opendaylight.ovsdb.lib.message.TableUpdates; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.schema.DatabaseSchema; import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch; import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.ovsdb.southbound.SouthboundMapper; import org.opendaylight.ovsdb.southbound.SouthboundUtil; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIdsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchExternalIdsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OpenVSwitchUpdateCommand extends AbstractTransactionCommand { private static final Logger LOG = LoggerFactory.getLogger(OpenVSwitchUpdateCommand.class); public OpenVSwitchUpdateCommand(OvsdbConnectionInstance key, TableUpdates updates, DatabaseSchema dbSchema) { super(key, updates, dbSchema); } @Override public void execute(ReadWriteTransaction transaction) { Map updatedOpenVSwitchRows = TyperUtils .extractRowsUpdated(OpenVSwitch.class, getUpdates(), getDbSchema()); Map deletedOpenVSwitchRows = TyperUtils .extractRowsOld(OpenVSwitch.class, getUpdates(), getDbSchema()); for (Entry entry : updatedOpenVSwitchRows.entrySet()) { OpenVSwitch openVSwitch = entry.getValue(); final InstanceIdentifier nodePath = getInstanceIdentifier(openVSwitch); OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder(); setVersion(ovsdbNodeBuilder, openVSwitch); setDataPathTypes(ovsdbNodeBuilder, openVSwitch); setInterfaceTypes(ovsdbNodeBuilder, openVSwitch); OpenVSwitch oldEntry = deletedOpenVSwitchRows.get(entry.getKey()); setExternalIds(transaction, ovsdbNodeBuilder, oldEntry, openVSwitch); setOtherConfig(transaction, ovsdbNodeBuilder, oldEntry, openVSwitch); ovsdbNodeBuilder.setConnectionInfo(getConnectionInfo()); NodeBuilder nodeBuilder = new NodeBuilder(); nodeBuilder.setNodeId(getNodeId(openVSwitch)); nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, ovsdbNodeBuilder.build()); transaction.merge(LogicalDatastoreType.OPERATIONAL, nodePath, nodeBuilder.build()); } } private void setOtherConfig(ReadWriteTransaction transaction, OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, OpenVSwitch oldEntry, OpenVSwitch openVSwitch) { Map oldOtherConfigs = null; Map otherConfigs = null; if (openVSwitch.getOtherConfigColumn() != null) { otherConfigs = openVSwitch.getOtherConfigColumn().getData(); } if (oldEntry != null && oldEntry.getOtherConfigColumn() != null) { oldOtherConfigs = oldEntry.getOtherConfigColumn().getData(); } if ((oldOtherConfigs == null) || oldOtherConfigs.isEmpty()) { setNewOtherConfigs(ovsdbNodeBuilder, otherConfigs); } else if (otherConfigs != null && !otherConfigs.isEmpty()) { removeOldConfigs(transaction, oldOtherConfigs, openVSwitch); setNewOtherConfigs(ovsdbNodeBuilder, otherConfigs); } } private void removeOldConfigs(ReadWriteTransaction transaction, Map oldOtherConfigs, OpenVSwitch ovs) { InstanceIdentifier nodeAugmentataionIid = InstanceIdentifier .create(NetworkTopology.class) .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) .child(Node.class, new NodeKey(getNodeId(ovs))).augmentation(OvsdbNodeAugmentation.class); Set otherConfigKeys = oldOtherConfigs.keySet(); for (String otherConfigKey : otherConfigKeys) { KeyedInstanceIdentifier externalIid = nodeAugmentataionIid .child(OpenvswitchOtherConfigs.class, new OpenvswitchOtherConfigsKey(otherConfigKey)); transaction.delete(LogicalDatastoreType.OPERATIONAL, externalIid); } } private void setNewOtherConfigs(OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, Map otherConfigs) { Set otherConfigKeys = otherConfigs.keySet(); List otherConfigsList = new ArrayList<>(); String otherConfigValue; for (String otherConfigKey : otherConfigKeys) { otherConfigValue = otherConfigs.get(otherConfigKey); if (otherConfigKey != null && otherConfigValue != null) { otherConfigsList.add(new OpenvswitchOtherConfigsBuilder().setOtherConfigKey(otherConfigKey) .setOtherConfigValue(otherConfigValue).build()); } } ovsdbNodeBuilder.setOpenvswitchOtherConfigs(otherConfigsList); } private void setExternalIds(ReadWriteTransaction transaction, OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, OpenVSwitch oldEntry, OpenVSwitch openVSwitch) { Map oldExternalIds = null; Map externalIds = null; if (openVSwitch.getExternalIdsColumn() != null) { externalIds = openVSwitch.getExternalIdsColumn().getData(); } if (oldEntry != null && oldEntry.getExternalIdsColumn() != null) { oldExternalIds = oldEntry.getExternalIdsColumn().getData(); } if ((oldExternalIds == null) || oldExternalIds.isEmpty()) { setNewExternalIds(ovsdbNodeBuilder, externalIds); } else if (externalIds != null && !externalIds.isEmpty()) { removeExternalIds(transaction, oldExternalIds, openVSwitch); setNewExternalIds(ovsdbNodeBuilder, externalIds); } } private void removeExternalIds(ReadWriteTransaction transaction, Map oldExternalIds, OpenVSwitch ovs) { InstanceIdentifier nodeAugmentataionIid = InstanceIdentifier .create(NetworkTopology.class) .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) .child(Node.class, new NodeKey(getNodeId(ovs))).augmentation(OvsdbNodeAugmentation.class); Set externalIdKeys = oldExternalIds.keySet(); for (String externalIdKey : externalIdKeys) { KeyedInstanceIdentifier externalIid = nodeAugmentataionIid .child(OpenvswitchExternalIds.class, new OpenvswitchExternalIdsKey(externalIdKey)); transaction.delete(LogicalDatastoreType.OPERATIONAL, externalIid); } } private void setNewExternalIds(OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, Map externalIds) { Set externalIdKeys = externalIds.keySet(); List externalIdsList = new ArrayList<>(); String externalIdValue; for (String externalIdKey : externalIdKeys) { externalIdValue = externalIds.get(externalIdKey); if (externalIdKey != null && externalIdValue != null) { externalIdsList.add(new OpenvswitchExternalIdsBuilder().setExternalIdKey(externalIdKey) .setExternalIdValue(externalIdValue).build()); } } ovsdbNodeBuilder.setOpenvswitchExternalIds(externalIdsList); } private void setInterfaceTypes( OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, OpenVSwitch openVSwitch) { try { Set iftypes = openVSwitch.getIfaceTypesColumn().getData(); List ifEntryList = new ArrayList<>(); for (String ifType : iftypes) { if (SouthboundMapper.createInterfaceType(ifType) != null) { InterfaceTypeEntry ifEntry = new InterfaceTypeEntryBuilder() .setInterfaceType( SouthboundMapper.createInterfaceType(ifType)) .build(); ifEntryList.add(ifEntry); } else { LOG.warn("Interface type {} not present in model", ifType); } } ovsdbNodeBuilder.setInterfaceTypeEntry(ifEntryList); } catch (SchemaVersionMismatchException e) { schemaMismatchLog("iface_types", SouthboundConstants.OPEN_V_SWITCH, e); } } private void setDataPathTypes( OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, OpenVSwitch openVSwitch) { try { Set dptypes = openVSwitch.getDatapathTypesColumn() .getData(); List dpEntryList = new ArrayList<>(); for (String dpType : dptypes) { if (SouthboundMapper.createDatapathType(dpType) != null) { DatapathTypeEntry dpEntry = new DatapathTypeEntryBuilder() .setDatapathType( SouthboundMapper.createDatapathType(dpType)) .build(); dpEntryList.add(dpEntry); } else { LOG.warn("Datapath type {} not present in model", dpType); } } ovsdbNodeBuilder.setDatapathTypeEntry(dpEntryList); } catch (SchemaVersionMismatchException e) { schemaMismatchLog("datapath_types", SouthboundConstants.OPEN_V_SWITCH, e); } } private void setVersion(OvsdbNodeAugmentationBuilder ovsdbNodeBuilder, OpenVSwitch openVSwitch) { try { ovsdbNodeBuilder.setOvsVersion(openVSwitch.getOvsVersionColumn().getData().iterator().next()); } catch (NoSuchElementException e) { LOG.debug("ovs_version is not set for this switch",e); } } private InstanceIdentifier getInstanceIdentifier(OpenVSwitch ovs) { if (ovs.getExternalIdsColumn() != null && ovs.getExternalIdsColumn().getData() != null && ovs.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) { String iidString = ovs.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY); InstanceIdentifier iid = (InstanceIdentifier) SouthboundUtil.deserializeInstanceIdentifier(iidString); getOvsdbConnectionInstance().setInstanceIdentifier(iid); } else { String nodeString = SouthboundConstants.OVSDB_URI_PREFIX + "://" + SouthboundConstants.UUID + "/" + ovs.getUuid().toString(); NodeId nodeId = new NodeId(new Uri(nodeString)); NodeKey nodeKey = new NodeKey(nodeId); InstanceIdentifier iid = InstanceIdentifier.builder(NetworkTopology.class) .child(Topology.class,new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) .child(Node.class,nodeKey) .build(); getOvsdbConnectionInstance().setInstanceIdentifier(iid); } return getOvsdbConnectionInstance().getInstanceIdentifier(); } private NodeId getNodeId(OpenVSwitch ovs) { NodeKey nodeKey = getInstanceIdentifier(ovs).firstKeyOf(Node.class, NodeKey.class); return nodeKey.getNodeId(); } }