[libvirt] [PATCH 0/3] attach-interface: Learn net type='direct'

I've just wanted to hotplug a macvtap device into a running guest. I was too lazy to write an XML, and I've found out that virsh attach-interface doesn't know how to plug macvtaps. Michal Privoznik (3): virsh attach-interface: Use enum instead of arbitrary integers virsh: Use VIR_ENUM* macros for vshCmdAttachInterface virsh attach-interface: Allow macvtap hotplug tools/virsh-domain.c | 38 ++++++++++++++++++++++++++++---------- tools/virsh.pod | 14 ++++++++------ 2 files changed, 36 insertions(+), 16 deletions(-) -- 2.0.5

The type of interface to attach is held in the variable 'typ'. Depending on interface type selected by user, the variable is set either to 1 (network), or 2 (bridge). Lets use an enum instead. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index bab44fe..b465eb5 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -854,6 +854,11 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) return 0; } +typedef enum { + IFACE_TYPE_NETWORK, + IFACE_TYPE_BRIDGE, +} vshCmdAttachInterfaceType; + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -862,7 +867,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) *type = NULL, *source = NULL, *model = NULL, *inboundStr = NULL, *outboundStr = NULL; virNetDevBandwidthRate inbound, outbound; - int typ; + vshCmdAttachInterfaceType typ; int ret; bool functionReturn = false; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -902,9 +907,9 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) /* check interface type */ if (STREQ(type, "network")) { - typ = 1; + typ = IFACE_TYPE_NETWORK; } else if (STREQ(type, "bridge")) { - typ = 2; + typ = IFACE_TYPE_BRIDGE; } else { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); @@ -938,9 +943,9 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type); virBufferAdjustIndent(&buf, 2); - if (typ == 1) + if (typ == IFACE_TYPE_NETWORK) virBufferAsprintf(&buf, "<source network='%s'/>\n", source); - else if (typ == 2) + else if (typ == IFACE_TYPE_BRIDGE) virBufferAsprintf(&buf, "<source bridge='%s'/>\n", source); if (target != NULL) -- 2.0.5

On Mon, Feb 09, 2015 at 10:58:28 +0100, Michal Privoznik wrote:
The type of interface to attach is held in the variable 'typ'. Depending on interface type selected by user, the variable is set either to 1 (network), or 2 (bridge). Lets use an enum instead.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
ACK, Peter

Instead of verbose string to enum conversion (if STREQ() else if STREQ() else if STREQ() ...) lets use awesome VIR_ENUM_* macros. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b465eb5..c7e4926 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -855,10 +855,16 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) } typedef enum { - IFACE_TYPE_NETWORK, + IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_LAST, } vshCmdAttachInterfaceType; +VIR_ENUM_DECL(vshCmdAttachInterface) +VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, + "network", + "bridge") + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -906,11 +912,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) goto cleanup; /* check interface type */ - if (STREQ(type, "network")) { - typ = IFACE_TYPE_NETWORK; - } else if (STREQ(type, "bridge")) { - typ = IFACE_TYPE_BRIDGE; - } else { + if ((typ = vshCmdAttachInterfaceTypeFromString(type)) < 0) { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); goto cleanup; @@ -943,10 +945,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type); virBufferAdjustIndent(&buf, 2); - if (typ == IFACE_TYPE_NETWORK) - virBufferAsprintf(&buf, "<source network='%s'/>\n", source); - else if (typ == IFACE_TYPE_BRIDGE) - virBufferAsprintf(&buf, "<source bridge='%s'/>\n", source); + switch (typ) { + case IFACE_TYPE_NETWORK: + case IFACE_TYPE_BRIDGE: + virBufferAsprintf(&buf, "<source %s='%s'/>\n", + vshCmdAttachInterfaceTypeToString(typ), source); + break; + case IFACE_TYPE_LAST: + /* nada */ + break; + } if (target != NULL) virBufferAsprintf(&buf, "<target dev='%s'/>\n", target); -- 2.0.5

On Mon, Feb 09, 2015 at 10:58:29 +0100, Michal Privoznik wrote:
Instead of verbose string to enum conversion (if STREQ() else if STREQ() else if STREQ() ...) lets use awesome VIR_ENUM_* macros.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b465eb5..c7e4926 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -855,10 +855,16 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) }
typedef enum { - IFACE_TYPE_NETWORK, + IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_LAST,
Usually we don't put a comma after the _LAST item.
} vshCmdAttachInterfaceType;
+VIR_ENUM_DECL(vshCmdAttachInterface) +VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, + "network", + "bridge") + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -906,11 +912,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) goto cleanup;
/* check interface type */ - if (STREQ(type, "network")) { - typ = IFACE_TYPE_NETWORK; - } else if (STREQ(type, "bridge")) { - typ = IFACE_TYPE_BRIDGE; - } else { + if ((typ = vshCmdAttachInterfaceTypeFromString(type)) < 0) { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); goto cleanup; @@ -943,10 +945,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type); virBufferAdjustIndent(&buf, 2);
- if (typ == IFACE_TYPE_NETWORK) - virBufferAsprintf(&buf, "<source network='%s'/>\n", source); - else if (typ == IFACE_TYPE_BRIDGE) - virBufferAsprintf(&buf, "<source bridge='%s'/>\n", source); + switch (typ) { + case IFACE_TYPE_NETWORK: + case IFACE_TYPE_BRIDGE: + virBufferAsprintf(&buf, "<source %s='%s'/>\n", + vshCmdAttachInterfaceTypeToString(typ), source); + break; + case IFACE_TYPE_LAST: + /* nada */
Usually we don't put the comment for the _LAST item as it's obvious it does "nada".
+ break; + }
if (target != NULL) virBufferAsprintf(&buf, "<target dev='%s'/>\n", target);
ACK with the cosmetic changes. Peter

On Mon, Feb 09, 2015 at 10:58:29AM +0100, Michal Privoznik wrote:
Instead of verbose string to enum conversion (if STREQ() else if STREQ() else if STREQ() ...) lets use awesome VIR_ENUM_* macros.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b465eb5..c7e4926 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -855,10 +855,16 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) }
typedef enum { - IFACE_TYPE_NETWORK, + IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_LAST, } vshCmdAttachInterfaceType;
+VIR_ENUM_DECL(vshCmdAttachInterface) +VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, + "network", + "bridge") + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -906,11 +912,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) goto cleanup;
/* check interface type */ - if (STREQ(type, "network")) { - typ = IFACE_TYPE_NETWORK; - } else if (STREQ(type, "bridge")) { - typ = IFACE_TYPE_BRIDGE; - } else { + if ((typ = vshCmdAttachInterfaceTypeFromString(type)) < 0) { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); goto cleanup; @@ -943,10 +945,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type);
Here, the type argument is already assumed to use values from the virDomainNetType enum. I think we can reuse that type here, instead of creating a new enum. Jan

On 09.02.2015 14:19, Ján Tomko wrote:
On Mon, Feb 09, 2015 at 10:58:29AM +0100, Michal Privoznik wrote:
Instead of verbose string to enum conversion (if STREQ() else if STREQ() else if STREQ() ...) lets use awesome VIR_ENUM_* macros.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b465eb5..c7e4926 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -855,10 +855,16 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) }
typedef enum { - IFACE_TYPE_NETWORK, + IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_LAST, } vshCmdAttachInterfaceType;
+VIR_ENUM_DECL(vshCmdAttachInterface) +VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, + "network", + "bridge") + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -906,11 +912,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) goto cleanup;
/* check interface type */ - if (STREQ(type, "network")) { - typ = IFACE_TYPE_NETWORK; - } else if (STREQ(type, "bridge")) { - typ = IFACE_TYPE_BRIDGE; - } else { + if ((typ = vshCmdAttachInterfaceTypeFromString(type)) < 0) { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); goto cleanup; @@ -943,10 +945,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type);
Here, the type argument is already assumed to use values from the virDomainNetType enum. I think we can reuse that type here, instead of creating a new enum.
Oh, you're right. I know about the enum, but for some reason thought it's libvirt internals, and virsh has no access to it. But we are already doing that, apparently: libvirt.git $ git grep domain_conf\.h tools/ | wc -l 3 So 1/2 and 2/3 are not needed. Let me respin the patches then. Michal

On 02/09/2015 08:19 AM, Ján Tomko wrote:
On Mon, Feb 09, 2015 at 10:58:29AM +0100, Michal Privoznik wrote:
Instead of verbose string to enum conversion (if STREQ() else if STREQ() else if STREQ() ...) lets use awesome VIR_ENUM_* macros.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b465eb5..c7e4926 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -855,10 +855,16 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) }
typedef enum { - IFACE_TYPE_NETWORK, + IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_LAST, } vshCmdAttachInterfaceType;
+VIR_ENUM_DECL(vshCmdAttachInterface) +VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, + "network", + "bridge") + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -906,11 +912,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) goto cleanup;
/* check interface type */ - if (STREQ(type, "network")) { - typ = IFACE_TYPE_NETWORK; - } else if (STREQ(type, "bridge")) { - typ = IFACE_TYPE_BRIDGE; - } else { + if ((typ = vshCmdAttachInterfaceTypeFromString(type)) < 0) { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); goto cleanup; @@ -943,10 +945,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type); Here, the type argument is already assumed to use values from the virDomainNetType enum. I think we can reuse that type here, instead of creating a new enum.
Except that virDomainNetType is not a part of libvirt's public API, and so is not available to an application program like virsh.

On Mon, Feb 09, 2015 at 09:47:47AM -0500, Laine Stump wrote:
On 02/09/2015 08:19 AM, Ján Tomko wrote:
On Mon, Feb 09, 2015 at 10:58:29AM +0100, Michal Privoznik wrote:
Instead of verbose string to enum conversion (if STREQ() else if STREQ() else if STREQ() ...) lets use awesome VIR_ENUM_* macros.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b465eb5..c7e4926 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -855,10 +855,16 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) }
typedef enum { - IFACE_TYPE_NETWORK, + IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_LAST, } vshCmdAttachInterfaceType;
+VIR_ENUM_DECL(vshCmdAttachInterface) +VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, + "network", + "bridge") + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -906,11 +912,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) goto cleanup;
/* check interface type */ - if (STREQ(type, "network")) { - typ = IFACE_TYPE_NETWORK; - } else if (STREQ(type, "bridge")) { - typ = IFACE_TYPE_BRIDGE; - } else { + if ((typ = vshCmdAttachInterfaceTypeFromString(type)) < 0) { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); goto cleanup; @@ -943,10 +945,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type); Here, the type argument is already assumed to use values from the virDomainNetType enum. I think we can reuse that type here, instead of creating a new enum.
Except that virDomainNetType is not a part of libvirt's public API, and so is not available to an application program like virsh.
We already include conf/*.h files in virsh. Should they be removed to make virsh a cleaner example of a client app? Or left in to avoid code duplication? Jan

On Mon, Feb 09, 2015 at 04:02:04PM +0100, Ján Tomko wrote:
On Mon, Feb 09, 2015 at 09:47:47AM -0500, Laine Stump wrote:
On 02/09/2015 08:19 AM, Ján Tomko wrote:
On Mon, Feb 09, 2015 at 10:58:29AM +0100, Michal Privoznik wrote:
Instead of verbose string to enum conversion (if STREQ() else if STREQ() else if STREQ() ...) lets use awesome VIR_ENUM_* macros.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b465eb5..c7e4926 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -855,10 +855,16 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) }
typedef enum { - IFACE_TYPE_NETWORK, + IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_LAST, } vshCmdAttachInterfaceType;
+VIR_ENUM_DECL(vshCmdAttachInterface) +VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, + "network", + "bridge") + static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) { @@ -906,11 +912,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) goto cleanup;
/* check interface type */ - if (STREQ(type, "network")) { - typ = IFACE_TYPE_NETWORK; - } else if (STREQ(type, "bridge")) { - typ = IFACE_TYPE_BRIDGE; - } else { + if ((typ = vshCmdAttachInterfaceTypeFromString(type)) < 0) { vshError(ctl, _("No support for %s in command 'attach-interface'"), type); goto cleanup; @@ -943,10 +945,16 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<interface type='%s'>\n", type); Here, the type argument is already assumed to use values from the virDomainNetType enum. I think we can reuse that type here, instead of creating a new enum.
Except that virDomainNetType is not a part of libvirt's public API, and so is not available to an application program like virsh.
We already include conf/*.h files in virsh.
Should they be removed to make virsh a cleaner example of a client app? Or left in to avoid code duplication?
I think virsh should aim to only use the public API in general. If we find the public API is insufficient for virsh, it is probably also insufficient for other apps, and as such we should be looking at extending the public API rather than letting virsh access private methods. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Our hotplug code supports macvtap insertion to guests. However, we somehow forgot about 'attach-interface' (which tries to build XML from passed arguments and use virDomainAttachDeviceFlags()). New type is accessible under 'direct' type, to keep the same type as used in domain XML. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 7 ++++++- tools/virsh.pod | 14 ++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index c7e4926..91b6f12 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -857,13 +857,15 @@ static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) typedef enum { IFACE_TYPE_NETWORK = 0, IFACE_TYPE_BRIDGE, + IFACE_TYPE_DIRECT, IFACE_TYPE_LAST, } vshCmdAttachInterfaceType; VIR_ENUM_DECL(vshCmdAttachInterface) VIR_ENUM_IMPL(vshCmdAttachInterface, IFACE_TYPE_LAST, "network", - "bridge") + "bridge", + "direct") static bool cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) @@ -951,6 +953,9 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) virBufferAsprintf(&buf, "<source %s='%s'/>\n", vshCmdAttachInterfaceTypeToString(typ), source); break; + case IFACE_TYPE_DIRECT: + virBufferAsprintf(&buf, "<source dev='%s'/>\n", source); + break; case IFACE_TYPE_LAST: /* nada */ break; diff --git a/tools/virsh.pod b/tools/virsh.pod index e367e04..b89a649 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -2390,12 +2390,14 @@ Likewise, I<--shareable> is an alias for I<--mode shareable>. [I<--target target>] [I<--mac mac>] [I<--script script>] [I<--model model>] [I<--config>] [I<--inbound average,peak,burst>] [I<--outbound average,peak,burst>] -Attach a new network interface to the domain. I<type> can be either -I<network> to indicate connection via a libvirt virtual network or -I<bridge> to indicate connection via a bridge device on the host. -I<source> indicates the source of the connection (either the name of a -network, or of a bridge device). I<target> is used to specify the -tap/macvtap device to be used to connect the domain to the +Attach a new network interface to the domain. I<type> can be +I<network> to indicate connection via a libvirt virtual network, or +I<bridge> to indicate connection via a bridge device on the host, or +I<direct> to indicate connection directly to one of the host's network +interfaces or bridges. I<source> indicates the source of the +connection (the name of a network, or of a bridge device, or the +host's network interfaces or bridges). I<target> is used to specify +the tap/macvtap device to be used to connect the domain to the source. Names starting with 'vnet' are considered as auto-generated and are blanked out/regenerated each time the interface is attached. I<mac> specifies the MAC address of the network interface; if a MAC -- 2.0.5

On Mon, Feb 09, 2015 at 10:58:30 +0100, Michal Privoznik wrote:
Our hotplug code supports macvtap insertion to guests. However, we somehow forgot about 'attach-interface' (which tries to build XML from passed arguments and use virDomainAttachDeviceFlags()). New type is accessible under 'direct' type, to keep the same type as used in domain XML.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tools/virsh-domain.c | 7 ++++++- tools/virsh.pod | 14 ++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-)
ACK, Peter
participants (5)
-
Daniel P. Berrange
-
Ján Tomko
-
Laine Stump
-
Michal Privoznik
-
Peter Krempa