import nmstate-1.0.2-1.el8
This commit is contained in:
parent
ea34f8f454
commit
a7f67e6847
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
SOURCES/nmstate-0.3.2.tar.gz
|
||||
SOURCES/nmstate-1.0.2.tar.gz
|
||||
SOURCES/nmstate.gpg
|
||||
|
@ -1,2 +1,2 @@
|
||||
5f07dbfc599578c7b90fd3efd044bf01f7aa7c4c SOURCES/nmstate-0.3.2.tar.gz
|
||||
c3efe2931425e910002e11ff34ef102fbfa0b9de SOURCES/nmstate.gpg
|
||||
eeda8a0238732e5dc37e2217ed6e316f76c93145 SOURCES/nmstate-1.0.2.tar.gz
|
||||
b5f872551d434e2c62b30d70471efaeede83ab44 SOURCES/nmstate.gpg
|
||||
|
@ -1,217 +0,0 @@
|
||||
From 83a9a81c38463c66ad512aacccfe627aa2b5a17e Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Tue, 23 Jun 2020 10:18:51 +0200
|
||||
Subject: [PATCH 1/3] base_iface: rename iface_type property to type
|
||||
|
||||
In order to follow the property naming, it makes sense to rename
|
||||
"iface_type" property to "type".
|
||||
|
||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
---
|
||||
libnmstate/ifaces/base_iface.py | 4 ++--
|
||||
libnmstate/ifaces/ifaces.py | 9 ++++-----
|
||||
libnmstate/ifaces/ovs.py | 4 ++--
|
||||
libnmstate/plugins/nmstate_plugin_ovsdb.py | 4 ++--
|
||||
4 files changed, 10 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
|
||||
index 56a1115..6c55f6a 100644
|
||||
--- a/libnmstate/ifaces/base_iface.py
|
||||
+++ b/libnmstate/ifaces/base_iface.py
|
||||
@@ -152,7 +152,7 @@ class BaseIface:
|
||||
return self._name
|
||||
|
||||
@property
|
||||
- def iface_type(self):
|
||||
+ def type(self):
|
||||
return self._info.get(Interface.TYPE, InterfaceType.UNKNOWN)
|
||||
|
||||
@property
|
||||
@@ -285,7 +285,7 @@ class BaseIface:
|
||||
if self.is_master and not self.is_absent:
|
||||
for slave_name in self.slaves:
|
||||
slave_iface = ifaces[slave_name]
|
||||
- slave_iface.set_master(self.name, self.iface_type)
|
||||
+ slave_iface.set_master(self.name, self.type)
|
||||
|
||||
def update(self, info):
|
||||
self._info.update(info)
|
||||
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index 9c254ac..e85123c 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -74,7 +74,7 @@ class Ifaces:
|
||||
|
||||
if iface_info.get(Interface.TYPE) is None:
|
||||
if cur_iface:
|
||||
- iface_info[Interface.TYPE] = cur_iface.iface_type
|
||||
+ iface_info[Interface.TYPE] = cur_iface.type
|
||||
elif iface.is_up:
|
||||
raise NmstateValueError(
|
||||
f"Interface {iface.name} has no type defined "
|
||||
@@ -82,7 +82,7 @@ class Ifaces:
|
||||
)
|
||||
iface = _to_specific_iface_obj(iface_info, save_to_disk)
|
||||
if (
|
||||
- iface.iface_type == InterfaceType.UNKNOWN
|
||||
+ iface.type == InterfaceType.UNKNOWN
|
||||
# Allowing deletion of down profiles
|
||||
and not iface.is_absent
|
||||
):
|
||||
@@ -147,7 +147,7 @@ class Ifaces:
|
||||
When OVS patch peer does not exist or is down, raise an error.
|
||||
"""
|
||||
for iface in self._ifaces.values():
|
||||
- if iface.iface_type == InterfaceType.OVS_INTERFACE and iface.is_up:
|
||||
+ if iface.type == InterfaceType.OVS_INTERFACE and iface.is_up:
|
||||
if iface.peer:
|
||||
peer_iface = self._ifaces.get(iface.peer)
|
||||
if not peer_iface or not peer_iface.is_up:
|
||||
@@ -156,8 +156,7 @@ class Ifaces:
|
||||
"be up"
|
||||
)
|
||||
elif (
|
||||
- not peer_iface.iface_type
|
||||
- == InterfaceType.OVS_INTERFACE
|
||||
+ not peer_iface.type == InterfaceType.OVS_INTERFACE
|
||||
or not peer_iface.is_patch_port
|
||||
):
|
||||
raise NmstateValueError(
|
||||
diff --git a/libnmstate/ifaces/ovs.py b/libnmstate/ifaces/ovs.py
|
||||
index 0a5abe9..cd04cef 100644
|
||||
--- a/libnmstate/ifaces/ovs.py
|
||||
+++ b/libnmstate/ifaces/ovs.py
|
||||
@@ -84,7 +84,7 @@ class OvsBridgeIface(BridgeIface):
|
||||
slave_iface.update(
|
||||
{BridgeIface.BRPORT_OPTIONS_METADATA: port_config}
|
||||
)
|
||||
- if slave_iface.iface_type == InterfaceType.OVS_INTERFACE:
|
||||
+ if slave_iface.type == InterfaceType.OVS_INTERFACE:
|
||||
slave_iface.parent = self.name
|
||||
super().gen_metadata(ifaces)
|
||||
|
||||
@@ -101,7 +101,7 @@ class OvsBridgeIface(BridgeIface):
|
||||
}
|
||||
)
|
||||
slave_iface.mark_as_changed()
|
||||
- slave_iface.set_master(self.name, self.iface_type)
|
||||
+ slave_iface.set_master(self.name, self.type)
|
||||
slave_iface.parent = self.name
|
||||
return slave_iface
|
||||
|
||||
diff --git a/libnmstate/plugins/nmstate_plugin_ovsdb.py b/libnmstate/plugins/nmstate_plugin_ovsdb.py
|
||||
index a0cfbc0..83965e1 100644
|
||||
--- a/libnmstate/plugins/nmstate_plugin_ovsdb.py
|
||||
+++ b/libnmstate/plugins/nmstate_plugin_ovsdb.py
|
||||
@@ -168,9 +168,9 @@ class NmstateOvsdbPlugin(NmstatePlugin):
|
||||
continue
|
||||
if not iface.is_up:
|
||||
continue
|
||||
- if iface.iface_type == OVSBridge.TYPE:
|
||||
+ if iface.type == OVSBridge.TYPE:
|
||||
table_name = "Bridge"
|
||||
- elif iface.iface_type == OVSInterface.TYPE:
|
||||
+ elif iface.type == OVSInterface.TYPE:
|
||||
table_name = "Interface"
|
||||
else:
|
||||
continue
|
||||
--
|
||||
2.27.0
|
||||
|
||||
|
||||
From 80a0a200fc198d9f2f31cfa67fbd3d2c776256df Mon Sep 17 00:00:00 2001
|
||||
From: Adwait Thattey <coderdude1999@gmail.com>
|
||||
Date: Thu, 18 Jun 2020 23:11:33 +0530
|
||||
Subject: [PATCH 2/3] iface: add setter method for mtu of interface
|
||||
|
||||
Signed-off-by: Adwait Thattey <coderdude1999@gmail.com>
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
---
|
||||
libnmstate/ifaces/base_iface.py | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
|
||||
index 6c55f6a..edccb1f 100644
|
||||
--- a/libnmstate/ifaces/base_iface.py
|
||||
+++ b/libnmstate/ifaces/base_iface.py
|
||||
@@ -298,6 +298,10 @@ class BaseIface:
|
||||
def mtu(self):
|
||||
return self._info.get(Interface.MTU)
|
||||
|
||||
+ @mtu.setter
|
||||
+ def mtu(self, value):
|
||||
+ self._info[Interface.MTU] = value
|
||||
+
|
||||
def _capitalize_mac(self):
|
||||
if self.mac:
|
||||
self._info[Interface.MAC] = self.mac.upper()
|
||||
--
|
||||
2.27.0
|
||||
|
||||
|
||||
From 60ef20b6b4a4cd76b47b5fa8f989eee2ca2608fd Mon Sep 17 00:00:00 2001
|
||||
From: Adwait Thattey <coderdude1999@gmail.com>
|
||||
Date: Thu, 18 Jun 2020 23:58:11 +0530
|
||||
Subject: [PATCH 3/3] vlan: validate mtu not greater than base iface
|
||||
|
||||
A new validator is added that verifies that the
|
||||
MTU of VLAN/VXLAN is not more than MTU of base iface
|
||||
|
||||
If base iface MTU doesn't exist, set as vlan MTU
|
||||
|
||||
Multiple tests are added to check if appropriate errors are thrown
|
||||
|
||||
Signed-off-by: Adwait Thattey <coderdude1999@gmail.com>
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
---
|
||||
libnmstate/ifaces/ifaces.py | 26 ++++++++++++++++++++++++++
|
||||
1 file changed, 26 insertions(+)
|
||||
|
||||
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index e85123c..c216dd8 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -123,6 +123,7 @@ class Ifaces:
|
||||
|
||||
def _pre_edit_validation_and_cleanup(self):
|
||||
self._validate_over_booked_slaves()
|
||||
+ self._validate_vlan_mtu()
|
||||
self._handle_master_slave_list_change()
|
||||
self._match_child_iface_state_with_parent()
|
||||
self._mark_orphen_as_absent()
|
||||
@@ -164,6 +165,31 @@ class Ifaces:
|
||||
" patch port"
|
||||
)
|
||||
|
||||
+ def _validate_vlan_mtu(self):
|
||||
+ """
|
||||
+ Validate that mtu of vlan or vxlan is less than
|
||||
+ or equal to it's base interface's MTU
|
||||
+
|
||||
+ If base MTU is not present, set same as vlan MTU
|
||||
+ """
|
||||
+ for iface in self._ifaces.values():
|
||||
+
|
||||
+ if (
|
||||
+ iface.type in [InterfaceType.VLAN, InterfaceType.VXLAN]
|
||||
+ and iface.is_up
|
||||
+ and iface.mtu
|
||||
+ ):
|
||||
+ base_iface = self._ifaces.get(iface.parent)
|
||||
+ if not base_iface.mtu:
|
||||
+ base_iface.mtu = iface.mtu
|
||||
+ if iface.mtu > base_iface.mtu:
|
||||
+ raise NmstateValueError(
|
||||
+ f"Interface {iface.name} has bigger "
|
||||
+ f"MTU({iface.mtu}) "
|
||||
+ f"than its base interface: {iface.parent} "
|
||||
+ f"MTU({base_iface.mtu})"
|
||||
+ )
|
||||
+
|
||||
def _handle_master_slave_list_change(self):
|
||||
"""
|
||||
* Mark slave interface as changed if master removed.
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,171 +0,0 @@
|
||||
From d0bfae4171f0d280241949a928654c84e63ed006 Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Mon, 29 Jun 2020 22:30:03 +0800
|
||||
Subject: [PATCH] pretty state: Dumping state in the sorted order with priority
|
||||
|
||||
For OVS bond port, we would like the `name` been shown before other
|
||||
properties.
|
||||
|
||||
To achieve that, we sort the dict keys and honoring the priority list which
|
||||
means keys in `PRIORITY_LIST` will be shown before others.
|
||||
|
||||
Currently the `PRIORITY_LIST` is:
|
||||
`("name", "type", "state", "enabled", "dns", "route-rules", "routes",
|
||||
"interfaces")`
|
||||
|
||||
Test cases added.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
Signed-off-by: Till Maas <till@redhat.com>
|
||||
---
|
||||
libnmstate/prettystate.py | 94 ++++++++++++++++++---------------------
|
||||
1 file changed, 43 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/libnmstate/prettystate.py b/libnmstate/prettystate.py
|
||||
index da57618..10e22d6 100644
|
||||
--- a/libnmstate/prettystate.py
|
||||
+++ b/libnmstate/prettystate.py
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
-# Copyright (c) 2018-2019 Red Hat, Inc.
|
||||
+# Copyright (c) 2018-2020 Red Hat, Inc.
|
||||
#
|
||||
# This file is part of nmstate
|
||||
#
|
||||
@@ -17,15 +17,29 @@
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
-from collections import OrderedDict
|
||||
+from collections.abc import Mapping
|
||||
+from collections.abc import Sequence
|
||||
from copy import deepcopy
|
||||
import difflib
|
||||
import json
|
||||
-from operator import itemgetter
|
||||
|
||||
import yaml
|
||||
|
||||
-from libnmstate.schema import Constants
|
||||
+from .schema import DNS
|
||||
+from .schema import Route
|
||||
+from .schema import RouteRule
|
||||
+from .schema import Interface
|
||||
+
|
||||
+PRIORITY_LIST = (
|
||||
+ "name",
|
||||
+ "type",
|
||||
+ "state",
|
||||
+ "enabled",
|
||||
+ DNS.KEY,
|
||||
+ RouteRule.KEY,
|
||||
+ Route.KEY,
|
||||
+ Interface.KEY,
|
||||
+)
|
||||
|
||||
|
||||
def format_desired_current_state_diff(desired_state, current_state):
|
||||
@@ -57,8 +71,8 @@ def format_desired_current_state_diff(desired_state, current_state):
|
||||
|
||||
class PrettyState:
|
||||
def __init__(self, state):
|
||||
- yaml.add_representer(OrderedDict, represent_ordereddict)
|
||||
- self.state = order_state(deepcopy(state))
|
||||
+ yaml.add_representer(dict, represent_dict)
|
||||
+ self.state = _sort_with_priority(state)
|
||||
|
||||
@property
|
||||
def yaml(self):
|
||||
@@ -71,35 +85,18 @@ class PrettyState:
|
||||
return json.dumps(self.state, indent=4, separators=(",", ": "))
|
||||
|
||||
|
||||
-def represent_ordereddict(dumper, data):
|
||||
+def represent_dict(dumper, data):
|
||||
+ """
|
||||
+ Represent dictionary with insert order
|
||||
"""
|
||||
- Represent OrderedDict as regular dictionary
|
||||
-
|
||||
- Source: https://stackoverflow.com/questions/16782112/can-pyyaml-dump-dict-items-in-non-alphabetical-order
|
||||
- """ # noqa: E501
|
||||
value = []
|
||||
|
||||
for item_key, item_value in data.items():
|
||||
node_key = dumper.represent_data(item_key)
|
||||
node_value = dumper.represent_data(item_value)
|
||||
-
|
||||
value.append((node_key, node_value))
|
||||
|
||||
- return yaml.nodes.MappingNode(u"tag:yaml.org,2002:map", value)
|
||||
-
|
||||
-
|
||||
-def order_state(state):
|
||||
- iface_states = state.pop(Constants.INTERFACES, None)
|
||||
-
|
||||
- state = order_iface_state(state)
|
||||
-
|
||||
- if iface_states is not None:
|
||||
- state[Constants.INTERFACES] = [
|
||||
- order_iface_state(iface_state)
|
||||
- for iface_state in sorted(iface_states, key=itemgetter("name"))
|
||||
- ]
|
||||
-
|
||||
- return state
|
||||
+ return yaml.nodes.MappingNode("tag:yaml.org,2002:map", value)
|
||||
|
||||
|
||||
def represent_unicode(_, data):
|
||||
@@ -112,30 +109,25 @@ def represent_unicode(_, data):
|
||||
"""
|
||||
|
||||
return yaml.ScalarNode(
|
||||
- tag=u"tag:yaml.org,2002:str", value=data.encode("utf-8")
|
||||
+ tag="tag:yaml.org,2002:str", value=data.encode("utf-8")
|
||||
)
|
||||
|
||||
|
||||
-def order_iface_state(iface_state):
|
||||
- ordered_state = OrderedDict()
|
||||
-
|
||||
- for setting in ("name", "type", "state"):
|
||||
- try:
|
||||
- ordered_state[setting] = iface_state.pop(setting)
|
||||
- except KeyError:
|
||||
- pass
|
||||
-
|
||||
- for key, value in order_dict(iface_state).items():
|
||||
- ordered_state[key] = value
|
||||
-
|
||||
- return ordered_state
|
||||
-
|
||||
-
|
||||
-def order_dict(dict_):
|
||||
- ordered_dict = OrderedDict()
|
||||
- for key, value in sorted(dict_.items()):
|
||||
- if isinstance(value, dict):
|
||||
- value = order_dict(value)
|
||||
- ordered_dict[key] = value
|
||||
-
|
||||
- return ordered_dict
|
||||
+def _sort_with_priority(data):
|
||||
+ if isinstance(data, Sequence) and not isinstance(data, str):
|
||||
+ return [_sort_with_priority(item) for item in data]
|
||||
+ elif isinstance(data, Mapping):
|
||||
+ new_data = {}
|
||||
+ for key in sorted(data.keys(), key=_sort_with_priority_key_func):
|
||||
+ new_data[key] = _sort_with_priority(data[key])
|
||||
+ return new_data
|
||||
+ else:
|
||||
+ return deepcopy(data)
|
||||
+
|
||||
+
|
||||
+def _sort_with_priority_key_func(key):
|
||||
+ try:
|
||||
+ priority = PRIORITY_LIST.index(key)
|
||||
+ except ValueError:
|
||||
+ priority = len(PRIORITY_LIST)
|
||||
+ return (priority, key)
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,176 +0,0 @@
|
||||
From c3a924203e8f0d3d6d6fc7882f006d60e7d8d985 Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Fri, 19 Jun 2020 10:14:25 +0800
|
||||
Subject: [PATCH] ip: canonicalize IP address
|
||||
|
||||
Canonicalize these IP addresses:
|
||||
* `InterfaceIP.ADDRESS_IP`
|
||||
* `Route.DESTINATION`
|
||||
* `Route.NEXT_HOP_ADDRESS`
|
||||
* `RouteRule.IP_FROM`
|
||||
* `RouteRule.IP_TO`
|
||||
|
||||
Introduced two functions to `libnmstate/iplib.py`:
|
||||
* `canonicalize_ip_network()` returns address with prefix
|
||||
* `canonicalize_ip_address()` returns address without prefix
|
||||
|
||||
Unit test cases added.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
---
|
||||
libnmstate/ifaces/base_iface.py | 19 +++++++------------
|
||||
libnmstate/iplib.py | 14 ++++++++++++++
|
||||
libnmstate/route.py | 12 ++++++++++++
|
||||
libnmstate/route_rule.py | 14 +++++++-------
|
||||
4 files changed, 40 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
|
||||
index 33da69d..56a1115 100644
|
||||
--- a/libnmstate/ifaces/base_iface.py
|
||||
+++ b/libnmstate/ifaces/base_iface.py
|
||||
@@ -20,13 +20,12 @@
|
||||
from collections.abc import Mapping
|
||||
from copy import deepcopy
|
||||
import logging
|
||||
-from ipaddress import ip_address
|
||||
from operator import itemgetter
|
||||
|
||||
from libnmstate.error import NmstateInternalError
|
||||
from libnmstate.error import NmstateValueError
|
||||
-from libnmstate.iplib import is_ipv6_address
|
||||
from libnmstate.iplib import is_ipv6_link_local_addr
|
||||
+from libnmstate.iplib import canonicalize_ip_address
|
||||
from libnmstate.schema import Interface
|
||||
from libnmstate.schema import InterfaceIP
|
||||
from libnmstate.schema import InterfaceIPv6
|
||||
@@ -44,7 +43,7 @@ class IPState:
|
||||
self._info = info
|
||||
self._remove_stack_if_disabled()
|
||||
self._sort_addresses()
|
||||
- self._canonicalize_ipv6_addr()
|
||||
+ self._canonicalize_ip_addr()
|
||||
self._canonicalize_dynamic()
|
||||
|
||||
def _canonicalize_dynamic(self):
|
||||
@@ -61,15 +60,11 @@ class IPState:
|
||||
):
|
||||
self._info.pop(dhcp_option, None)
|
||||
|
||||
- def _canonicalize_ipv6_addr(self):
|
||||
- """
|
||||
- Convert full IPv6 address to abbreviated address.
|
||||
- """
|
||||
- if self._family == Interface.IPV6:
|
||||
- for addr in self.addresses:
|
||||
- address = addr[InterfaceIP.ADDRESS_IP]
|
||||
- if is_ipv6_address(address):
|
||||
- addr[InterfaceIP.ADDRESS_IP] = str(ip_address(address))
|
||||
+ def _canonicalize_ip_addr(self):
|
||||
+ for addr in self.addresses:
|
||||
+ addr[InterfaceIP.ADDRESS_IP] = canonicalize_ip_address(
|
||||
+ addr[InterfaceIP.ADDRESS_IP]
|
||||
+ )
|
||||
|
||||
def _sort_addresses(self):
|
||||
self.addresses.sort(key=itemgetter(InterfaceIP.ADDRESS_IP))
|
||||
diff --git a/libnmstate/iplib.py b/libnmstate/iplib.py
|
||||
index 57fffd7..183b81b 100644
|
||||
--- a/libnmstate/iplib.py
|
||||
+++ b/libnmstate/iplib.py
|
||||
@@ -52,3 +52,17 @@ def ip_address_full_to_tuple(addr):
|
||||
raise NmstateValueError(f"Invalid IP address, error: {err}")
|
||||
|
||||
return f"{net.network_address}", net.prefixlen
|
||||
+
|
||||
+
|
||||
+def canonicalize_ip_network(address):
|
||||
+ try:
|
||||
+ return ipaddress.ip_network(address, strict=False).with_prefixlen
|
||||
+ except ValueError as e:
|
||||
+ raise NmstateValueError(f"Invalid IP network address: {e}")
|
||||
+
|
||||
+
|
||||
+def canonicalize_ip_address(address):
|
||||
+ try:
|
||||
+ return ipaddress.ip_address(address).compressed
|
||||
+ except ValueError as e:
|
||||
+ raise NmstateValueError(f"Invalid IP address: {e}")
|
||||
diff --git a/libnmstate/route.py b/libnmstate/route.py
|
||||
index 6534182..a182f99 100644
|
||||
--- a/libnmstate/route.py
|
||||
+++ b/libnmstate/route.py
|
||||
@@ -22,6 +22,8 @@ from collections import defaultdict
|
||||
from libnmstate.error import NmstateValueError
|
||||
from libnmstate.error import NmstateVerificationError
|
||||
from libnmstate.iplib import is_ipv6_address
|
||||
+from libnmstate.iplib import canonicalize_ip_network
|
||||
+from libnmstate.iplib import canonicalize_ip_address
|
||||
from libnmstate.prettystate import format_desired_current_state_diff
|
||||
from libnmstate.schema import Interface
|
||||
from libnmstate.schema import Route
|
||||
@@ -44,6 +46,7 @@ class RouteEntry(StateEntry):
|
||||
# TODO: Convert IPv6 full address to abbreviated address
|
||||
self.complement_defaults()
|
||||
self._invalid_reason = None
|
||||
+ self._canonicalize_ip_address()
|
||||
|
||||
@property
|
||||
def is_ipv6(self):
|
||||
@@ -148,6 +151,15 @@ class RouteEntry(StateEntry):
|
||||
return False
|
||||
return True
|
||||
|
||||
+ def _canonicalize_ip_address(self):
|
||||
+ if not self.absent:
|
||||
+ if self.destination:
|
||||
+ self.destination = canonicalize_ip_network(self.destination)
|
||||
+ if self.next_hop_address:
|
||||
+ self.next_hop_address = canonicalize_ip_address(
|
||||
+ self.next_hop_address
|
||||
+ )
|
||||
+
|
||||
|
||||
class RouteState:
|
||||
def __init__(self, ifaces, des_route_state, cur_route_state):
|
||||
diff --git a/libnmstate/route_rule.py b/libnmstate/route_rule.py
|
||||
index 8b45367..f35d59c 100644
|
||||
--- a/libnmstate/route_rule.py
|
||||
+++ b/libnmstate/route_rule.py
|
||||
@@ -6,7 +6,7 @@ from libnmstate.error import NmstateVerificationError
|
||||
from libnmstate.error import NmstateValueError
|
||||
from libnmstate.iplib import KERNEL_MAIN_ROUTE_TABLE_ID
|
||||
from libnmstate.iplib import is_ipv6_address
|
||||
-from libnmstate.iplib import to_ip_address_full
|
||||
+from libnmstate.iplib import canonicalize_ip_network
|
||||
from libnmstate.prettystate import format_desired_current_state_diff
|
||||
from libnmstate.schema import Interface
|
||||
from libnmstate.schema import RouteRule
|
||||
@@ -23,7 +23,7 @@ class RouteRuleEntry(StateEntry):
|
||||
self.priority = route_rule.get(RouteRule.PRIORITY)
|
||||
self.route_table = route_rule.get(RouteRule.ROUTE_TABLE)
|
||||
self._complement_defaults()
|
||||
- self._append_prefix_length_for_host_only_ip()
|
||||
+ self._canonicalize_ip_network()
|
||||
|
||||
def _complement_defaults(self):
|
||||
if self.ip_from is None:
|
||||
@@ -38,11 +38,11 @@ class RouteRuleEntry(StateEntry):
|
||||
):
|
||||
self.route_table = KERNEL_MAIN_ROUTE_TABLE_ID
|
||||
|
||||
- def _append_prefix_length_for_host_only_ip(self):
|
||||
- if self.ip_from and "/" not in self.ip_from:
|
||||
- self.ip_from = to_ip_address_full(self.ip_from)
|
||||
- if self.ip_to and "/" not in self.ip_to:
|
||||
- self.ip_to = to_ip_address_full(self.ip_to)
|
||||
+ def _canonicalize_ip_network(self):
|
||||
+ if self.ip_from:
|
||||
+ self.ip_from = canonicalize_ip_network(self.ip_from)
|
||||
+ if self.ip_to:
|
||||
+ self.ip_to = canonicalize_ip_network(self.ip_to)
|
||||
|
||||
def _keys(self):
|
||||
return (self.ip_from, self.ip_to, self.priority, self.route_table)
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,63 +0,0 @@
|
||||
From 26ca4e3a1a96829ca115f436872d4a575490cce6 Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Wed, 24 Jun 2020 15:27:42 +0800
|
||||
Subject: [PATCH] nm/device: Only invoke reapply on activated device
|
||||
|
||||
Only invoke `NM.Device.reapply_async()` on activated device.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
---
|
||||
libnmstate/nm/device.py | 32 ++++++++++++++++++--------------
|
||||
1 file changed, 18 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/libnmstate/nm/device.py b/libnmstate/nm/device.py
|
||||
index 92447b0..528f57d 100644
|
||||
--- a/libnmstate/nm/device.py
|
||||
+++ b/libnmstate/nm/device.py
|
||||
@@ -53,25 +53,29 @@ def delete(context, dev):
|
||||
con_profile.delete()
|
||||
|
||||
|
||||
-def modify(context, dev, connection_profile):
|
||||
+def modify(context, nm_dev, connection_profile):
|
||||
"""
|
||||
Modify the given connection profile on the device.
|
||||
Implemented by the reapply operation with a fallback to the
|
||||
connection profile activation.
|
||||
"""
|
||||
- version_id = 0
|
||||
- flags = 0
|
||||
- action = f"Reapply device config: {dev.get_iface()}"
|
||||
- context.register_async(action)
|
||||
- user_data = context, dev, action
|
||||
- dev.reapply_async(
|
||||
- connection_profile,
|
||||
- version_id,
|
||||
- flags,
|
||||
- context.cancellable,
|
||||
- _modify_callback,
|
||||
- user_data,
|
||||
- )
|
||||
+ nm_ac = nm_dev.get_active_connection()
|
||||
+ if connection.is_activated(nm_ac, nm_dev):
|
||||
+ version_id = 0
|
||||
+ flags = 0
|
||||
+ action = f"Reapply device config: {nm_dev.get_iface()}"
|
||||
+ context.register_async(action)
|
||||
+ user_data = context, nm_dev, action
|
||||
+ nm_dev.reapply_async(
|
||||
+ connection_profile,
|
||||
+ version_id,
|
||||
+ flags,
|
||||
+ context.cancellable,
|
||||
+ _modify_callback,
|
||||
+ user_data,
|
||||
+ )
|
||||
+ else:
|
||||
+ _activate_async(context, nm_dev)
|
||||
|
||||
|
||||
def _modify_callback(src_object, result, user_data):
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,68 +0,0 @@
|
||||
From 69bed0e79bd951b4e5496cae6b3738649030b5ae Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 20:28:30 +0800
|
||||
Subject: [PATCH] ovs: Eliminate the repeat call of is_ovs_running()
|
||||
|
||||
The `validate_interface_capabilities()` is invoking `is_ovs_running()`
|
||||
on every interface. Fixed by using `set()` for interface types for
|
||||
duplicate types and also caching ovs daemon status.
|
||||
|
||||
The `NetworkManagerPlugin.get_interfaces()` is invoking
|
||||
`is_ovs_running()` on every interface. Fixed by caching ovs daemon
|
||||
status.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
---
|
||||
libnmstate/nm/plugin.py | 3 ++-
|
||||
libnmstate/validator.py | 5 +++--
|
||||
2 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py
|
||||
index 20fa77e..4032359 100644
|
||||
--- a/libnmstate/nm/plugin.py
|
||||
+++ b/libnmstate/nm/plugin.py
|
||||
@@ -97,6 +97,7 @@ class NetworkManagerPlugin(NmstatePlugin):
|
||||
|
||||
def get_interfaces(self):
|
||||
info = []
|
||||
+ capabilities = self.capabilities
|
||||
|
||||
devices_info = [
|
||||
(dev, nm_device.get_device_common_info(dev))
|
||||
@@ -122,7 +123,7 @@ class NetworkManagerPlugin(NmstatePlugin):
|
||||
if nm_bond.is_bond_type_id(type_id):
|
||||
bondinfo = nm_bond.get_bond_info(dev)
|
||||
iface_info.update(_ifaceinfo_bond(bondinfo))
|
||||
- elif NmstatePlugin.OVS_CAPABILITY in self.capabilities:
|
||||
+ elif NmstatePlugin.OVS_CAPABILITY in capabilities:
|
||||
if nm_ovs.is_ovs_bridge_type_id(type_id):
|
||||
iface_info["bridge"] = nm_ovs.get_ovs_info(
|
||||
self.context, dev, devices_info
|
||||
diff --git a/libnmstate/validator.py b/libnmstate/validator.py
|
||||
index ee30166..02890b4 100644
|
||||
--- a/libnmstate/validator.py
|
||||
+++ b/libnmstate/validator.py
|
||||
@@ -47,9 +47,10 @@ def validate_capabilities(state, capabilities):
|
||||
|
||||
|
||||
def validate_interface_capabilities(ifaces_state, capabilities):
|
||||
- ifaces_types = [iface_state.get("type") for iface_state in ifaces_state]
|
||||
+ ifaces_types = {iface_state.get("type") for iface_state in ifaces_state}
|
||||
has_ovs_capability = NmstatePlugin.OVS_CAPABILITY in capabilities
|
||||
has_team_capability = NmstatePlugin.TEAM_CAPABILITY in capabilities
|
||||
+ ovs_is_running = is_ovs_running()
|
||||
for iface_type in ifaces_types:
|
||||
is_ovs_type = iface_type in (
|
||||
InterfaceType.OVS_BRIDGE,
|
||||
@@ -57,7 +58,7 @@ def validate_interface_capabilities(ifaces_state, capabilities):
|
||||
InterfaceType.OVS_PORT,
|
||||
)
|
||||
if is_ovs_type and not has_ovs_capability:
|
||||
- if not is_ovs_running():
|
||||
+ if not ovs_is_running:
|
||||
raise NmstateDependencyError(
|
||||
"openvswitch service is not started."
|
||||
)
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,60 +0,0 @@
|
||||
From 54e49943b636eab9453189381e93c68050c1e423 Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Sun, 28 Jun 2020 20:05:08 +0800
|
||||
Subject: [PATCH] dns: Fix remove dns config
|
||||
|
||||
Current code raise NmstateVerificationError when user not providing
|
||||
the full state:
|
||||
DNS.CONFIG: {DNS.SERVER: [], DNS.SEARCH: []}
|
||||
|
||||
Now supporting remove static DNS config via:
|
||||
* DNS.CONFIG: {}
|
||||
* DNS.CONFIG: {DNS.SERVER: []}
|
||||
* DNS.CONFIG: {DNS.SEARCH: []}
|
||||
* DNS.CONFIG: {DNS.SERVER: [], DNS.SEARCH: []}
|
||||
|
||||
Test case updated for this.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
---
|
||||
libnmstate/dns.py | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libnmstate/dns.py b/libnmstate/dns.py
|
||||
index 3196fc4..1ec0d81 100644
|
||||
--- a/libnmstate/dns.py
|
||||
+++ b/libnmstate/dns.py
|
||||
@@ -33,14 +33,16 @@ class DnsState:
|
||||
|
||||
def __init__(self, des_dns_state, cur_dns_state):
|
||||
self._config_changed = False
|
||||
- if des_dns_state:
|
||||
+ if des_dns_state is None or des_dns_state.get(DNS.CONFIG) is None:
|
||||
+ # Use current config if DNS.KEY not defined or DNS.CONFIG not
|
||||
+ # defined.
|
||||
+ self._dns_state = cur_dns_state or {}
|
||||
+ else:
|
||||
self._dns_state = des_dns_state
|
||||
self._validate()
|
||||
self._config_changed = _is_dns_config_changed(
|
||||
des_dns_state, cur_dns_state
|
||||
)
|
||||
- else:
|
||||
- self._dns_state = cur_dns_state or {}
|
||||
self._cur_dns_state = deepcopy(cur_dns_state) if cur_dns_state else {}
|
||||
|
||||
@property
|
||||
@@ -179,7 +181,9 @@ class DnsState:
|
||||
|
||||
def verify(self, cur_dns_state):
|
||||
cur_dns = DnsState(des_dns_state=None, cur_dns_state=cur_dns_state,)
|
||||
- if self.config != cur_dns.config:
|
||||
+ if self.config.get(DNS.SERVER) != cur_dns.config.get(
|
||||
+ DNS.SERVER
|
||||
+ ) or self.config.get(DNS.SEARCH) != cur_dns.config.get(DNS.SEARCH):
|
||||
raise NmstateVerificationError(
|
||||
format_desired_current_state_diff(
|
||||
{DNS.KEY: self.config}, {DNS.KEY: cur_dns.config},
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,16 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCAAdFiEE8f1XsqXpyNthgIbGbM3lj+QeKP8FAl7nxvAACgkQbM3lj+Qe
|
||||
KP/6yw/9GBET+XD86qCuzu9sxZt2vZTw3CIqvieuCPkzquqymoI2owJ2rCrNpnZy
|
||||
jdhrobV992pt4qpHo12k8o8LubO38rzVkG6lXSJ8rlLrRkJc5c3APJPzeEnuWsrB
|
||||
HL0JZ4Z2MA+q4TdLGPDNrN/XpnOEDphRZcuD6sFIa9nmiCbj6aI2BaQRriwr8bbh
|
||||
W0LBzQ71u5tIXLVKo+Z3XYmQwFcjW8jQkxrfQbTYT80JORc2aC+yBdfayw+5GSsm
|
||||
Us41H8cStfayv4m5t3Cvy8DMoxe1YC/GBY16sPDdmX+qTS43de8vtCgBho3KZrXx
|
||||
cHi2V2/vlxo2Zra2a8wpwDFOU0nPbgRR+79R7w5/2f9U6g0sok3Qa4WLYjYE1tbK
|
||||
l2gw/hdzHRLzq7UuVN8nchNDGmqQErtLJALvf7kWucVgN/u9VqrteEh6ZL7/eZ9G
|
||||
AE3Dot2I+TWBgQ7D1feD9TGj7riY2/m3hNMMG5KeiyifHWDIo3tVqwO4WgaBU25h
|
||||
L2AAQKtS0aBMp034cN1nFUxRAw0cFZPQmE52kSNaIbzQpy+3jR6o43IvLuTOVA4j
|
||||
2FlGr9wGLk/Rom/mt2gGY6agiTnfkIV32Muesqwr0zr55ktbQ64xcIlXlXVpIL4j
|
||||
ysbj8f2dBBR/4J/UrNTtzjEofTsDyO4+2NdXS3HuWTw3X74UFyY=
|
||||
=EP3F
|
||||
-----END PGP SIGNATURE-----
|
16
SOURCES/nmstate-1.0.2.tar.gz.asc
Normal file
16
SOURCES/nmstate-1.0.2.tar.gz.asc
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCAAdFiEEfUQ+BAINyWGvqJXerIciWuEsPqMFAmAueEYACgkQrIciWuEs
|
||||
PqPJxw//UmWdCJgoClFkEpWqWUkjMmfkGh70PoxtuOeNrAYwHv9zCHDBFjLtaDG1
|
||||
18+jakwrVIlTiFHZqfz1g3o0Te86w5rKiU2y0FBtBPZ1cdcJZk2Is5wb/JJo78n+
|
||||
9sWRfZmSN0SMiJ5HfzhTdZ2RsZYRSaDPSUxchRY03LzsBusxoK8swWu9oUHqmYKd
|
||||
S3k4skP5ZQvpHtKzq9w1lfU4YAw42sRvXHW/++HqGgE0rypf+Wlcu9C+It9kVLCr
|
||||
3rdp8iTGTg+LRg7LxFmEsRlmPpxhO25LaxjFvYSFnhE94xOt28KXeHBYs8hPPRwh
|
||||
+z2w6zJ3hgIrLh10IPzePTWk//KNWDRaAJXQTCma1UE4jdL3+wbxb8H3vl5VCrBU
|
||||
3fuj3JwfvFU1NuDf+yuJ0sCKzNXaAzpYYgfIaCaPdtBpg5jl2DTEfEF8QZKYuJDU
|
||||
ueCo6reBAlwJzce433aSzBXshFbHG/RdD09duS3p84Dn6ljEN3GfJwUAC9s9TsAQ
|
||||
U5+rWog6zMpVke/9yqwEf1KmqtLM3/+Ih30CHb3ZoPTf05KB14k0d1CLDdC9d9dy
|
||||
gN0w8xjdTUXbUXW/XIvRVX9KWqyNI6lnZoL0MWzPwUmMxwPJkRpAVpLKpgyUrVpD
|
||||
yjtLTFDZJNmfmbi2b0myFFcc2chaXmYlpLCP8vfRYJA3mCee6Xg=
|
||||
=b/Mh
|
||||
-----END PGP SIGNATURE-----
|
@ -3,20 +3,14 @@
|
||||
%define libname libnmstate
|
||||
|
||||
Name: nmstate
|
||||
Version: 0.3.2
|
||||
Release: 6%{?dist}
|
||||
Version: 1.0.2
|
||||
Release: 1%{?dist}
|
||||
Summary: Declarative network manager API
|
||||
License: LGPLv2+
|
||||
URL: https://github.com/%{srcname}/%{srcname}
|
||||
Source0: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz
|
||||
Source1: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz.asc
|
||||
Source2: https://www.nmstate.io/nmstate.gpg
|
||||
Patch1: BZ_1850698-Fix-remove-dns-config.patch
|
||||
Patch2: BZ_1788763_improve_vlan_mtu_error_message.patch
|
||||
Patch3: BZ_1816612_canonicalize-IP-address.patch
|
||||
Patch4: BZ_1806474-sort-pretty-state-with-priority.patch
|
||||
Patch5: BZ_1820009_remove_duplicate_call_of_is_ovs_running.patch
|
||||
Patch6: BZ_1820009_only_reapply_if_activated.patch
|
||||
BuildArch: noarch
|
||||
BuildRequires: python3-devel
|
||||
BuildRequires: python3-setuptools
|
||||
@ -33,7 +27,7 @@ provider support on the southbound.
|
||||
|
||||
%package -n python3-%{libname}
|
||||
Summary: nmstate Python 3 API library
|
||||
Requires: NetworkManager-libnm >= 1:1.22.16
|
||||
Requires: NetworkManager-libnm >= 1:1.26.0
|
||||
# Use Recommends for NetworkManager because only access to NM DBus is required,
|
||||
# but NM could be running on a different host
|
||||
Recommends: NetworkManager
|
||||
@ -43,6 +37,8 @@ Recommends: NetworkManager-config-server
|
||||
# required for OVS and team support
|
||||
Suggests: NetworkManager-ovs
|
||||
Suggests: NetworkManager-team
|
||||
Requires: nispor
|
||||
Requires: python3dist(varlink)
|
||||
|
||||
%package -n nmstate-plugin-ovsdb
|
||||
Summary: nmstate plugin for OVS database manipulation
|
||||
@ -87,6 +83,92 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0}
|
||||
%{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb*
|
||||
|
||||
%changelog
|
||||
* Fri Feb 19 2021 Gris Ge <fge@redhat.com> - 1.0.2-1
|
||||
- Upgrade to 1.0.2.
|
||||
|
||||
* Wed Feb 10 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-0.3
|
||||
- Fix sources name
|
||||
|
||||
* Wed Feb 10 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-0.2
|
||||
- Upgrade to 1.0.2 alpha 2
|
||||
|
||||
* Tue Jan 26 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-0.1
|
||||
- Upgrade to 1.0.2 alpha 1
|
||||
|
||||
* Tue Jan 19 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.1-1
|
||||
- Upgrade to 1.0.1. RHBZ#1881287
|
||||
|
||||
* Tue Jan 05 2021 Gris Ge <fge@redhat.com> - 1.0.1-0.1
|
||||
- Upgrade to 1.0.1 alpha 1
|
||||
|
||||
* Tue Dec 08 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.0-1
|
||||
- Upgrade to 1.0.0
|
||||
|
||||
* Mon Nov 16 2020 Gris Ge <fge@redhat.com> - 1.0.0-0.1
|
||||
- Upgrade to 1.0.0 alpha 1
|
||||
|
||||
* Wed Oct 28 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.1-2
|
||||
- Allow VRF port to hold IP information
|
||||
|
||||
* Thu Oct 22 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.1-1
|
||||
- Upgrade to 0.4.1
|
||||
|
||||
* Tue Oct 20 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.0-3
|
||||
- Add nispor as a dependency for CI gating
|
||||
|
||||
* Tue Oct 20 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.0-2
|
||||
- Rebuild for CI gating
|
||||
- Remove old patches from the repository
|
||||
|
||||
* Mon Sep 14 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.0-1
|
||||
- Upgrade to 0.4.0
|
||||
- Sync. up with upstream spec file.
|
||||
|
||||
* Tue Aug 18 2020 Gris Ge <fge@redhat.com> - 0.3.4-12
|
||||
- New patch: OVSDB: Allowing remove all OVS ports. RHBZ#1869345
|
||||
|
||||
* Tue Aug 18 2020 Gris Ge <fge@redhat.com> - 0.3.4-11
|
||||
- OVSDB: Allowing remove all OVS ports. RHBZ#1869345
|
||||
|
||||
* Thu Aug 06 2020 Gris Ge <fge@redhat.com> - 0.3.4-10
|
||||
- OVSDB: Preserv old external_ids. RHBZ#1866269
|
||||
|
||||
* Tue Aug 04 2020 Gris Ge <fge@redhat.com> - 0.3.4-9
|
||||
- Fix converting memory only profile to persistent. RHBZ#1859844
|
||||
|
||||
* Mon Aug 03 2020 Gris Ge <fge@redhat.com> - 0.3.4-8
|
||||
- Fix failure when adding ovs bond to existing bridge. RHBZ#1858758
|
||||
|
||||
* Thu Jul 30 2020 Gris Ge <fge@redhat.com> - 0.3.4-7
|
||||
- Remove existing inactivate NM profiles. RHBZ#1862025
|
||||
|
||||
* Wed Jul 29 2020 Gris Ge <fge@redhat.com> - 0.3.4-6
|
||||
- New build to retrigger the CI gating.
|
||||
|
||||
* Wed Jul 29 2020 Gris Ge <fge@redhat.com> - 0.3.4-5
|
||||
- Use new patch. RHBZ#1861668
|
||||
|
||||
* Wed Jul 29 2020 Gris Ge <fge@redhat.com> - 0.3.4-4
|
||||
- Ignore unknown interface. RHBZ#1861668
|
||||
|
||||
* Tue Jul 28 2020 Gris Ge <fge@redhat.com> - 0.3.4-3
|
||||
- Add support NetworkManaged exteranl managed interface. RHBZ#1861263
|
||||
|
||||
* Tue Jul 28 2020 Gris Ge <fge@redhat.com> - 0.3.4-2
|
||||
- Hide MTU for OVS patch port. RHBZ#1858762
|
||||
|
||||
* Sat Jul 25 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-1
|
||||
- Upgrade to 0.3.4
|
||||
|
||||
* Fri Jul 24 2020 Gris Ge <fge@redhat.com> - 0.3.3-3
|
||||
- Allowing child been marked absent. RHBZ#1859148
|
||||
|
||||
* Mon Jul 06 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.3-2
|
||||
- Fix bug 1850698
|
||||
|
||||
* Thu Jul 02 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.3-1
|
||||
- Upgrade to 0.3.3
|
||||
|
||||
* Mon Jun 29 2020 Gris Ge <fge@redhat.com> - 0.3.2-6
|
||||
- Improve performance by remove unneeded calls. RHBZ#1820009
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user