+
+ public boolean addTerminationPoint(
+ Node bridgeNode, String portName, String type, Map<String, String> options,
+ Map<String, String> externalIds) {
+ return addTerminationPoint(bridgeNode, portName, type, options, externalIds, null);
+ }
+
+ public boolean addTerminationPoint(
+ Node bridgeNode, String portName, String type, Map<String, String> options, Map<String, String> externalIds,
+ Long ofPort) {
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+
+ tpAugmentationBuilder.setName(portName);
+ tpAugmentationBuilder.setOfport(ofPort);
+ if (type != null) {
+ tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
+ }
+
+ if (options != null && options.size() > 0) {
+ List<Options> optionsList = new ArrayList<>();
+ for (Map.Entry<String, String> entry : options.entrySet()) {
+ OptionsBuilder optionsBuilder = new OptionsBuilder();
+ optionsBuilder.withKey(new OptionsKey(entry.getKey()));
+ optionsBuilder.setOption(entry.getKey());
+ optionsBuilder.setValue(entry.getValue());
+ optionsList.add(optionsBuilder.build());
+ }
+ tpAugmentationBuilder.setOptions(optionsList);
+ }
+
+ if (externalIds != null && externalIds.size() > 0) {
+ List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
+ for (Map.Entry<String, String> entry : externalIds.entrySet()) {
+ InterfaceExternalIdsBuilder interfaceExternalIdsBuilder = new InterfaceExternalIdsBuilder();
+ interfaceExternalIdsBuilder.withKey(new InterfaceExternalIdsKey(entry.getKey()));
+ interfaceExternalIdsBuilder.setExternalIdKey(entry.getKey());
+ interfaceExternalIdsBuilder.setExternalIdValue(entry.getValue());
+ externalIdsList.add(interfaceExternalIdsBuilder.build());
+ }
+ tpAugmentationBuilder.setInterfaceExternalIds(externalIdsList);
+ }
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
+ tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+ /* TODO SB_MIGRATION should this be merge or mdsalUtils.put */
+ return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
+ }
+
+ public Boolean addTerminationPoint(Node bridgeNode, String portName, String type) {
+ return addTerminationPoint(bridgeNode, portName, type, Collections.EMPTY_MAP, null);
+ }
+
+ public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName,
+ String type, Map<String, String> options) {
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+
+ tpAugmentationBuilder.setName(portName);
+ if (type != null) {
+ tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
+ }
+
+ List<Options> optionsList = new ArrayList<>();
+ for (Map.Entry<String, String> entry : options.entrySet()) {
+ OptionsBuilder optionsBuilder = new OptionsBuilder();
+ optionsBuilder.withKey(new OptionsKey(entry.getKey()));
+ optionsBuilder.setOption(entry.getKey());
+ optionsBuilder.setValue(entry.getValue());
+ optionsList.add(optionsBuilder.build());
+ }
+ tpAugmentationBuilder.setOptions(optionsList);
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
+ tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+ /* TODO SB_MIGRATION should this be merge or mdsalUtils.put */
+ return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
+ }
+
+ public Boolean addTerminationPoint(Node bridgeNode, String bridgeName, String portName, String type) {
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(bridgeNode, portName);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
+ new OvsdbTerminationPointAugmentationBuilder();
+
+ tpAugmentationBuilder.setName(portName);
+ if (type != null) {
+ tpAugmentationBuilder.setInterfaceType(OVSDB_INTERFACE_TYPE_MAP.get(type));
+ }
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+ return mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build());
+ }
+
+ public Boolean addPatchTerminationPoint(Node node, String bridgeName, String portName, String peerPortName) {
+ Map<String, String> option = new HashMap<>();
+ option.put("peer", peerPortName);
+ return addTerminationPoint(node, bridgeName, portName, PATCH_PORT_TYPE, option);
+ }
+
+ private String getControllerIPAddress() {
+ String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
+ if (addressString != null) {
+ try {
+ if (InetAddress.getByName(addressString) != null) {
+ return addressString;
+ }
+ } catch (UnknownHostException e) {
+ LOG.error("Host {} is invalid", addressString, e);
+ }
+ }
+
+ addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
+ if (addressString != null) {
+ try {
+ if (InetAddress.getByName(addressString) != null) {
+ return addressString;
+ }
+ } catch (UnknownHostException e) {
+ LOG.error("Host {} is invalid", addressString, e);
+ }
+ }
+
+ return null;
+ }
+
+ private short getControllerOFPort() {
+ short openFlowPort = OPENFLOW_PORT;
+ String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
+ if (portString != null) {
+ try {
+ openFlowPort = Short.parseShort(portString);
+ } catch (NumberFormatException e) {
+ LOG.warn("Invalid port:{}, use default({})", portString,
+ openFlowPort, e);
+ }
+ }
+ return openFlowPort;
+ }
+
+ public List<String> getControllersFromOvsdbNode(Node node) {
+ List<String> controllersStr = new ArrayList<>();
+
+ String controllerIpStr = getControllerIPAddress();
+ if (controllerIpStr != null) {
+ // If codepath makes it here, the ip address to be used was explicitly provided.
+ // Being so, also fetch openflowPort provided via ConfigProperties.
+ controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
+ + ":" + controllerIpStr + ":" + getControllerOFPort());
+ } else {
+ // Check if ovsdb node has manager entries
+ OvsdbNodeAugmentation ovsdbNodeAugmentation = extractOvsdbNode(node);
+ if (ovsdbNodeAugmentation != null) {
+ List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
+ if (managerEntries != null && !managerEntries.isEmpty()) {
+ for (ManagerEntry managerEntry : managerEntries) {
+ if (managerEntry == null || managerEntry.getTarget() == null) {
+ continue;
+ }
+ String[] tokens = managerEntry.getTarget().getValue().split(":");
+ if (tokens.length == 3 && tokens[0].equalsIgnoreCase("tcp")) {
+ controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
+ + ":" + tokens[1] + ":" + getControllerOFPort());
+ } else if (tokens[0].equalsIgnoreCase("ptcp")) {
+ ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
+ if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
+ controllerIpStr = String.valueOf(connectionInfo.getLocalIp().getValue());
+ controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
+ + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
+ } else {
+ LOG.warn("Ovsdb Node does not contain connection info: {}", node);
+ }
+ } else if (tokens.length == 3 && tokens[0].equalsIgnoreCase("ssl")) {
+ controllersStr.add(OPENFLOW_SECURE_PROTOCOL
+ + ":" + tokens[1] + ":" + getControllerOFPort());
+ } else if (tokens[0].equalsIgnoreCase("pssl")) {
+ ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
+ if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
+ controllerIpStr = String.valueOf(connectionInfo.getLocalIp().getValue());
+ controllersStr.add(OPENFLOW_SECURE_PROTOCOL
+ + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
+ } else {
+ LOG.warn("Ovsdb Node does not contain connection info: {}", node);
+ }
+ } else {
+ LOG.trace("Skipping manager entry {} for node {}",
+ managerEntry.getTarget(), node.getNodeId().getValue());
+ }
+ }
+ } else {
+ LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
+ }
+ }
+ }
+
+ if (controllersStr.isEmpty()) {
+ // Neither user provided ip nor ovsdb node has manager entries. Lets use local machine ip address.
+ LOG.debug("Use local machine ip address as a OpenFlow Controller ip address");
+ controllerIpStr = getLocalControllerHostIpAddress();
+ if (controllerIpStr != null) {
+ controllersStr.add(OPENFLOW_CONNECTION_PROTOCOL
+ + ":" + controllerIpStr + ":" + OPENFLOW_PORT);
+ }
+ }
+
+ if (controllersStr.isEmpty()) {
+ LOG.warn("Failed to determine OpenFlow controller ip address");
+ } else if (LOG.isDebugEnabled()) {
+ LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(),
+ controllersStr.stream().collect(Collectors.joining(" ")));
+ }
+
+ return controllersStr;
+ }
+
+ private String getLocalControllerHostIpAddress() {
+ String ipaddress = null;
+ try {
+ for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+ ifaces.hasMoreElements();) {
+ NetworkInterface iface = ifaces.nextElement();
+
+ for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
+ InetAddress inetAddr = inetAddrs.nextElement();
+ if (!inetAddr.isLoopbackAddress() && inetAddr.isSiteLocalAddress()) {
+ ipaddress = inetAddr.getHostAddress();
+ break;
+ }
+ }
+ }
+ } catch (SocketException e) {
+ LOG.warn("Exception while fetching local host ip address ", e);
+ }
+ return ipaddress;
+ }
+
+ public long getDataPathId(Node node) {
+ long dpid = 0L;
+ String datapathId = getDatapathId(node);
+ if (datapathId != null) {
+ dpid = new BigInteger(datapathId.replaceAll(":", ""), 16).longValue();
+ }
+ return dpid;
+ }
+
+ public String getDataPathIdStr(final Node node) {
+ if (node != null) {
+ long dpId = getDataPathId(node);
+ if (dpId != 0) {
+ return String.valueOf(dpId);
+ }
+ }
+
+ return null;
+ }
+
+ public String getDatapathId(Node node) {
+ OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.augmentation(OvsdbBridgeAugmentation.class);
+ return getDatapathId(ovsdbBridgeAugmentation);
+ }
+
+ public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {
+ String datapathId = null;
+ if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
+ datapathId = ovsdbBridgeAugmentation.getDatapathId().getValue();
+ }
+ return datapathId;
+ }
+
+ public String extractBridgeName(Node node) {
+ return node.augmentation(OvsdbBridgeAugmentation.class).getBridgeName().getValue();
+ }
+
+ public boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
+ boolean found = false;
+ OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
+ if (ovsdbNodeAugmentation != null) {
+ List<ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
+ if (managedNodes != null) {
+ for (ManagedNodeEntry managedNode : managedNodes) {
+ InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
+ if (bridgeIid.toString().contains(bridgeName)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ return found;
+ }
+
+ public OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
+ OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
+ InstanceIdentifier<Node> bridgeIid =
+ createInstanceIdentifier(node.key(), bridge);
+ Node bridgeNode = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
+ if (bridgeNode != null) {
+ ovsdbBridgeAugmentation = bridgeNode.augmentation(OvsdbBridgeAugmentation.class);
+ }
+ return ovsdbBridgeAugmentation;
+ }
+
+ private void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
+ NodeKey ovsdbNodeKey) {
+ InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(ovsdbNodeKey.getNodeId());
+ ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
+ }
+
+ public boolean isOvsdbNodeDpdk(Node ovsdbNode) {
+ boolean found = false;
+ OvsdbNodeAugmentation ovsdbNodeAugmentation = extractNodeAugmentation(ovsdbNode);
+ if (ovsdbNodeAugmentation != null) {
+ List<InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
+ if (ifTypes != null) {
+ for (InterfaceTypeEntry ifType : ifTypes) {
+ if (ifType.getInterfaceType().equals(InterfaceTypeDpdk.class)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ return found;
+ }
+
+ private List<ControllerEntry> createControllerEntries(List<String> controllersStr,
+ Long maxBackoff, Long inactivityProbe) {
+ List<ControllerEntry> controllerEntries = new ArrayList<>();
+ if (controllersStr != null) {
+ for (String controllerStr : controllersStr) {
+ ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
+ controllerEntryBuilder.setTarget(new Uri(controllerStr));
+ if (maxBackoff != null) {
+ controllerEntryBuilder.setMaxBackoff(maxBackoff);
+ }
+ if (inactivityProbe != null) {
+ controllerEntryBuilder.setInactivityProbe(inactivityProbe);
+ }
+ controllerEntries.add(controllerEntryBuilder.build());
+ }
+ }
+ return controllerEntries;
+ }
+
+ public OvsdbTerminationPointAugmentation extractTerminationPointAugmentation(Node bridgeNode, String portName) {
+ if (bridgeNode.augmentation(OvsdbBridgeAugmentation.class) != null) {
+ List<OvsdbTerminationPointAugmentation> tpAugmentations = extractTerminationPointAugmentations(bridgeNode);
+ for (OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation : tpAugmentations) {
+ if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
+ return ovsdbTerminationPointAugmentation;
+ }
+ }
+ }
+ return null;
+ }
+
+ public List<OvsdbTerminationPointAugmentation> extractTerminationPointAugmentations(Node node) {
+ List<OvsdbTerminationPointAugmentation> tpAugmentations = new ArrayList<>();
+ if (node == null) {
+ LOG.error("extractTerminationPointAugmentations: Node value is null");
+ return Collections.emptyList();
+ }
+ List<TerminationPoint> terminationPoints = node.getTerminationPoint();
+ if (terminationPoints != null && !terminationPoints.isEmpty()) {
+ for (TerminationPoint tp : terminationPoints) {
+ OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+ tp.augmentation(OvsdbTerminationPointAugmentation.class);
+ if (ovsdbTerminationPointAugmentation != null) {
+ tpAugmentations.add(ovsdbTerminationPointAugmentation);
+ }
+ }
+ }
+ return tpAugmentations;
+ }
+
+ /**
+ * Extract the <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code> identified by
+ * <code>portName</code>.
+ */
+ public OvsdbTerminationPointAugmentation getTerminationPointOfBridge(Node node, String portName) {
+ OvsdbTerminationPointAugmentation tpAugmentation = extractTerminationPointAugmentation(node,portName);
+ if (tpAugmentation == null) {
+ List<OvsdbTerminationPointAugmentation> tpAugmentations = readTerminationPointAugmentations(node);
+ if (tpAugmentations != null) {
+ for (OvsdbTerminationPointAugmentation ovsdbTpAugmentation : tpAugmentations) {
+ if (ovsdbTpAugmentation.getName().equals(portName)) {
+ return ovsdbTpAugmentation;
+ }
+ }
+ }
+ }
+ return tpAugmentation;
+ }
+
+ /**
+ * Read the list of <code>OvsdbTerminationPointAugmentation</code> for the particular <code>node</code>.
+ */
+ public List<OvsdbTerminationPointAugmentation> readTerminationPointAugmentations(Node node) {
+ if (node == null) {
+ LOG.error("readTerminationPointAugmentations: Node value is null");
+ return Collections.emptyList();
+ }
+ Node operNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
+ .child(Node.class, new NodeKey(node.getNodeId())));
+ if (operNode != null) {
+ return extractTerminationPointAugmentations(operNode);
+ }
+ return new ArrayList<>();
+ }
+
+ /**
+ * Get all OVSDB nodes from topology.
+ * @return a list of nodes or null if the topology could not found
+ */
+ public List<Node> getOvsdbNodes() {
+ InstanceIdentifier<Topology> inst = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
+ new TopologyKey(OVSDB_TOPOLOGY_ID));
+ Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, inst);
+ return topology != null ? topology.getNode() : null;
+ }
+
+ /**
+ * Get OpenvSwitch other-config by key.
+ * @param node OVSDB node
+ * @param key key to extract from other-config
+ * @return the value for key or null if key not found
+ */
+ public String getOpenvswitchOtherConfig(Node node, String key) {
+ OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
+ if (ovsdbNode == null) {
+ Node nodeFromReadOvsdbNode = readOvsdbNode(node);
+ if (nodeFromReadOvsdbNode != null) {
+ ovsdbNode = nodeFromReadOvsdbNode.augmentation(OvsdbNodeAugmentation.class);
+ }
+ }
+
+ if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
+ for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
+ if (openvswitchOtherConfigs.getOtherConfigKey().equals(key)) {
+ return openvswitchOtherConfigs.getOtherConfigValue();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static TerminationPoint getTerminationPointByExternalId(final Node bridgeNode, final String interfaceName) {
+ if (bridgeNode.getTerminationPoint() != null) {
+ for (TerminationPoint tp : bridgeNode.getTerminationPoint()) {
+ OvsdbTerminationPointAugmentation ovsdbTp = tp.augmentation(OvsdbTerminationPointAugmentation.class);
+ String externalIdValue = getExternalInterfaceIdValue(ovsdbTp);
+ if (externalIdValue != null && externalIdValue.equals(interfaceName)) {
+ LOG.debug("Found matching termination point with iface-id {} on bridgeNode {}, returning tp {}",
+ interfaceName, bridgeNode, tp);
+ return tp;
+ }
+ }
+ }
+ return null;
+ }
+
+ // This utility shouldn't be called often, as it reads all OVSDB nodes each time - not good for scale
+ public Node getNodeByTerminationPointExternalId(final String interfaceName) {
+ List<Node> nodes = getOvsdbNodes();
+ if (nodes != null) {
+ for (Node node : nodes) {
+ TerminationPoint tp = getTerminationPointByExternalId(node, interfaceName);
+ if (tp != null) {
+ return node;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static String getExternalInterfaceIdValue(final OvsdbTerminationPointAugmentation ovsdbTp) {
+ if (ovsdbTp != null) {
+ List<InterfaceExternalIds> ifaceExtIds = ovsdbTp.getInterfaceExternalIds();
+ if (ifaceExtIds != null) {
+ for (InterfaceExternalIds entry : ifaceExtIds) {
+ if (entry.getExternalIdKey().equals(EXTERNAL_INTERFACE_ID_KEY)) {
+ return entry.getExternalIdValue();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public String getDatapathIdFromNodeInstanceId(InstanceIdentifier<Node> nodeInstanceId) {
+ Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
+ String dpId = node != null ? getDataPathIdStr(node) : null;
+ if (dpId != null) {
+ return dpId;
+ }
+ return null;
+ }
+
+ public static boolean compareDbVersionToMinVersion(final String dbVersion, final String minVersion) {
+ final Matcher dbVersionMatcher = PATTERN.matcher(dbVersion);
+ final Matcher minVersionMatcher = PATTERN.matcher(minVersion);
+ LOG.debug("dbVersion {}, minVersion {}", dbVersion, minVersion);
+ if (!dbVersionMatcher.find()) {
+ LOG.error("Invalid DB version format {}", dbVersion);
+ return false;
+ }
+ if (!minVersionMatcher.find()) {
+ LOG.error("Invalid Min DB version format {}", minVersion);
+ return false;
+ }
+
+ if (dbVersion != null && !dbVersion.isEmpty() && minVersion != null && !minVersion.isEmpty()) {
+ final int dbVersionMatch1 = Integer.parseInt(dbVersionMatcher.group(1));
+ final int dbVersionMatch2 = Integer.parseInt(dbVersionMatcher.group(2));
+ final int dbVersionMatch3 = Integer.parseInt(dbVersionMatcher.group(3));
+ final int minVersionMatch1 = Integer.parseInt(minVersionMatcher.group(1));
+ final int minVersionMatch2 = Integer.parseInt(minVersionMatcher.group(2));
+ final int minVersionMatch3 = Integer.parseInt(minVersionMatcher.group(3));
+ if (dbVersionMatch1 == minVersionMatch1 && dbVersionMatch2 == minVersionMatch2
+ && dbVersionMatch3 == minVersionMatch3) {
+ return true;
+ }
+
+ if (dbVersionMatch1 > minVersionMatch1) {
+ return true;
+ }
+
+ if (dbVersionMatch1 < minVersionMatch1) {
+ return false;
+ }
+
+ // major version is equal
+ if (dbVersionMatch2 > minVersionMatch2) {
+ return true;
+ }
+
+ if (dbVersionMatch2 < minVersionMatch2) {
+ return false;
+ }
+
+ if (dbVersionMatch3 > minVersionMatch3) {
+ return true;
+ }
+ }
+ return false;
+ }