[libvirt] Unable to setup qemu-guest-agent

2013-06-17 Thread Nehal J. Wani
Could anyone please list out the steps required to run the command
$virsh qemu-agent-command

Steps that I followed:

1. Clone the latest source code of libvirt
2. Create a vm of f18 (source:liveCD)
3. Edit f18 domain xml and add this:

channel type='unix'
   source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/
   target type='virtio' name='org.qemu.guest_agent.0'/
/channel

4. On host: #./tools/virsh start f18
5. On guest: #yum install qemu-guest-agent -y
6. On host: # ./tools/virsh qemu-agent-command f18
'{execute:guest-network-get-interfaces}'

Expected Response:

{return:[{name:lo,ip-
addresses:[{ip-address-type:ipv4,ip-address:127.0.0.1,prefix:8},{ip-address-type:ipv6,ip-address:::1,prefix:128}],hardware-address:00:00:00:00:00:00},{name:eth0,ip-addresses:[{ip-address-type:ipv4,ip-address:192.168.122.62,prefix:24},{ip-address-type:ipv6,ip-address:fe80::5054:ff:fe14:9998,prefix:64}],hardware-address:52:54:00:14:99:98}]}

Actual result:
error: unknown procedure: 3


Where am I going wrong?
-- 
Nehal J. Wani
UG2, BTech CS+MS(CL)
IIIT-Hyderabad
http://commanlinewani.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Unable to setup qemu-guest-agent

2013-06-17 Thread Nehal J. Wani
The error:
# ./tools/virsh qemu-agent-command f18
'{execute:guest-network-get-interfaces}'
error: unknown procedure: 3

Comes when I clone from  $git clone git://libvirt.org/libvirt.git

But  when I download http://libvirt.org/sources/libvirt-1.0.6.tar.gz
and make, I get:
# ./tools/virsh qemu-agent-command f18
'{execute:guest-network-get-interfaces}'
(null)


On 6/17/13, Osier Yang jy...@redhat.com wrote:
 On 17/06/13 14:00, Nehal J. Wani wrote:
 Could anyone please list out the steps required to run the command
 $virsh qemu-agent-command

 Steps that I followed:

 1. Clone the latest source code of libvirt
 2. Create a vm of f18 (source:liveCD)
 3. Edit f18 domain xml and add this:

 channel type='unix'
 source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/
 target type='virtio' name='org.qemu.guest_agent.0'/
 /channel

 4. On host: #./tools/virsh start f18
 5. On guest: #yum install qemu-guest-agent -y
 6. On host: # ./tools/virsh qemu-agent-command f18
 '{execute:guest-network-get-interfaces}'

 Expected Response:

 {return:[{name:lo,ip-
 addresses:[{ip-address-type:ipv4,ip-address:127.0.0.1,prefix:8},{ip-address-type:ipv6,ip-address:::1,prefix:128}],hardware-address:00:00:00:00:00:00},{name:eth0,ip-addresses:[{ip-address-type:ipv4,ip-address:192.168.122.62,prefix:24},{ip-address-type:ipv6,ip-address:fe80::5054:ff:fe14:9998,prefix:64}],hardware-address:52:54:00:14:99:98}]}

 Actual result:
 error: unknown procedure: 3

 What's your running libvirtd's version? It sounds like it's old enough
 without
 the API used by qemu-guest-agent.

 Osier



-- 
Nehal J. Wani
UG2, BTech CS+MS(CL)
IIIT-Hyderabad
http://commanlinewani.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Unable to setup qemu-guest-agent

2013-06-17 Thread Nehal J. Wani
I was able to solve the error. It was a stupid mistake. There was a
mismatch between versions of virsh and the libvirt daemon.


On Mon, Jun 17, 2013 at 3:56 PM, Michal Privoznik mpriv...@redhat.comwrote:

 On 17.06.2013 09:21, Nehal J. Wani wrote:
  The error:
  # ./tools/virsh qemu-agent-command f18
  '{execute:guest-network-get-interfaces}'
  error: unknown procedure: 3
 
  Comes when I clone from  $git clone git://libvirt.org/libvirt.git
 
  But  when I download http://libvirt.org/sources/libvirt-1.0.6.tar.gz
  and make, I get:
  # ./tools/virsh qemu-agent-command f18
  '{execute:guest-network-get-interfaces}'
  (null)
 

 Unfortunately, the patch which dispatches errors from qemu-agent-command
 has been submitted after the 1.0.6 release:

 commit 0eb2f8aa90d26e75ce5d9449da03bb553da85d2d
 Author: Peter Krempa pkre...@redhat.com
 AuthorDate: Mon Jun 3 16:12:52 2013 +0200
 Commit: Peter Krempa pkre...@redhat.com
 CommitDate: Mon Jun 3 17:25:33 2013 +0200

 libvirt-qemu: Dispatch errors from virDomainQemuAgentCommand()

 The original implementation didn't follow the established pattern and
 did not dispatch errors in case of failure.

 So if you could try out building the libvirt from git and get the real
 error.
 Or if you want to use the 1.0.6 release, you'll find the error message in
 the libvirtd log.


 Michal




-- 
Nehal J. Wani
UG2, BTech CS+MS(CL)
IIIT-Hyderabad
http://commanlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] RFC: Introduce API to query IP addresses for given domain

2013-06-28 Thread Nehal J. Wani
Hello, fellow developers!
  I am a GSoC candidate this year working for libvirt.org. My
project is Introduce API to query IP addresses for given domain.
The discussion regarding this feature had started here:
http://www.mail-archive.com/libvir-list@redhat.com/msg51857.html and
then Michal had sent a patch too (refer:
http://www.mail-archive.com/libvir-list@redhat.com/msg57141.html). But
it was not pushed upstream due to lack of extensibility.

So far I've come up with an API and I want to get your opinion before
I start writing the rest so I don't follow the wrong direction.

Following are the valid commands:

domifaddr domain-name
domifaddr domain-name interface-name
domifaddr domain-name interface-name method
domifaddr domain-name method

methods:
(i) Querying qemu-guest-agent
(ii) Getting info from dnsmasq.leases file
(iii) Using the nwfilter to snoop the traffic

If no method is mentioned, qemu-guest-agent will be used.

Previous attempts by Michal had used structs and xml. Structs bring in
restrictions and xml has to be parsed. Hence I am not planning to
continue with either of these.

As a start, I would like to know your comments about my API which
queries the qemu-guest-agent and returns the results in
virTypedParameter **params.

Format(JSON) in which the qemu guest agent returns info:

[{name:lo,
ip-addresses:
[{ip-address-type:ipv4,ip-address:127.0.0.1,prefix:8},
{ip-address-type:ipv6,ip-address:::1,prefix:128}],
hardware-address:00:00:00:00:00:00},
{name:eth0,
ip-addresses:

[{ip-address-type:ipv4,ip-address:192.168.122.42,prefix:24},

{ip-address-type:ipv6,ip-address:fe80::5054:ff:fe09:d240,prefix:64}],
hardware-address:52:54:00:09:d2:40}]

//Possible 1-D Structure (A little hassle to maintain)

params[0] = {iface-count,int,2}
params[1] = {iface-name,string,lo}
params[2] = {iface-hwaddr,string,00:00:00:00:00:00}
params[3] = {iface-addr-count,int,2}
params[4] = {iface-addr-type,string,ipv4}
params[5] = {iface-addr,string,127.0.0.1}
params[6] = {iface-addr-prefix,int,8}
params[7] = {iface-addr-type,string,ipv6}
params[8] = {iface-addr,string,::1}
params[9] = {iface-addr-prefix,int,128}




//2D Structure: (Not very hasslefree, but easier to maintain as one
interface per row)

params[0] = 
{iface-name,string,lo}{iface-hwaddr,string,00:00:00:00:00:00}{iface-addr-type,string,ipv4}{iface-addr,string,127.0.0.1}{iface-addr-prefix,int,8}{iface-addr-type,string,ipv6}{iface-addr,string,::1}{iface-addr-prefix,int,128}
params[1] = 
{iface-name,string,eth0}{iface-hwaddr,string,52:54:00:09:d2:40}{iface-addr-type,string,ipv4}{iface-addr,string,192.168.122.42}{iface-addr-prefix,int,8}{iface-addr-type,string,ipv6}{iface-addr,string,fe80::5054:ff:fe09:d240}{iface-addr-prefix,int,64}


Function definitions that I intend to use are:

static int
remoteDispatchDomainInterfacesAddresses(
virNetServerPtr server ATTRIBUTE_UNUSED,
virNetServerClientPtr client,
virNetMessagePtr msg ATTRIBUTE_UNUSED,
virNetMessageErrorPtr rerr,
remote_domain_interfaces_addresses_args *args,
remote_domain_interfaces_addresses_ret *ret)

int virDomainInterfacesAddresses (virDomainPtr dom,
 virTypedParameterPtr *params,
  int *nparams,
  unsigned int flags);


typedef int
(*virDrvDomainInterfacesAddresses)   (virDomainPtr dom,
  virTypedParameterPtr *params,
  int *nparams,
  unsigned int flags);



int
virDomainInterfacesAddresses (virDomainPtr dom,
 virTypedParameterPtr *params,
 int *nparams,
 unsigned int flags)

int
qemuAgentGetInterfaces(qemuAgentPtr mon,
   virTypedParameterPtr *params,
   int *nparams)


int qemuAgentGetInterfaces(qemuAgentPtr mon,
   virTypedParameterPtr *params,
   int *nparams);


static int
qemuDomainInterfacesAddresses(virDomainPtr dom,
  virTypedParameterPtr *params,
  int *nparams,
  unsigned int flags)

static int
remoteDomainInterfacesAddresses(virDomainPtr dom,
   virTypedParameterPtr *params,
   int *nparams,
unsigned int flags)

static bool
cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)

Also, It will be helpful to know whether we want the client to first
query for the number of parameters and then send the request or have
the server side allocate appropriate memory and return the result once
in for all. In the latter case, I'll be using something of the kind
virTypedParameterPtr ***params.


Thanking You,
Nehal J. Wani
UG2, BTech

Re: [libvirt] RFC: Introduce API to query IP addresses for given domain

2013-07-02 Thread Nehal J. Wani
Following will be the methods:
(i) Querying qemu-guest-agent
(ii) Getting info from dnsmasq.leases file
(iii) Using the nwfilter to snoop the traffic

Valid values:
 domifaddr domain-name qemu-ga
 domifaddr domain-name dnsmasq
 domifaddr domain-name snoop

Suggestions are welcome for the 'name' of values of the option 'method'.

The main idea behind using virTypedParameter: It gives us extensibility -
as long as we tell the user how many interfaces and how many parameters per
interface, then we can add more parameters per interface.

If we use structs, then extensibility is lost.

If we use XML, then first JSON output is parsed into XML, then XML is
parsed. More effort is involved.

As I think the previous patches by Michal were not pushed upstream due to
lack of extensibility.




On Tue, Jul 2, 2013 at 4:03 PM, Daniel P. Berrange berra...@redhat.comwrote:

 On Fri, Jun 28, 2013 at 03:56:10PM +0530, Nehal J. Wani wrote:
  Hello, fellow developers!
I am a GSoC candidate this year working for libvirt.org. My
  project is Introduce API to query IP addresses for given domain.
  The discussion regarding this feature had started here:
  http://www.mail-archive.com/libvir-list@redhat.com/msg51857.html and
  then Michal had sent a patch too (refer:
  http://www.mail-archive.com/libvir-list@redhat.com/msg57141.html). But
  it was not pushed upstream due to lack of extensibility.
 
  So far I've come up with an API and I want to get your opinion before
  I start writing the rest so I don't follow the wrong direction.
 
  Following are the valid commands:
 
  domifaddr domain-name
  domifaddr domain-name interface-name
  domifaddr domain-name interface-name method
  domifaddr domain-name method

 What are valid values for 'method' here ?

 
  methods:
  (i) Querying qemu-guest-agent
  (ii) Getting info from dnsmasq.leases file
  (iii) Using the nwfilter to snoop the traffic
 
  If no method is mentioned, qemu-guest-agent will be used.
 
  Previous attempts by Michal had used structs and xml. Structs bring in
  restrictions and xml has to be parsed. Hence I am not planning to
  continue with either of these.
 
  As a start, I would like to know your comments about my API which
  queries the qemu-guest-agent and returns the results in
  virTypedParameter **params.
 
  Format(JSON) in which the qemu guest agent returns info:
 
  [{name:lo,
ip-addresses:
 
 [{ip-address-type:ipv4,ip-address:127.0.0.1,prefix:8},
 
 {ip-address-type:ipv6,ip-address:::1,prefix:128}],
  hardware-address:00:00:00:00:00:00},
  {name:eth0,
ip-addresses:
 
 [{ip-address-type:ipv4,ip-address:192.168.122.42,prefix:24},
 
 {ip-address-type:ipv6,ip-address:fe80::5054:ff:fe09:d240,prefix:64}],
  hardware-address:52:54:00:09:d2:40}]
 
  //Possible 1-D Structure (A little hassle to maintain)
 
  params[0] = {iface-count,int,2}
  params[1] = {iface-name,string,lo}
  params[2] = {iface-hwaddr,string,00:00:00:00:00:00}
  params[3] = {iface-addr-count,int,2}
  params[4] = {iface-addr-type,string,ipv4}
  params[5] = {iface-addr,string,127.0.0.1}
  params[6] = {iface-addr-prefix,int,8}
  params[7] = {iface-addr-type,string,ipv6}
  params[8] = {iface-addr,string,::1}
  params[9] = {iface-addr-prefix,int,128}
  
  
  
 
  //2D Structure: (Not very hasslefree, but easier to maintain as one
  interface per row)
 
  params[0] =
 {iface-name,string,lo}{iface-hwaddr,string,00:00:00:00:00:00}{iface-addr-type,string,ipv4}{iface-addr,string,127.0.0.1}{iface-addr-prefix,int,8}{iface-addr-type,string,ipv6}{iface-addr,string,::1}{iface-addr-prefix,int,128}
  params[1] =
 {iface-name,string,eth0}{iface-hwaddr,string,52:54:00:09:d2:40}{iface-addr-type,string,ipv4}{iface-addr,string,192.168.122.42}{iface-addr-prefix,int,8}{iface-addr-type,string,ipv6}{iface-addr,string,fe80::5054:ff:fe09:d240}{iface-addr-prefix,int,64}

 IMHO both of these approaches to encoding the data in virTypedParameter
 are seriously unpleasant for an app to deal with. Now this is a true for
 virTypedParameter in general, but I think that the need to deal with a
 list of objects here, each containing a list of typed parameters makes
 it even worse than normal. I wouldn't really like this as an application
 developer.

 Looking at this possible approach of virTypedParameter, I'm think I am
 preferring either the XML or fixed struct approach to this API as was
 proposed in the past, with a bias towards a fixed struct for simplicity
 of use by app developers.

 Regards,
 Danuiel
 --
 |: 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:|




-- 
Nehal J. Wani
UG2, BTech CS+MS(CL)
IIIT-Hyderabad
http://commanlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https

Re: [libvirt] RFC: Introduce API to query IP addresses for given domain

2013-07-08 Thread Nehal J. Wani
Eric, could you please share your opinion as to what should be more
appropriate to use for this functionality: Structs/XML/VirTypedParams ?


On Tue, Jul 2, 2013 at 7:25 PM, Osier Yang jy...@redhat.com wrote:

 On 02/07/13 18:33, Daniel P. Berrange wrote:

 On Fri, Jun 28, 2013 at 03:56:10PM +0530, Nehal J. Wani wrote:

 Hello, fellow developers!
I am a GSoC candidate this year working for libvirt.org. My
 project is Introduce API to query IP addresses for given domain.
 The discussion regarding this feature had started here:
 http://www.mail-archive.com/**libvir-list@redhat.com/**msg51857.htmlhttp://www.mail-archive.com/libvir-list@redhat.com/msg51857.htmland
 then Michal had sent a patch too (refer:
 http://www.mail-archive.com/**libvir-list@redhat.com/**msg57141.htmlhttp://www.mail-archive.com/libvir-list@redhat.com/msg57141.html).
 But
 it was not pushed upstream due to lack of extensibility.

 So far I've come up with an API and I want to get your opinion before
 I start writing the rest so I don't follow the wrong direction.

 Following are the valid commands:

 domifaddr domain-name
 domifaddr domain-name interface-name
 domifaddr domain-name interface-name method
 domifaddr domain-name method

 What are valid values for 'method' here ?

  methods:
 (i) Querying qemu-guest-agent
 (ii) Getting info from dnsmasq.leases file
 (iii) Using the nwfilter to snoop the traffic

 If no method is mentioned, qemu-guest-agent will be used.

 Previous attempts by Michal had used structs and xml. Structs bring in
 restrictions and xml has to be parsed. Hence I am not planning to
 continue with either of these.

 As a start, I would like to know your comments about my API which
 queries the qemu-guest-agent and returns the results in
 virTypedParameter **params.

 Format(JSON) in which the qemu guest agent returns info:

 [{name:lo,
 ip-addresses:
 [{ip-address-type:ipv4,**ip-address:127.0.0.1,*
 *prefix:8},
 {ip-address-type:ipv6,ip-**
 address:::1,prefix:128}],
  hardware-address:00:00:00:**00:00:00},
 {name:eth0,
 ip-addresses:
 [{ip-address-type:ipv4,**
 ip-address:192.168.122.42,**prefix:24},
 {ip-address-type:ipv6,ip-**
 address:fe80::5054:ff:fe09:**d240,prefix:64}],
  hardware-address:52:54:00:**09:d2:40}]

 //Possible 1-D Structure (A little hassle to maintain)

 params[0] = {iface-count,int,2}
 params[1] = {iface-name,string,lo}
 params[2] = {iface-hwaddr,string,00:00:**00:00:00:00}
 params[3] = {iface-addr-count,int,2}
 params[4] = {iface-addr-type,string,**ipv4}
 params[5] = {iface-addr,string,127.0.0.**1}
 params[6] = {iface-addr-prefix,int,8}
 params[7] = {iface-addr-type,string,**ipv6}
 params[8] = {iface-addr,string,::1}
 params[9] = {iface-addr-prefix,int,128}
 
 
 

 //2D Structure: (Not very hasslefree, but easier to maintain as one
 interface per row)

 params[0] = {iface-name,string,lo}{**iface-hwaddr,string,00:00:**
 00:00:00:00}{iface-addr-**type,string,ipv4}{iface-**
 addr,string,127.0.0.1}{**iface-addr-prefix,int,8}{**
 iface-addr-type,string,ipv6**}{iface-addr,string,::1}{**
 iface-addr-prefix,int,128}
 params[1] = {iface-name,string,eth0}{**iface-hwaddr,string,52:54:
 **00:09:d2:40}{iface-addr-**type,string,ipv4}{iface-**
 addr,string,192.168.122.42}**{iface-addr-prefix,int,8}{**
 iface-addr-type,string,ipv6**}{iface-addr,string,fe80::**
 5054:ff:fe09:d240}{iface-**addr-prefix,int,64}

 IMHO both of these approaches to encoding the data in virTypedParameter
 are seriously unpleasant for an app to deal with. Now this is a true for
 virTypedParameter in general, but I think that the need to deal with a
 list of objects here, each containing a list of typed parameters makes
 it even worse than normal. I wouldn't really like this as an application
 developer.

 Looking at this possible approach of virTypedParameter, I'm think I am
 preferring either the XML or fixed struct approach to this API as was
 proposed in the past, with a bias towards a fixed struct for simplicity
 of use by app developers.


 agreed.

 after seeing the trouble caused by multiple addrs, i'm not sure about
 using virTypedParameter too. even if we have an array type value, it still
 looks like not easy to use for api user, one has to know how many elements
 of the array too.




 Regards,
 Danuiel





-- 
Nehal J. Wani
UG2, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] RFC: Introduce API to return configuration/state paths of the network driver

2013-07-25 Thread Nehal J. Wani
Currently, there is no API which returns configuration/state paths of the
network driver.
Although it is a private implementation of the network driver, I don't see
any harm in
making the locations public because although the locations might change,
there will always
be a location for these files. There is a need for this API to implement
method 2 of the
API to query ip addresses of a given domain, refer:
http://www.mail-archive.com/libvir-list@redhat.com/msg79793.html . It is
required to parse
the leases file generated by dnsmasq. So, this API will be used by the qemu
driver, but it
can also be made public, so that, if a user wants to know get some
information from a
configuration file, he can get the location from libvirt and analyze it on
his own. Right now,
there is an alternate way to get the info: by using
networkDnsmasqLeaseFileNameDefault,
defined in /src/network/bridge_driver.c Since this function is static, it
is part of the private
implementation and not visible outside. To make it public, the following
hack is possible:

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a7ff602..7274861 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -124,7 +124,7 @@ static int networkUnplugBandwidth(virNetworkObjPtr net,

 static struct network_driver *driverState = NULL;

-static char *
+char *
 networkDnsmasqLeaseFileNameDefault(const char *netname)
 {
 char *leasefile;
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index 50258b5..40e3990 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -49,6 +49,8 @@ int networkDnsmasqConfContents(virNetworkObjPtr network,
 char **configstr,
 dnsmasqContext *dctx,
 dnsmasqCapsPtr caps);
+char * networkDnsmasqLeaseFileNameDefault(const char *netname)
+ATTRIBUTE_NONNULL(1);
 # else
 /* Define no-op replacements that don't drag in any link dependencies.  */
 #  define networkAllocateActualDevice(iface) 0
@@ -57,6 +59,7 @@ int networkDnsmasqConfContents(virNetworkObjPtr network,
 #  define networkGetNetworkAddress(netname, netaddr) (-2)
 #  define networkDnsmasqConfContents(network, pidfile, configstr, \
 dctx, caps) 0
+#  define networkDnsmasqLeaseFileNameDefault(netname) 0
 # endif

 typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname);

Similar hack has been used so that networkAllocateActualDevice() can be
called
from qemu_command.c. Although the above method works, we want to have a
formal API and not leave things like a hack.

/*
 * @conn: connection object
 * @params: array to populate on output
 * @nparams: number of parameters that will be filled
 * @flags: not supported, user should pass 0 for now
 * return 0 on success -1 otherwise
 * Valid parameter field names:
 * VIR_NETWORK_CONFIG_DIR, VIR_NETWORK_AUTOSTART_DIR, VIR_STATE_DIR,
 * VIR_PID_DIR, VIR_DNSMASQ_STATE_DIR, VIR_RADVD_STATE_DIR
 * All the above will of the type VIR_TYPED_PARAM_STRING
 */
int virNetworkGetConfigFileName(virConnectPtr conn,
virTypedParameterPtr params,
int nparams,
unsigned int flags)


Nehal J. Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] RFC: Introduce API to return configuration/state paths of the network driver

2013-08-13 Thread Nehal J. Wani
On Wed, Aug 14, 2013 at 4:29 AM, Eric Blake ebl...@redhat.com wrote:

 On 08/13/2013 04:48 PM, Eric Blake wrote:

 virNetworkGetDHCPLeaseForMAC(virNetworkPtr network,
  unsigned char *macaddr,
 
  I personally think the public API should stick to stringized
  representations.  Yes, it's less friendly to machine code, but
  internally, our src/util/virmacaddr.h helps transfer between stringized
  and binary.  Furthermore, we already have other API that operates on
  stringized versions, but none that operates on raw (see
  virDomainSetInterfaceParameters).  Knowing what representation we are
  targetting impacts how this API will look.

 For comparison, look at the API for virDomainLookupByUUID (takes a raw
 uuid - fixed number of bytes, unsigned char* argument) vs.
 virDomainLookupByUUIDString (takes a stringized uuid, char* argument).
 If efficiency were a concern, then I'd propose that we have two API:

 virNetworkGetDHCPLeaseForMAC(virNetworkPtr network,
  unsigned char *macaddr, ...)

 virNetworkGetDHCPLeaseForMACString(virNetworkPtr network,
char *macaddr, ...)

 But I don't think efficiency is a concern, and rather than add a new API
 that has to have dual forms, I'd rather stick with the shorter name but
 using the stringized form of MAC.

 --
 Eric Blake   eblake redhat com+1-919-301-3266
 Libvirt virtualization library http://libvirt.org


I would like to see the API as:

/**
 * virNetworkGetDHCPLeases:
 * @network: pointer to network object
 * @macaddr: MAC Address of an interface
 * @leases: pointer to an array of structs which will hold the leases
 * @nleases: number of leases in output
 * @flags: extra flags, not used yet, so callers should always pass 0
 *
 * The API returns the leases of all interfaces by default, and if
 * @macaddr is specified,.only the lease of the interface which
 * matches the @macaddr is returned.
 *
 * Returns number of leases on success, -1 otherwise
 */
int virNetworkGetDHCPLeases(virNetworkPtr network,
const char *macaddr,
virNetworkDHCPLeasesPtr *leases,
int *nleases,
unsigned int flags);



Structs to be used:

/*In include/libvirt/libvirt.h.in */

struct _virNetworkDHCPLeases {
long long expirytime;
char *macaddr;
char *ipaddr;
char *hostname;
char *clientid;
};

/*In src/remote/remote_protocol.x*/

struct remote_network_dhcp_leases {
hyper expirytime;
remote_nonnull_string macaddr;
remote_nonnull_string ipaddr;
remote_nonnull_string hostname;
remote_nonnull_string clientid;
};

struct remote_network_get_dhcp_leases_args {
remote_nonnull_network net;
remote_string macaddr;
unsigned int flags;
};

struct remote_network_get_dhcp_leases_ret {
remote_network_dhcp_leases leases;
};


The following two blocks are required more than one, so should
we be introducing helper functions for them?

if ((VIR_STRDUP((*leases)[0].macaddr, leaseparams[1])  0) ||
(VIR_STRDUP((*leases)[0].ipaddr, leaseparams[2])  0) ||
(VIR_STRDUP((*leases)[0].hostname, leaseparams[3])  0) ||
(VIR_STRDUP((*leases)[0].clientid, leaseparams[4])  0))
goto cleanup;

for (i = 0; i  nleases; i++) {
 VIR_FREE(leases[i].macaddr);
 VIR_FREE(leases[i].ipaddr);
 VIR_FREE(leases[i].hostname);
 VIR_FREE(leases[i].clientid);
}


--
Nehal J. Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv3 3/5] domifaddr: Implement the API for qemu

2013-08-22 Thread Nehal J. Wani
, /* 1.1.2
 */
  .nodeGetMemoryStats = qemuNodeGetMemoryStats, /* 0.9.3 */
  .nodeGetCellsFreeMemory = qemuNodeGetCellsFreeMemory, /* 0.4.4 */
  .nodeGetFreeMemory = qemuNodeGetFreeMemory, /* 0.4.4 */
 diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
 index 4e27981..6b6c47f 100644
 --- a/tests/qemuagenttest.c
 +++ b/tests/qemuagenttest.c
 @@ -31,6 +31,8 @@

  #define VIR_FROM_THIS VIR_FROM_NONE

 +
 +
  static int
  testQemuAgentFSFreeze(const void *data)
  {
 @@ -271,6 +273,7 @@ cleanup:
  }


 +
  static int
  testQemuAgentShutdown(const void *data)
  {
 @@ -496,7 +499,7 @@ testQemuAgentArbitraryCommand(const void *data)
  goto cleanup;

  if (qemuAgentArbitraryCommand(qemuMonitorTestGetAgent(test),
 -  {\execute\:\ble\},
 + {\execute\:\ble\},
reply,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) 
 0)
  goto cleanup;
 @@ -576,6 +579,90 @@ cleanup:
  return ret;
  }

 +static const char testQemuAgentGetInterfacesResponse[] =
 +{\return\: 
 +[
 +   {\name\:\lo\,
 +\ip-addresses\:
 +  [
 + {\ip-address-type\:\ipv4\,
 +  \ip-address\:\127.0.0.1\,
 +  \prefix\:8
 + },
 + {\ip-address-type\:\ipv6\,
 +  \ip-address\:\::1\,
 +  \prefix\:128
 + }
 +  ],
 +\hardware-address\:\00:00:00:00:00:00\
 +   },
 +   {\name\:\eth0\,
 +\ip-addresses\:
 +  [
 + {\ip-address-type\:\ipv4\,
 +  \ip-address\:\192.168.102.142\,
 +  \prefix\:24
 + },
 + {\ip-address-type\:\ipv6\,
 +  \ip-address\:\fe80::5054:ff:fe89:ad35\,
 +  \prefix\:64
 + }
 +  ],
 +\hardware-address\:\52:54:00:89:ad:35\
 +   },
 +   {\name\:\eth1\,
 +\ip-addresses\:
 +  [
 + {\ip-address-type\:\ipv4\,
 +  \ip-address\:\192.168.103.83\,
 +  \prefix\:24
 + },
 + {\ip-address-type\:\ipv6\,
 +  \ip-address\:\fe80::5054:ff:fed3:39ee\,
 +  \prefix\:64
 + }
 +  ],
 +\hardware-address\:\52:54:00:d3:39:ee\
 +   }
 +]
 +};
 +
 +static int
 +testQemuAgentGetInterfaces(const void *data)
 +{
 +virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
 +qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
 +int ret = -1;
 +int ifaces_count = 0;
 +virDomainInterfacePtr *ifaces;
 +
 +if (!test)
 +return -1;
 +
 +if (qemuMonitorTestAddAgentSyncResponse(test)  0)
 +goto cleanup;
 +
 +if (qemuMonitorTestAddItem(test, guest-network-get-interfaces,
 +   testQemuAgentGetInterfacesResponse)  0)
 +goto cleanup;
 +
 +if ((ifaces_count =
 qemuAgentGetInterfaces(qemuMonitorTestGetAgent(test),
 +   ifaces))  0) {
 +goto cleanup;
 +}
 +
 +if (ifaces_count != 3) {
 +virReportError(VIR_ERR_INTERNAL_ERROR,
 +   expected 3 interfaces, got %d, ret);
 +goto cleanup;
 +}
 +
 +ret = 0;
 +
 +cleanup:
 +qemuMonitorTestFree(test);
 +return ret;
 +}

  static int
  mymain(void)
 @@ -605,6 +692,7 @@ mymain(void)
  DO_TEST(Shutdown);
  DO_TEST(CPU);
  DO_TEST(ArbitraryCommand);
 +DO_TEST(GetInterfaces);

  DO_TEST(Timeout); /* Timeout should always be called last */

 --
 1.7.11.7




-- 
Nehal J. Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv3 4/5] domifaddr: Add virsh support

2013-08-23 Thread Nehal J Wani
 be driver dependent, it can be
 +the name within guest OS or the name you would see in domain XML.
 +Moreover, the whole command may require a guest agent to be configured
 +for the queried domain under some drivers, notably qemu.
 +
  =item Bdomifstat Idomain Iinterface-device

  Get network interface stats for a running domain.
 --
 1.7.11.7

 --
 libvir-list mailing list
 libvir-list@redhat.com
 https://www.redhat.com/mailman/listinfo/libvir-list




 --
 Doug Goldstein


The leases method will be applied to this API when
virNetworkGetDHCPLeases() API is accepted, which is the next step after
this.
Refer: http://www.redhat.com/archives/libvir-list/2013-July/msg01603.html and
its followups.

The output from the virNetworkGetDHCPLeases will be something of this kind:

 virsh # net-dhcp-leases default

 Virtual Network   Expiry Time  MAC address  IP address
   Hostname ClientId
 

 default   16-08-2013 03:53:11  52:54:00:89:4e:97
 192.168.101.130   f18  *
 default   16-08-2013 03:45:20  52:54:00:fe:4c:4f
 192.168.101.197   **


--
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv3 4/5] domifaddr: Add virsh support

2013-08-24 Thread Nehal J Wani
On Sat, Aug 24, 2013 at 6:46 AM, Doug Goldstein car...@gentoo.org wrote:

 On Fri, Aug 23, 2013 at 10:45 AM, Nehal J Wani nehaljw.k...@gmail.com
wrote:




 On Fri, Aug 23, 2013 at 8:16 PM, Doug Goldstein car...@gentoo.org
wrote:
 
  On Thu, Aug 22, 2013 at 5:18 PM, nehaljwani nehaljw.k...@gmail.com
wrote:
 
  Use virDomainInterfacesAddresses in virsh
 
  tools/virsh-domain-monitor.c
 * Introduce new command : domifaddr
 
 virsh # domifaddr f18
 Name   MAC address  IP address
 ---
 lo 00:00:00:00:00:00127.0.0.1/8 ::1/128
 eth0   52:54:00:89:ad:35
  192.168.102.142/24fe80::5054:ff:fe89:ad35/64
 eth1   52:54:00:d3:39:ee
  192.168.103.183/24fe80::5054:ff:fed3:39ee/64
 eth2   52:54:00:fe:4c:4f
  192.168.101.197/24fe80::5054:ff:fefe:4c4f/64
 eth3   52:54:00:89:4e:97
  192.168.101.130/24fe80::5054:ff:fe89:4e97/64
 
 
  Not a review, but a question. How does this work with IP aliases? Will
it show all the aliases 1 per line or just show the primary address?
 
 
  tools/virsh.pod
 * Document new command
 
  ---
   tools/virsh-domain-monitor.c | 99

   tools/virsh.pod  | 10 +
   2 files changed, 109 insertions(+)
 
  diff --git a/tools/virsh-domain-monitor.c
b/tools/virsh-domain-monitor.c
  index b29b82a..91efa71 100644
  --- a/tools/virsh-domain-monitor.c
  +++ b/tools/virsh-domain-monitor.c
  @@ -1871,6 +1871,99 @@ cleanup:
   }
   #undef FILTER
 
  +/* domifaddr command
  + */
  +static const vshCmdInfo info_domifaddr[] = {
  +{help, N_(Get network interfaces' addresses for a running
domain)},
  +{desc, N_(Get network interfaces' addresses for a running
domain)},
  +{NULL, NULL}
  +};
  +
  +static const vshCmdOptDef opts_domifaddr[] = {
  +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or
uuid)},
  +{interface, VSH_OT_DATA, VSH_OFLAG_NONE, N_(network interface
name)},
  +{NULL, 0, 0, NULL}
  +};
  +
  +static bool
  +cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
  +{
  +virDomainPtr dom = NULL;
  +const char *interface = NULL;
  +virDomainInterfacePtr *ifaces = NULL;
  +size_t i, j;
  +int ifaces_count = 0;
  +unsigned int flags = 0;
  +bool ret = false;
  +
  +if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
  +return false;
  +
  +if (vshCommandOptString(cmd, interface, interface)  0) {
  +goto cleanup;
  +}
  +
  +if ((ifaces_count = virDomainInterfacesAddresses(dom, ifaces,
flags))  0) {
  +vshError(ctl, _(Failed to query for interfaces addresses));
  +goto cleanup;
  +}
  +
  +vshPrintExtra(ctl,  %-10s %-17s%s\n%s\n,
  +  _(Name), _(MAC address), _(IP address),
  +
 ---);
  +
  +for (i = 0; i  ifaces_count; i++) {
  +virDomainInterfacePtr iface = ifaces[i];
  +virBuffer buf = VIR_BUFFER_INITIALIZER;
  +const char *hwaddr = ;
  +const char *ip_addr_str = NULL;
  +
  +if (interface  STRNEQ(interface, iface-name)) {
  +virBufferFreeAndReset(buf);
  +continue;
  +}
  +
  +if (iface-hwaddr)
  +hwaddr = iface-hwaddr;
  +
  +for (j = 0; j  iface-naddrs; j++) {
  +if (j)
  +virBufferAddChar(buf, ' ');
  +virBufferAsprintf(buf, %s/%d,
  +  iface-addrs[j].addr,
  +  iface-addrs[j].prefix);
  +}
  +
  +if (virBufferError(buf)) {
  +virBufferFreeAndReset(buf);
  +virReportOOMError();
  +return ret;
  +}
  +
  +ip_addr_str = virBufferContentAndReset(buf);
  +
  +if (!ip_addr_str)
  +ip_addr_str = ;
  +
  +vshPrintExtra(ctl,  %-10s %-17s%s\n,
  + iface-name, hwaddr, ip_addr_str);
  +
  +virBufferFreeAndReset(buf);
  +}
  +
  +ret = true;
  +
  +cleanup:
  +for (i = 0; i  ifaces_count; i++) {
  +if (ifaces[i])
  +virDomainInterfaceFree(ifaces[i]);
  +}
  +VIR_FREE(ifaces);
  +
  +virDomainFree(dom);
  +return ret;
  +}
  +
   const vshCmdDef domMonitoringCmds[] = {
   {.name = domblkerror,
.handler = cmdDomBlkError,
  @@ -1944,5 +2037,11 @@ const vshCmdDef domMonitoringCmds[] = {
.info = info_list,
.flags = 0
   },
  +{.name = domifaddr,
  + .handler = cmdDomIfAddr,
  + .opts = opts_domifaddr,
  + .info = info_domifaddr,
  + .flags = 0
  +},
   {.name = NULL}
   };
  diff --git a/tools/virsh.pod b/tools/virsh.pod
  index 0ae5178..008ffea 100644
  --- a/tools/virsh.pod
  +++ b/tools/virsh.pod
  @@ -636,6 +636,16 @@ BExplanation of fields (fields appear in the
following order):
 flush_total_times - total

[libvirt] [PATCHv4 2/5] domifaddr: Implement the remote protocol

2013-08-24 Thread Nehal J Wani
Implement RPC calls for virDomainInterfacesAddresses

daemon/remote.c
   * Define remoteSerializeDomainInterfacePtr, 
remoteDispatchDomainInterfacesAddresses

src/remote/remote_driver.c
   * Define remoteDomainInterfacesAddresses

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_DOMAIN_INTERFACES_ADDRESSES
   * Define structs remote_domain_ip_addr, remote_domain_interface,
 remote_domain_interfaces_addresses_args, 
remote_domain_interfaces_addresses_ret

src/remote_protocol-structs
   * New structs added

---
 daemon/remote.c  | 127 +++
 src/remote/remote_driver.c   |  85 +
 src/remote/remote_protocol.x |  41 +-
 src/remote_protocol-structs  |  24 
 4 files changed, 276 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 03d5557..44d7ff2 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5025,7 +5025,134 @@ cleanup:
 return rv;
 }
 
+static int
+remoteSerializeDomainInterfacePtr(virDomainInterfacePtr *ifaces,
+  unsigned int ifaces_count,
+  remote_domain_interfaces_addresses_ret *ret)
+{
+size_t i, j;
+
+if (ifaces_count  REMOTE_DOMAIN_INTERFACE_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(Number of interfaces exceeds max limit!));
+return -1;
+}
+
+if (VIR_ALLOC_N(ret-ifaces.ifaces_val, ifaces_count)  0)
+return -1;
+
+ret-ifaces.ifaces_len = ifaces_count;
+
+for (i = 0; i  ifaces_count; i++) {
+virDomainInterfacePtr iface = ifaces[i];
+remote_domain_interface *iface_ret = (ret-ifaces.ifaces_val[i]);
 
+if ((VIR_STRDUP(iface_ret-name, iface-name))  0)
+goto cleanup;
+
+if (iface-hwaddr) {
+char **hwaddr_p = NULL;
+if (VIR_ALLOC(hwaddr_p)  0)
+goto cleanup;
+if (VIR_STRDUP(*hwaddr_p, iface-hwaddr)  0) {
+VIR_FREE(hwaddr_p);
+goto cleanup;
+}
+
+iface_ret-hwaddr = hwaddr_p;
+}
+
+if (iface-naddrs  REMOTE_DOMAIN_IP_ADDR_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(Number of IP addresses exceeds max limit!));
+goto cleanup;
+}
+
+if (VIR_ALLOC_N(iface_ret-addrs.addrs_val,
+iface-naddrs)  0)
+goto cleanup;
+
+iface_ret-addrs.addrs_len = iface-naddrs;
+
+for (j = 0; j  iface-naddrs; j++) {
+virDomainIPAddressPtr ip_addr = (iface-addrs[j]);
+remote_domain_ip_addr *ip_addr_ret =
+(iface_ret-addrs.addrs_val[j]);
+
+if (VIR_STRDUP(ip_addr_ret-addr, ip_addr-addr)  0)
+goto cleanup;
+
+ip_addr_ret-prefix = ip_addr-prefix;
+ip_addr_ret-type = ip_addr-type;
+}
+}
+
+return 0;
+
+cleanup:
+if (ret-ifaces.ifaces_val) {
+for (i = 0; i  ifaces_count; i++) {
+remote_domain_interface *iface_ret = (ret-ifaces.ifaces_val[i]);
+VIR_FREE(iface_ret-name);
+VIR_FREE(iface_ret-hwaddr);
+for (j = 0; j  iface_ret-addrs.addrs_len; j++) {
+remote_domain_ip_addr *ip_addr =
+(iface_ret-addrs.addrs_val[j]);
+VIR_FREE(ip_addr-addr);
+}
+VIR_FREE(iface_ret);
+}
+VIR_FREE(ret-ifaces.ifaces_val);
+}
+
+return -1;
+}
+
+static int
+remoteDispatchDomainInterfacesAddresses(
+virNetServerPtr server ATTRIBUTE_UNUSED,
+virNetServerClientPtr client,
+virNetMessagePtr msg ATTRIBUTE_UNUSED,
+virNetMessageErrorPtr rerr,
+remote_domain_interfaces_addresses_args *args,
+remote_domain_interfaces_addresses_ret *ret)
+{
+int rv = -1;
+virDomainPtr dom = NULL;
+virDomainInterfacePtr *ifaces = NULL;
+int ifaces_count = 0;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv-conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv-conn, args-dom)))
+goto cleanup;
+
+if ((ifaces_count = virDomainInterfacesAddresses(dom, ifaces, 
args-flags))  0)
+goto cleanup;
+
+if (remoteSerializeDomainInterfacePtr(ifaces, ifaces_count, ret)  0)
+goto cleanup;
+
+rv = 0;
+
+cleanup:
+if (rv  0)
+virNetMessageSaveError(rerr);
+if (dom)
+virDomainFree(dom);
+if (ifaces) {
+size_t i;
+for (i = 0; i  ifaces_count; i++)
+virDomainInterfaceFree(ifaces[i]);
+VIR_FREE(ifaces);
+}
+return rv;
+}
 
 /*- Helpers. -*/
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 71d0034..94eb63d 100644
--- 

[libvirt] [PATCHv4 0/5] Introduce API to query IP addresses for given domain

2013-08-24 Thread Nehal J Wani
This feature has been requested for a very long time. Since qemu guest
agent gives us reliable results, now the wait is over.

The RFC was first proposed by Michal Privoznik:
 http://www.mail-archive.com/libvir-list@redhat.com/msg51857.html
A patch was submitted, using structs:
 http://www.mail-archive.com/libvir-list@redhat.com/msg57141.html
Another patch was submitted, using XML:
 http://www.mail-archive.com/libvir-list@redhat.com/msg57829.html

Neither of the patches were accepted, probably due to lack of extensibility
and usability. Hence, we thought of using virTypedParameters for reporting
list of interfaces along with their MAC address and IP addresses. The RFC
can be found here:
 http://www.mail-archive.com/libvir-list@redhat.com/msg79793.html

The idea of extensibility was rejected and rendered out of scope of
libvirt. Hence, we were back to structs.

This API is called virDomainInterfacesAddresses which returns a dynamically
allocated array of virDomainInterface struct. The great disadvantage is
once this gets released, it's written in stone and we cannot change
or add an item into it.

The API supports two methods:

* Return information (list of all associated interfaces with MAC address
 and IP addresses) of all of the domain interfaces by default (if
 no interface name is provided)

* Return information for the specified interface (if an interface name
 is provided)

Nehal J Wani (5):
  domifaddr: Implement the public API
  domifaddr: Implement the remote protocol
  domifaddr: Implement the API for qemu
  domifaddr: Add virsh support
  domifaddr: Expose python binding

 daemon/remote.c | 127 +
 examples/python/Makefile.am |   2 +-
 examples/python/README  |   1 +
 examples/python/domipaddrs.py   |  50 +
 include/libvirt/libvirt.h.in|  33 +
 python/generator.py |   3 +
 python/libvirt-override-api.xml |   8 ++-
 python/libvirt-override.c   | 113 +
 src/driver.h|   6 ++
 src/libvirt.c   | 109 
 src/libvirt_public.syms |   6 ++
 src/qemu/qemu_agent.c   | 153 
 src/qemu/qemu_agent.h   |   3 +
 src/qemu/qemu_driver.c  |  55 +++
 src/remote/remote_driver.c  |  85 ++
 src/remote/remote_protocol.x|  41 ++-
 src/remote_protocol-structs |  24 +++
 tests/qemuagenttest.c   | 113 +
 tools/virsh-domain-monitor.c| 101 ++
 tools/virsh.pod |  10 +++
 20 files changed, 1040 insertions(+), 3 deletions(-)
 create mode 100755 examples/python/domipaddrs.py

-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv4 5/5] domifaddr: Expose python binding

2013-08-24 Thread Nehal J Wani
Expose virDomainInterfacesAddresses to python binding

examples/python/Makefile.am:
  * Add new file domipaddrs.py

examples/python/README:
  * Add documentation for the python example

python/libvirt-override-api.xml:
  * Add new symbol for virDomainInterfacesAddresses

python/libvirt-override.c:
  * Hand written python api

Example:
  $ ./run ./examples/python/domipaddrs.py qemu:///system f18
  Interface  MAC address  IPv4 AddressIPv6 Address
  eth3:1 52:54:00:fe:4c:4f192.168.101.198/24
  eth2:1 52:54:00:d3:39:ee192.168.103.185/24
  eth2:0 52:54:00:d3:39:ee192.168.103.184/24
  eth1:2 52:54:00:89:ad:35192.168.102.143/24
  lo 00:00:00:00:00:00127.0.0.1/8  ::1/128
  eth0:2 52:54:00:89:4e:97192.168.101.132/24
  eth0:1 52:54:00:89:4e:97192.168.101.133/24
  eth3   52:54:00:fe:4c:4f192.168.101.197/24  fe80::5054:ff:fefe:4c4f/64
  eth2   52:54:00:d3:39:ee192.168.103.183/24  fe80::5054:ff:fed3:39ee/64
  eth1   52:54:00:89:ad:35192.168.102.142/24  fe80::5054:ff:fe89:ad35/64
  eth0   52:54:00:89:4e:97192.168.101.130/24  fe80::5054:ff:fe89:4e97/64

---
 examples/python/Makefile.am |   2 +-
 examples/python/README  |   1 +
 examples/python/domipaddrs.py   |  49 +
 python/libvirt-override-api.xml |   8 ++-
 python/libvirt-override.c   | 113 
 5 files changed, 171 insertions(+), 2 deletions(-)
 create mode 100755 examples/python/domipaddrs.py

diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am
index 2cacfa1..d33ee17 100644
--- a/examples/python/Makefile.am
+++ b/examples/python/Makefile.am
@@ -17,4 +17,4 @@
 EXTRA_DIST=\
README  \
consolecallback.py  \
-   dominfo.py domrestore.py domsave.py domstart.py esxlist.py
+   dominfo.py domrestore.py domsave.py domstart.py esxlist.py domipaddrs.py
diff --git a/examples/python/README b/examples/python/README
index f4db76c..1285d52 100644
--- a/examples/python/README
+++ b/examples/python/README
@@ -10,6 +10,7 @@ domsave.py  - save all running domU's into a directory
 domrestore.py - restore domU's from their saved files in a directory
 esxlist.py  - list active domains of an VMware ESX host and print some info.
   also demonstrates how to use the libvirt.openAuth() method
+domipaddrs.py - print domain interfaces along with their MAC and IP addresses
 
 The XML files in this directory are examples of the XML format that libvirt
 expects, and will have to be adapted for your setup. They are only needed
diff --git a/examples/python/domipaddrs.py b/examples/python/domipaddrs.py
new file mode 100755
index 000..e71e8f6
--- /dev/null
+++ b/examples/python/domipaddrs.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# domipaddrds - print domain interfaces along with their MAC and IP addresses
+
+import libvirt
+import sys
+
+def usage():
+print Usage: %s [URI] DOMAIN % sys.argv[0]
+print Print domain interfaces along with their MAC and IP 
addresses
+
+uri = None
+name = None
+args = len(sys.argv)
+
+if args == 2:
+name = sys.argv[1]
+elif args == 3:
+uri = sys.argv[1]
+name = sys.argv[2]
+else:
+usage()
+sys.exit(2)
+
+conn = libvirt.openReadOnly(uri)
+if conn == None:
+print Unable to open connection to libvirt
+sys.exit(1)
+
+try:
+dom = conn.lookupByName(name)
+except libvirt.libvirtError:
+print Domain %s not found % name
+sys.exit(0)
+
+ifaces = dom.interfacesAddresses(0)
+if (ifaces == None):
+print Failed to get domain interfaces
+sys.exit(0)
+
+print  {0:10} {1:20} {2:15} {3}.format(Interface, MAC address, IPv4 
Address, IPv6 Address)
+
+for (name, val) in ifaces.iteritems():
+print  {0:10} {1:17}.format(name, val['hwaddr']),
+
+if (val['ip_addrs']  None):
+print   ,
+for addr in val['ip_addrs']:
+print {0}/{1} .format(addr['addr'], addr['prefix']),
+print
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 9a88215..f5c6e83 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -602,5 +602,11 @@
   arg name='conn' type='virConnectPtr' info='pointer to the hypervisor 
connection'/
   arg name='flags' type='int' info='unused, pass 0'/
 /function
-  /symbols
+function name='virDomainInterfacesAddresses' file='python'
+  inforeturns a dictionary of domain interfaces along with their MAC and 
IP addresses/info
+  arg name='dom' type='virDomainPtr' info='pointer to the domain'/
+  arg name='flags' type='unsigned int' info='extra flags; not used yet, 
so callers should always pass 0'/
+  return type='virDomainInterfacePtr' info=dictionary of domain 
interfaces along with their MAC and IP addresses/
+/function
+/symbols
 /api
diff --git 

[libvirt] [PATCHv4 1/5] domifaddr: Implement the public API

2013-08-24 Thread Nehal J Wani
Define a new API virDomainInterfacesAddresses, which returns
the address information of a running domain's interfaces(s).
If no interface name is specified, it returns the information
of all interfaces, otherwise it only returns the information
of the specificed interface. The address information includes
the MAC and IP addresses.

The API is going to provide multiple methods by flags, e.g.

  * Query guest agent
  * Parse lease file of dnsmasq
  * DHCP snooping

But at this stage, it will only work with guest agent, and flags
won't be supported.

include/libvirt/libvirt.h.in:
  * Define virDomainInterfacesAddresses, virDomainInterfaceFree
  * Define structs virDomainInterface, virDomainIPAddress

python/generator.py:
  * Skip the auto-generation for virDomainInterfacesAddresses
and virDomainInterfaceFree

src/driver.h:
  * Define domainInterfacesAddresses

src/libvirt.c:
  * Implement virDomainInterfacesAddresses
  * Implement virDomainInterfaceFree

src/libvirt_public.syms:
  * Export the new symbols

---
 include/libvirt/libvirt.h.in |  33 +
 python/generator.py  |   3 ++
 src/driver.h |   6 +++
 src/libvirt.c| 109 +++
 src/libvirt_public.syms  |   6 +++
 5 files changed, 157 insertions(+)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..deb1e1f 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2044,6 +2044,39 @@ int virDomainGetInterfaceParameters 
(virDomainPtr dom,
  virTypedParameterPtr 
params,
  int *nparams, 
unsigned int flags);
 
+typedef enum {
+VIR_IP_ADDR_TYPE_IPV4,
+VIR_IP_ADDR_TYPE_IPV6,
+
+#ifdef VIR_ENUM_SENTINELS
+VIR_IP_ADDR_TYPE_LAST
+#endif
+} virIPAddrType;
+
+
+typedef struct _virDomainInterfaceIPAddress virDomainIPAddress;
+typedef virDomainIPAddress *virDomainIPAddressPtr;
+struct _virDomainInterfaceIPAddress {
+int type;   /* virIPAddrType */
+char *addr; /* IP address */
+int prefix; /* IP address prefix */
+};
+
+typedef struct _virDomainInterface virDomainInterface;
+typedef virDomainInterface *virDomainInterfacePtr;
+struct _virDomainInterface {
+char *name; /* interface name */
+char *hwaddr;   /* hardware address */
+unsigned int naddrs;/* number of items in @addrs */
+virDomainIPAddressPtr addrs;/* array of IP addresses */
+};
+
+int virDomainInterfacesAddresses (virDomainPtr dom,
+  virDomainInterfacePtr **ifaces,
+  unsigned int flags);
+
+void virDomainInterfaceFree (virDomainInterfacePtr iface);
+
 /* Management of domain block devices */
 
 int virDomainBlockPeek (virDomainPtr dom,
diff --git a/python/generator.py b/python/generator.py
index fb321c6..f24561e 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -458,6 +458,7 @@ skip_impl = (
 'virNodeGetMemoryParameters',
 'virNodeSetMemoryParameters',
 'virNodeGetCPUMap',
+'virDomainInterfacesAddresses',
 'virDomainMigrate3',
 'virDomainMigrateToURI3',
 )
@@ -560,6 +561,8 @@ skip_function = (
 virTypedParamsGetString,
 virTypedParamsGetUInt,
 virTypedParamsGetULLong,
+
+virDomainInterfaceFree, # Only useful in C
 )
 
 lxc_skip_function = (
diff --git a/src/driver.h b/src/driver.h
index be64333..8b6182e 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -518,6 +518,11 @@ typedef int
   unsigned int flags);
 
 typedef int
+(*virDrvDomainInterfacesAddresses)(virDomainPtr dom,
+   virDomainInterfacePtr **ifaces,
+   unsigned int flags);
+
+typedef int
 (*virDrvDomainMemoryStats)(virDomainPtr domain,
struct _virDomainMemoryStat *stats,
unsigned int nr_stats,
@@ -1238,6 +1243,7 @@ struct _virDriver {
 virDrvDomainInterfaceStats domainInterfaceStats;
 virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
 virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
+virDrvDomainInterfacesAddressesdomainInterfacesAddresses;
 virDrvDomainMemoryStats domainMemoryStats;
 virDrvDomainBlockPeek domainBlockPeek;
 virDrvDomainMemoryPeek domainMemoryPeek;
diff --git a/src/libvirt.c b/src/libvirt.c
index 07a3fd5..05e3a03 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -8643,6 +8643,94 @@ error:
 return -1;
 }
 
+ /**
+ * virDomainInterfacesAddresses:
+ * @dom: domain object
+ * @ifaces: pointer to an array of pointers pointing interface objects
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Return a pointer to the allocated array of interfaces present in given
+ * 

[libvirt] [PATCHv4 3/5] domifaddr: Implement the API for qemu

2013-08-24 Thread Nehal J Wani
By querying the qemu guest agent with the QMP command
guest-network-get-interfaces and converting the received
JSON output to structured objects.

src/qemu/qemu_agent.h:
  * Define qemuAgentGetInterfaces

src/qemu/qemu_agent.c:
  * Implement qemuAgentGetInterface

src/qemu/qemu_driver.c:
  * New function qemuDomainInterfacesAddresses

src/remote_protocol-sructs:
  * Define new structs

tests/qemuagenttest.c:
  * Add new test: testQemuAgentGetInterfaces

---
 src/qemu/qemu_agent.c  | 153 +
 src/qemu/qemu_agent.h  |   3 +
 src/qemu/qemu_driver.c |  55 ++
 tests/qemuagenttest.c  | 113 
 4 files changed, 324 insertions(+)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 2cd0ccc..11f5467 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1319,6 +1319,159 @@ cleanup:
 return ret;
 }
 
+
+int
+qemuAgentGetInterfaces(qemuAgentPtr mon,
+   virDomainInterfacePtr **ifaces)
+{
+int ret = -1;
+size_t i, j;
+int size = -1;
+virJSONValuePtr cmd = NULL;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr ret_array = NULL;
+int ifaces_count = 0;
+virDomainInterfacePtr *ifaces_ret = NULL;
+
+if (!(cmd = qemuAgentMakeCommand(guest-network-get-interfaces, NULL)))
+   return -1;
+
+if (qemuAgentCommand(mon, cmd, reply, 
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK)  0 ||
+qemuAgentCheckError(cmd, reply)  0) {
+goto cleanup;
+}
+
+if (!(ret_array = virJSONValueObjectGet(reply, return))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+_(qemu agent didn't provide 'return' field));
+goto cleanup;
+}
+
+if ((size = virJSONValueArraySize(ret_array))  0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+_(qemu agent didn't return an array of interfaces));
+goto cleanup;
+}
+
+ifaces_count = (unsigned int) size;
+
+if (VIR_ALLOC_N(ifaces_ret, size)  0)
+goto cleanup;
+
+for (i = 0; i  size; i++) {
+virJSONValuePtr tmp_iface = virJSONValueArrayGet(ret_array, i);
+virJSONValuePtr ip_addr_arr = NULL;
+const char *name, *hwaddr;
+int ip_addr_arr_size;
+
+if (VIR_ALLOC(ifaces_ret[i])  0)
+goto cleanup;
+
+/* Shouldn't happen but doesn't hurt to check neither */
+if (!tmp_iface) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+_(something has went really wrong));
+goto error;
+}
+
+/* interface name is required to be presented */
+name = virJSONValueObjectGetString(tmp_iface, name);
+if (!name) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+_(qemu agent didn't provide 'name' field));
+goto error;
+}
+
+if (VIR_STRDUP(ifaces_ret[i]-name, name)  0)
+goto error;
+
+/* hwaddr might be omitted */
+hwaddr = virJSONValueObjectGetString(tmp_iface, hardware-address);
+if (hwaddr  VIR_STRDUP(ifaces_ret[i]-hwaddr, hwaddr)  0)
+goto error;
+
+/* as well as IP address which - moreover -
+ * can be presented multiple times */
+ip_addr_arr = virJSONValueObjectGet(tmp_iface, ip-addresses);
+if (!ip_addr_arr)
+continue;
+
+if ((ip_addr_arr_size = virJSONValueArraySize(ip_addr_arr))  0)
+/* Mmm, empty 'ip-address'? */
+continue;
+
+(*(ifaces_ret)[i]).naddrs = (unsigned int) ip_addr_arr_size;
+
+if (VIR_ALLOC_N((*(ifaces_ret)[i]).addrs, ip_addr_arr_size)  0)
+goto error;
+
+for (j = 0; j  ip_addr_arr_size; j++) {
+virJSONValuePtr ip_addr_obj = virJSONValueArrayGet(ip_addr_arr, j);
+virDomainIPAddressPtr ip_addr = ifaces_ret[i]-addrs[j];
+const char *type, *addr;
+
+/* Shouldn't happen but doesn't hurt to check neither */
+if (!ip_addr_obj) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+_(something has went really wrong));
+goto error;
+}
+
+type = virJSONValueObjectGetString(ip_addr_obj, ip-address-type);
+if (!type) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_(qemu agent didn't provide 'ip-address-type'
+   field for interface '%s'), name);
+goto error;
+} else if (STREQ(type, ipv4)) {
+ip_addr-type = VIR_IP_ADDR_TYPE_IPV4;
+} else if (STREQ(type, ipv6)) {
+ip_addr-type = VIR_IP_ADDR_TYPE_IPV6;
+} else {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_(unknown ip address type '%s'),
+   

[libvirt] [PATCHv4 4/5] domifaddr: Add virsh support

2013-08-24 Thread Nehal J Wani
Use virDomainInterfacesAddresses in virsh

tools/virsh-domain-monitor.c
   * Introduce new command : domifaddr
   virsh # domifaddr f18
   Name   MAC address  IPv4 addressIPv6 address
   
---
   lo 00:00:00:00:00:00127.0.0.1/8  ::1/128
   eth0   52:54:00:89:4e:97192.168.101.130/24  
fe80::5054:ff:fe89:4e97/64
   eth0:1 52:54:00:89:4e:97192.168.101.133/24
   eth0:2 52:54:00:89:4e:97192.168.101.132/24
   eth1   52:54:00:89:ad:35192.168.102.142/24  
fe80::5054:ff:fe89:ad35/64
   eth1:1 52:54:00:89:ad:35192.168.102.143/24
   eth2   52:54:00:d3:39:ee192.168.103.183/24  
fe80::5054:ff:fed3:39ee/64
   eth2:0 52:54:00:d3:39:ee192.168.103.184/24
   eth2:1 52:54:00:d3:39:ee192.168.103.185/24
   eth3   52:54:00:fe:4c:4f192.168.101.197/24  
fe80::5054:ff:fefe:4c4f/64
   eth3:1 52:54:00:fe:4c:4f192.168.101.198/24



tools/virsh.pod
   * Document new command

---
 tools/virsh-domain-monitor.c | 101 +++
 tools/virsh.pod  |  10 +
 2 files changed, 111 insertions(+)

diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index b29b82a..040b0e4 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1871,6 +1871,101 @@ cleanup:
 }
 #undef FILTER
 
+/* domifaddr command
+ */
+static const vshCmdInfo info_domifaddr[] = {
+{help, N_(Get network interfaces' addresses for a running domain)},
+{desc, N_(Get network interfaces' addresses for a running domain)},
+{NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domifaddr[] = {
+{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)},
+{interface, VSH_OT_DATA, VSH_OFLAG_NONE, N_(network interface name)},
+{NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom = NULL;
+const char *interface = NULL;
+virDomainInterfacePtr *ifaces = NULL;
+size_t i, j;
+int ifaces_count = 0;
+unsigned int flags = 0;
+bool ret = false;
+
+if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if (vshCommandOptString(cmd, interface, interface)  0) {
+goto cleanup;
+}
+
+if ((ifaces_count = virDomainInterfacesAddresses(dom, ifaces, flags))  
0) {
+vshError(ctl, _(Failed to query for interfaces addresses));
+goto cleanup;
+}
+
+vshPrintExtra(ctl,  %-10s %-20s %-15s %s\n%s%s\n, _(Name),
+  _(MAC address), _(IPv4 address), _(IPv6 address),
+  _(-),
+  _(--));
+
+for (i = 0; i  ifaces_count; i++) {
+virDomainInterfacePtr iface = ifaces[i];
+virBuffer buf = VIR_BUFFER_INITIALIZER;
+const char *hwaddr = ;
+const char *ip_addr_str = NULL;
+
+if (interface  STRNEQ(interface, iface-name)) {
+virBufferFreeAndReset(buf);
+continue;
+}
+
+if (iface-hwaddr)
+hwaddr = iface-hwaddr;
+
+for (j = 0; j  iface-naddrs; j++) {
+if (j)
+virBufferAsprintf(buf, %25s/%d,
+  iface-addrs[j].addr,
+  iface-addrs[j].prefix);
+else
+virBufferAsprintf(buf, %s/%d,
+  iface-addrs[j].addr,
+  iface-addrs[j].prefix);
+}
+
+if (virBufferError(buf)) {
+virBufferFreeAndReset(buf);
+virReportOOMError();
+return ret;
+}
+
+ip_addr_str = virBufferContentAndReset(buf);
+
+if (!ip_addr_str)
+ip_addr_str = ;
+
+vshPrintExtra(ctl,  %-10s %-17s%s\n,
+ iface-name, hwaddr, ip_addr_str);
+
+virBufferFreeAndReset(buf);
+}
+
+ret = true;
+
+cleanup:
+for (i = 0; i  ifaces_count; i++)
+virDomainInterfaceFree(ifaces[i]);
+VIR_FREE(ifaces);
+
+virDomainFree(dom);
+return ret;
+}
+
 const vshCmdDef domMonitoringCmds[] = {
 {.name = domblkerror,
  .handler = cmdDomBlkError,
@@ -1944,5 +2039,11 @@ const vshCmdDef domMonitoringCmds[] = {
  .info = info_list,
  .flags = 0
 },
+{.name = domifaddr,
+ .handler = cmdDomIfAddr,
+ .opts = opts_domifaddr,
+ .info = info_domifaddr,
+ .flags = 0
+},
 {.name = NULL}
 };
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0ae5178..008ffea 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -636,6 +636,16 @@ BExplanation of fields (fields appear in the following 
order):
   flush_total_times - total time flush operations took (ns)
 -- other fields provided by hypervisor --
 
+
+=item Bdomifaddr Idomain [Iinterface]
+

Re: [libvirt] [PATCHv4 1/5] domifaddr: Implement the public API

2013-08-27 Thread Nehal J Wani
On Tue, Aug 27, 2013 at 6:06 PM, Daniel P. Berrange berra...@redhat.com
wrote:

 On Sun, Aug 25, 2013 at 04:45:41AM +0530, Nehal J Wani wrote:
  diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
  index a47e33c..deb1e1f 100644
  --- a/include/libvirt/libvirt.h.in
  +++ b/include/libvirt/libvirt.h.in
  @@ -2044,6 +2044,39 @@ int
virDomainGetInterfaceParameters (virDomainPtr dom,
 
virTypedParameterPtr params,
int *nparams,
unsigned int flags);
 
  +typedef enum {
  +VIR_IP_ADDR_TYPE_IPV4,
  +VIR_IP_ADDR_TYPE_IPV6,
  +
  +#ifdef VIR_ENUM_SENTINELS
  +VIR_IP_ADDR_TYPE_LAST
  +#endif
  +} virIPAddrType;
  +
  +
  +typedef struct _virDomainInterfaceIPAddress virDomainIPAddress;
  +typedef virDomainIPAddress *virDomainIPAddressPtr;
  +struct _virDomainInterfaceIPAddress {
  +int type;   /* virIPAddrType */
  +char *addr; /* IP address */
  +int prefix; /* IP address prefix */
  +};

 s/int/unsigned int/ since there's no reason for prefix to ever
 be negative.

  +
  +typedef struct _virDomainInterface virDomainInterface;
  +typedef virDomainInterface *virDomainInterfacePtr;
  +struct _virDomainInterface {
  +char *name; /* interface name */
  +char *hwaddr;   /* hardware address */
  +unsigned int naddrs;/* number of items in @addrs */
  +virDomainIPAddressPtr addrs;/* array of IP addresses */
  +};
  +
  +int virDomainInterfacesAddresses (virDomainPtr dom,
  +  virDomainInterfacePtr **ifaces,
  +  unsigned int flags);

 Don't put a space between the function name  opening bracket.

 The double pluralization reads oddly to me. I'd suggest we
 just name this  'virDomainInterfaceAddresses'

 ie remove the 's' from Interfaces here, and in all similarly
 named functions in this series.


The double pluralization was chosen because there are multiple
IP Addresses per interface and there are multiple interfaces. If we
choose to use 'virDomainInterfaceAddresses', then it would look
as if this function will report all the IP Addresses related to a single
Interface only.

  +
  +void virDomainInterfaceFree (virDomainInterfacePtr iface);

 Likewise.

  diff --git a/src/driver.h b/src/driver.h
  index be64333..8b6182e 100644
  --- a/src/driver.h
  +++ b/src/driver.h
  @@ -518,6 +518,11 @@ typedef int
 unsigned int flags);
 
   typedef int
  +(*virDrvDomainInterfacesAddresses)(virDomainPtr dom,
  +   virDomainInterfacePtr **ifaces,
  +   unsigned int flags);
  +
  +typedef int
   (*virDrvDomainMemoryStats)(virDomainPtr domain,
  struct _virDomainMemoryStat *stats,
  unsigned int nr_stats,
  @@ -1238,6 +1243,7 @@ struct _virDriver {
   virDrvDomainInterfaceStats domainInterfaceStats;
   virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
   virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
  +virDrvDomainInterfacesAddressesdomainInterfacesAddresses;
   virDrvDomainMemoryStats domainMemoryStats;
   virDrvDomainBlockPeek domainBlockPeek;
   virDrvDomainMemoryPeek domainMemoryPeek;
  diff --git a/src/libvirt.c b/src/libvirt.c
  index 07a3fd5..05e3a03 100644
  --- a/src/libvirt.c
  +++ b/src/libvirt.c
  @@ -8643,6 +8643,94 @@ error:
   return -1;
   }
 
  + /**
  + * virDomainInterfacesAddresses:
  + * @dom: domain object
  + * @ifaces: pointer to an array of pointers pointing interface objects
  + * @flags: extra flags; not used yet, so callers should always pass 0
  + *
  + * Return a pointer to the allocated array of interfaces present in
given
  + * domain along with their IP and MAC addresses. Note that single
interface
  + * can have multiple or even 0 IP address.
  + *
  + * This API dynamically allocates the virDomainInterfacePtr struct
based
  + * on how many interfaces domain @dom has, usually there's 1:1
correlation.
  + * The count of the interfaces is returned as the return value.
  + *
  + * Note that for some hypervisors, a configured guest agent is needed
  + * for successful return from this API. Moreover, if guest agent is
  + * used then the interface name is the one seen by guest OS. To match
  + * such interface with the one from @dom XML use MAC address or IP
range.
  + *
  + * @ifaces-name is never NULL, @ifaces-hwaddr might be NULL.
  + *
  + * The caller *must* free @ifaces when no longer needed. Usual use
  + * case looks like this:
  + *
  + * virDomainInterfacePtr *ifaces = NULL;
  + * int ifaces_count = 0;
  + * size_t i, j;
  + * virDomainPtr dom = ... obtain a domain here ...;
  + *
  + * if ((ifaces_count = virDomainInterfacesAddresses(dom, ifaces, 0))
 0)
  + * goto cleanup;
  + *
  + * ... do something with returned values

Re: [libvirt] [PATCHv4 4/5] domifaddr: Add virsh support

2013-08-27 Thread Nehal J Wani
On Tue, Aug 27, 2013 at 6:20 PM, Daniel P. Berrange berra...@redhat.com
wrote:

 On Sun, Aug 25, 2013 at 04:45:44AM +0530, Nehal J Wani wrote:
  Use virDomainInterfacesAddresses in virsh
 
  tools/virsh-domain-monitor.c
 * Introduce new command : domifaddr
 virsh # domifaddr f18
 Name   MAC address  IPv4 addressIPv6 address
 
 ---
 lo 00:00:00:00:00:00127.0.0.1/8
 ::1/128
 eth0   52:54:00:89:4e:97192.168.101.130/24 
  fe80::5054:ff:fe89:4e97/64
 eth0:1 52:54:00:89:4e:97192.168.101.133/24
 eth0:2 52:54:00:89:4e:97192.168.101.132/24
 eth1   52:54:00:89:ad:35192.168.102.142/24 
  fe80::5054:ff:fe89:ad35/64
 eth1:1 52:54:00:89:ad:35192.168.102.143/24
 eth2   52:54:00:d3:39:ee192.168.103.183/24 
  fe80::5054:ff:fed3:39ee/64
 eth2:0 52:54:00:d3:39:ee192.168.103.184/24
 eth2:1 52:54:00:d3:39:ee192.168.103.185/24
 eth3   52:54:00:fe:4c:4f192.168.101.197/24 
  fe80::5054:ff:fefe:4c4f/64
 eth3:1 52:54:00:fe:4c:4f192.168.101.198/24

 This formatting of IP addrs is broken.

 We should not expose interface aliases 'eth0:1', 'eth0:2', etc. If QEMU
agent
 is returning such names, either we should fix the agent, or strip the :1
 suffixes in libvirt. The aliased names are an artifact of the legacy
linux IP
 config tools. The new 'ip' command does not use these - it just shows
'eth0'
 with multiple IPv4 and multiple IPv6 addresses, which is also how
libvirt/netcf
 report physical device names  config.

 Our display format must allow for NICs having arbitrarily many addresses
 of either type, so displaying IPv4/IPv6 side by side will not work.

 I think we need a display format like:

   virsh  domifaddr f18
 Name   MAC address  Protocol  Address

---
 lo 00:00:00:00:00:00ipv4  127.0.0.1/8
 -  -ipv6  ::1/128
 eth0   52:54:00:89:4e:97ipv4  192.168.101.130/24
 -  -ipv4  192.168.101.133/24
 -  -ipv4  192.168.101.132/24
 -  -ipv6  fe80::5054:ff:fe89:4e97/64
 eth1   52:54:00:89:ad:35ipv4  192.168.102.142/24
 -  -ipv4  192.168.102.143/24
 -  -ipv6  fe80::5054:ff:fe89:ad35/64


 With option to fully display all fields to make life easier for scripts:

   virsh domifaddr --full f18
 Name   MAC address  Protocol  Address

---
 lo 00:00:00:00:00:00ipv4  127.0.0.1/8
 lo 00:00:00:00:00:00ipv6  ::1/128
 eth0   52:54:00:89:4e:97ipv4  192.168.101.130/24
 eth0   52:54:00:89:4e:97ipv4  192.168.101.133/24
 eth0   52:54:00:89:4e:97ipv4  192.168.101.132/24
 eth0   52:54:00:89:4e:97ipv6  fe80::5054:ff:fe89:4e97/64
 eth1   52:54:00:89:ad:35ipv4  192.168.102.142/24
 eth1   52:54:00:89:ad:35ipv4  192.168.102.143/24
 eth1   52:54:00:89:ad:35ipv6  fe80::5054:ff:fe89:ad35/64


  +
  +for (i = 0; i  ifaces_count; i++) {
  +virDomainInterfacePtr iface = ifaces[i];
  +virBuffer buf = VIR_BUFFER_INITIALIZER;
  +const char *hwaddr = ;
  +const char *ip_addr_str = NULL;
  +
  +if (interface  STRNEQ(interface, iface-name)) {
  +virBufferFreeAndReset(buf);
  +continue;
  +}
  +
  +if (iface-hwaddr)
  +hwaddr = iface-hwaddr;
  +
  +for (j = 0; j  iface-naddrs; j++) {
  +if (j)
  +virBufferAsprintf(buf, %25s/%d,
  +  iface-addrs[j].addr,
  +  iface-addrs[j].prefix);
  +else
  +virBufferAsprintf(buf, %s/%d,
  +  iface-addrs[j].addr,
  +  iface-addrs[j].prefix);

 This logic is very broken not allowing for multiple addrs per device

  +}
  +
  +if (virBufferError(buf)) {
  +virBufferFreeAndReset(buf);
  +virReportOOMError();
  +return ret;
  +}
  +
  +ip_addr_str = virBufferContentAndReset(buf);
  +
  +if (!ip_addr_str)
  +ip_addr_str = ;
  +
  +vshPrintExtra(ctl,  %-10s %-17s%s\n,
  + iface-name, hwaddr, ip_addr_str);
  +
  +virBufferFreeAndReset(buf);
  +}
  +
  +ret = true;
  +
  +cleanup:
  +for (i = 0; i  ifaces_count; i++)
  +virDomainInterfaceFree(ifaces[i]);
  +VIR_FREE(ifaces

Re: [libvirt] [PATCHv4 4/5] domifaddr: Add virsh support

2013-08-27 Thread Nehal J Wani
  So, qemu-ga doesn't understand that there can't be more than one
  device with same MAC addr. So, I think we are left with the following
  options:

 Actually that's wrong. You *can* have 2 completely different physical
 NICs with the same MAC address.

  (i) Modify qemu-guest-agent to return addresses belonging to same
  MAC address grouped under one interface only.

 You would not want to group based on MAC address - you explicitly just
 want to normalize by stripping the legacy aliases suffixes.

Actually, the order in which the qemu-agent returns the value isn't always:

ethX
ethX:0
ethX:1
ethY
ethY:0
ethY:2

It can be:

ethX
ethY:2
ethX:0
ethY:0
ethX:1
ethY

which, after stripping, will just be left with:

ethX
ethY
ethX
ethY
ethX
ethY

whereas, we would want:

ethX
ethX
ethX
ethY
ethY
ethY

Hence, grouping either by the stripped down interface name or
by the MAC address will be required. So that all IP addresses
related to a single NIC are not distributed in the output.


  OR
  (ii) Let the reply be as it is now. Strip the :0, :1 from the
response
  of guest agent (Is this really necessary?) . We'll have to parse the
JSON
  multiple times and fill the virDomainInterface structs by grouping them
  according to the MAC addresses.

 I think we need to do (ii) regardless to cope with existing deployed
 QEMU agent versions.

 We should also recommend to QEMU developers to fix the agent to not expose
 these legacy device alias names.


 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:|




--
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 2/5] domifaddr: Implement the remote protocol

2013-08-27 Thread Nehal J Wani
 s/ip/IP/,


  + */
 +const REMOTE_DOMAIN_IP_ADDR_MAX = 16;


 hm, are these 2 limits too small? I don't believe one host could only have
 up to 32 interfaces.  Any evidence for you to descrease them in new series?

 Osier


Since there is no theoretical limit on the number of interfaces that a
physical
or virtual machine can have, I would suggest making
REMOTE_DOMAIN_INTERFACE_MAX = 2048
and
REMOTE_DOMAIN_IP_ADDR_MAX = 2048
Earlier there used to be limitation defined in /usr/include/li
nux/net_alias.h:
 #define NET_ALIAS_MAX_SLOT  256 but then the kernel developers thought
 that limits suck and removed them after kernel 2.0.
I have tested creating multiple ipv4 aliases on the same interface and was
able
to achieve the count of 1010 without any warnings/errors.

-- 
Nehal J Wani
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCHv5 1/5] domifaddr: Implement the public APIs

2013-09-01 Thread Nehal J Wani
Define a new API virDomainInterfaceAddresses, which returns
the address information of a running domain's interfaces(s).
If no interface name is specified, it returns the information
of all interfaces, otherwise it only returns the information
of the specificed interface. The address information includes
the MAC and IP addresses.

Define helper function virDomainInterfaceFree, which allows
the upper layer application to free the domain interface object
conveniently.

The API is going to provide multiple methods by flags, e.g.

  * Query guest agent
  * Parse lease file of dnsmasq
  * DHCP snooping

But at this stage, it will only work with guest agent, and flags
won't be supported.

include/libvirt/libvirt.h.in:
  * Define virDomainInterfaceAddresses, virDomainInterfaceFree
  * Define structs virDomainInterface, virDomainIPAddress

python/generator.py:
  * Skip the auto-generation for virDomainInterfaceAddresses
and virDomainInterfaceFree

src/driver.h:
  * Define domainInterfaceAddresses

src/libvirt.c:
  * Implement virDomainInterfaceAddresses
  * Implement virDomainInterfaceFree

src/libvirt_public.syms:
  * Export the new symbols

---
 include/libvirt/libvirt.h.in |  32 
 python/generator.py  |   3 ++
 src/driver.h |   6 +++
 src/libvirt.c| 115 +++
 src/libvirt_public.syms  |   6 +++
 5 files changed, 162 insertions(+)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..1a34d02 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2044,6 +2044,38 @@ int virDomainGetInterfaceParameters 
(virDomainPtr dom,
  virTypedParameterPtr 
params,
  int *nparams, 
unsigned int flags);
 
+typedef enum {
+VIR_IP_ADDR_TYPE_IPV4,
+VIR_IP_ADDR_TYPE_IPV6,
+
+#ifdef VIR_ENUM_SENTINELS
+VIR_IP_ADDR_TYPE_LAST
+#endif
+} virIPAddrType;
+
+typedef struct _virDomainInterfaceIPAddress virDomainIPAddress;
+typedef virDomainIPAddress *virDomainIPAddressPtr;
+struct _virDomainInterfaceIPAddress {
+int type;/* virIPAddrType */
+char *addr;  /* IP address */
+unsigned int prefix; /* IP address prefix */
+};
+
+typedef struct _virDomainInterface virDomainInterface;
+typedef virDomainInterface *virDomainInterfacePtr;
+struct _virDomainInterface {
+char *name; /* interface name */
+char *hwaddr;   /* hardware address */
+unsigned int naddrs;/* number of items in @addrs */
+virDomainIPAddressPtr addrs;/* array of IP addresses */
+};
+
+int virDomainInterfaceAddresses(virDomainPtr dom,
+virDomainInterfacePtr **ifaces,
+unsigned int flags);
+
+void virDomainInterfaceFree(virDomainInterfacePtr iface);
+
 /* Management of domain block devices */
 
 int virDomainBlockPeek (virDomainPtr dom,
diff --git a/python/generator.py b/python/generator.py
index fb321c6..50f779b 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -458,6 +458,7 @@ skip_impl = (
 'virNodeGetMemoryParameters',
 'virNodeSetMemoryParameters',
 'virNodeGetCPUMap',
+'virDomainInterfaceAddresses',
 'virDomainMigrate3',
 'virDomainMigrateToURI3',
 )
@@ -560,6 +561,8 @@ skip_function = (
 virTypedParamsGetString,
 virTypedParamsGetUInt,
 virTypedParamsGetULLong,
+
+virDomainInterfaceFree, # Only useful in C
 )
 
 lxc_skip_function = (
diff --git a/src/driver.h b/src/driver.h
index be64333..eb4927b 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -518,6 +518,11 @@ typedef int
   unsigned int flags);
 
 typedef int
+(*virDrvDomainInterfaceAddresses)(virDomainPtr dom,
+  virDomainInterfacePtr **ifaces,
+  unsigned int flags);
+
+typedef int
 (*virDrvDomainMemoryStats)(virDomainPtr domain,
struct _virDomainMemoryStat *stats,
unsigned int nr_stats,
@@ -1238,6 +1243,7 @@ struct _virDriver {
 virDrvDomainInterfaceStats domainInterfaceStats;
 virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
 virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
+virDrvDomainInterfaceAddressesdomainInterfaceAddresses;
 virDrvDomainMemoryStats domainMemoryStats;
 virDrvDomainBlockPeek domainBlockPeek;
 virDrvDomainMemoryPeek domainMemoryPeek;
diff --git a/src/libvirt.c b/src/libvirt.c
index 07a3fd5..82c117f 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -8643,6 +8643,96 @@ error:
 return -1;
 }
 
+ /**
+ * virDomainInterfaceAddresses:
+ * @dom: domain object
+ * @ifaces: pointer to an array of pointers pointing to interface objects
+ * @flags: 

[libvirt] [PATCHv5 0/5] Introduce API to query IP addresses for given domain

2013-09-01 Thread Nehal J Wani
This feature has been requested for a very long time. Since qemu guest
agent gives us reliable results, now the wait is over.

The RFC was first proposed by Michal Privoznik:
 http://www.redhat.com/archives/libvir-list/2012-February/msg00437.html
A patch was submitted, using structs:
 https://www.redhat.com/archives/libvir-list/2012-June/msg00220.html
Another patch was submitted, using XML:
 https://www.redhat.com/archives/libvir-list/2012-June/msg00904.html

Neither of the patches were accepted, probably due to lack of extensibility
and usability. Hence, we thought of using virTypedParameters for reporting
list of interfaces along with their MAC address and IP addresses. The RFC
can be found here:
 https://www.redhat.com/archives/libvir-list/2013-July/msg00084.html

The idea of extensibility was rejected and rendered out of scope of
libvirt. Hence, we were back to structs.

This API is called virDomainInterfaceAddresses which returns a dynamically
allocated array of virDomainInterface struct. The great disadvantage is
once this gets released, it's written in stone and we cannot change
or add an item into it.

The API supports two methods:

* Return information (list of all associated interfaces with MAC address
 and IP addresses) of all of the domain interfaces by default (if
 no interface name is provided)

* Return information for the specified interface (if an interface name
 is provided)

v5:
* s/virDomainInterfacesAddresses/virDomainInterfaceAddresses.
* Case for IP aliasing handled using virHashTable.
* New test cases added, involving multiple and 0 IP addresse(s)
  per interface.
* IP prefix changed from int to unsigned int.
* Changes to practice libvirt habits.

v4:
* Various style nits, indentation errors, memory leaks fixed.
* https://www.redhat.com/archives/libvir-list/2013-August/msg01265.html

v3:
* Upper bounds to number of interfaces and addresses per interface
  introduced.
* Change from array of structs to array of pointers
* ifaces_count moved from function argument to return value
* Changes in variable names
* Test cases added for qemuAgentGetInterfaces.
* https://www.redhat.com/archives/libvir-list/2013-August/msg01215.html

v2:
* Logical errors, memory leaks and few other errors fixed.
* https://www.redhat.com/archives/libvir-list/2013-August/msg00631.html

v1:
* http://www.redhat.com/archives/libvir-list/2013-July/msg01553.html

Nehal J Wani (5):
  domifaddr: Implement the public APIs
  domifaddr: Implement the remote protocol
  domifaddr: Implement the API for qemu
  domifaddr: Add virsh support
  domifaddr: Expose python binding

 daemon/remote.c | 131 +++
 examples/python/Makefile.am |   2 +-
 examples/python/README  |   1 +
 examples/python/domipaddrs.py   |  50 +++
 include/libvirt/libvirt.h.in|  32 +++
 python/generator.py |   3 +
 python/libvirt-override-api.xml |   8 +-
 python/libvirt-override.c   | 111 +++
 src/driver.h|   6 ++
 src/libvirt.c   | 115 
 src/libvirt_public.syms |   6 ++
 src/qemu/qemu_agent.c   | 193 
 src/qemu/qemu_agent.h   |   3 +
 src/qemu/qemu_driver.c  |  55 
 src/remote/remote_driver.c  |  99 +
 src/remote/remote_protocol.x|  40 -
 src/remote_protocol-structs |  24 +
 tests/qemuagenttest.c   | 149 +++
 tools/virsh-domain-monitor.c| 119 +
 tools/virsh.pod |  11 +++
 20 files changed, 1155 insertions(+), 3 deletions(-)
 create mode 100755 examples/python/domipaddrs.py

-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv5 2/5] domifaddr: Implement the remote protocol

2013-09-01 Thread Nehal J Wani
daemon/remote.c
   * Define remoteSerializeDomainInterface, 
remoteDispatchDomainInterfaceAddresses

src/remote/remote_driver.c
   * Define remoteDomainInterfaceAddresses

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES
   * Define structs remote_domain_ip_addr, remote_domain_interface,
 remote_domain_interfaces_addresse_args, 
remote_domain_interface_addresses_ret
   * Introduce upper bounds (to handle DDoS attacks):
 REMOTE_DOMAIN_INTERFACE_MAX = 2048
 REMOTE_DOMAIN_IP_ADDR_MAX = 2048
 Restrictions on the maximum number of aliases per interface were
 removed after kernel v2.0, and theoretically, at present, there
 are no upper limits on number of interfaces per virtual machine
 and on the number of IP addresses per interface.

src/remote_protocol-structs
   * New structs added

---
 daemon/remote.c  | 131 +++
 src/remote/remote_driver.c   |  99 
 src/remote/remote_protocol.x |  40 -
 src/remote_protocol-structs  |  24 
 4 files changed, 293 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 6ace7af..7091cab 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5144,7 +5144,138 @@ cleanup:
 return rv;
 }
 
+static int
+remoteSerializeDomainInterface(virDomainInterfacePtr *ifaces,
+   unsigned int ifaces_count,
+   remote_domain_interface_addresses_ret *ret)
+{
+size_t i, j;
+
+if (ifaces_count  REMOTE_DOMAIN_INTERFACE_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of interfaces, %d exceeds the max limit: %d),
+   ifaces_count, REMOTE_DOMAIN_INTERFACE_MAX);
+return -1;
+}
+
+if (VIR_ALLOC_N(ret-ifaces.ifaces_val, ifaces_count)  0)
+return -1;
+
+ret-ifaces.ifaces_len = ifaces_count;
+
+for (i = 0; i  ifaces_count; i++) {
+virDomainInterfacePtr iface = ifaces[i];
+remote_domain_interface *iface_ret = (ret-ifaces.ifaces_val[i]);
+
+if ((VIR_STRDUP(iface_ret-name, iface-name))  0)
+goto cleanup;
+
+if (iface-hwaddr) {
+char **hwaddr_p = NULL;
+if (VIR_ALLOC(hwaddr_p)  0)
+goto cleanup;
+if (VIR_STRDUP(*hwaddr_p, iface-hwaddr)  0) {
+VIR_FREE(hwaddr_p);
+goto cleanup;
+}
+
+iface_ret-hwaddr = hwaddr_p;
+}
+
+if (iface-naddrs  REMOTE_DOMAIN_IP_ADDR_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of interfaces, %d exceeds the max limit: 
%d),
+   iface-naddrs, REMOTE_DOMAIN_IP_ADDR_MAX);
+goto cleanup;
+}
+
+if (VIR_ALLOC_N(iface_ret-addrs.addrs_val,
+iface-naddrs)  0)
+goto cleanup;
+
+iface_ret-addrs.addrs_len = iface-naddrs;
+
+for (j = 0; j  iface-naddrs; j++) {
+virDomainIPAddressPtr ip_addr = (iface-addrs[j]);
+remote_domain_ip_addr *ip_addr_ret =
+(iface_ret-addrs.addrs_val[j]);
+
+if (VIR_STRDUP(ip_addr_ret-addr, ip_addr-addr)  0)
+goto cleanup;
+
+ip_addr_ret-prefix = ip_addr-prefix;
+ip_addr_ret-type = ip_addr-type;
+}
+}
+
+return 0;
+
+cleanup:
+if (ret-ifaces.ifaces_val) {
+for (i = 0; i  ifaces_count; i++) {
+remote_domain_interface *iface_ret = (ret-ifaces.ifaces_val[i]);
+VIR_FREE(iface_ret-name);
+VIR_FREE(iface_ret-hwaddr);
+for (j = 0; j  iface_ret-addrs.addrs_len; j++) {
+remote_domain_ip_addr *ip_addr =
+(iface_ret-addrs.addrs_val[j]);
+VIR_FREE(ip_addr-addr);
+}
+VIR_FREE(iface_ret);
+}
+VIR_FREE(ret-ifaces.ifaces_val);
+}
 
+return -1;
+}
+
+static int
+remoteDispatchDomainInterfaceAddresses(
+virNetServerPtr server ATTRIBUTE_UNUSED,
+virNetServerClientPtr client,
+virNetMessagePtr msg ATTRIBUTE_UNUSED,
+virNetMessageErrorPtr rerr,
+remote_domain_interface_addresses_args *args,
+remote_domain_interface_addresses_ret *ret)
+{
+size_t i;
+int rv = -1;
+virDomainPtr dom = NULL;
+virDomainInterfacePtr *ifaces = NULL;
+int ifaces_count = 0;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv-conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv-conn, args-dom)))
+goto cleanup;
+
+if ((ifaces_count = virDomainInterfaceAddresses(dom, ifaces, 
args-flags))  0)
+goto cleanup;
+
+if (remoteSerializeDomainInterface(ifaces, ifaces_count, 

[libvirt] [PATCHv5 4/5] domifaddr: Add virsh support

2013-09-01 Thread Nehal J Wani
Use virDomainInterfaceAddresses in virsh

tools/virsh-domain-monitor.c
   * Introduce new command : domifaddr
 Usage: domifaddr domain [interface] [full]

 Example output:
 virsh # domifaddr f18
 Name   MAC address  Protocol IP Address
 
---
 lo 00:00:00:00:00:00ipv4 127.0.0.1/8
 -  -ipv6 ::1/128
 eth0   52:54:00:2e:45:ceipv4 10.1.33.188/24
 -  -ipv6 2001:db8:0:f101::2/64
 -  -ipv6 fe80::5054:ff:fe2e:45ce/64
 eth1   52:54:00:b1:70:19ipv4 192.168.105.201/16
 -  -ipv4 192.168.201.195/16
 -  -ipv6 fe80::5054:ff:feb1:7019/64
 eth2   52:54:00:36:2a:e5

tools/virsh.pod
   * Document new command

---
 tools/virsh-domain-monitor.c | 119 +++
 tools/virsh.pod  |  11 
 2 files changed, 130 insertions(+)

diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index b29b82a..cd1df7a 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1871,6 +1871,119 @@ cleanup:
 }
 #undef FILTER
 
+/* domifaddr command
+ */
+static const vshCmdInfo info_domifaddr[] = {
+{help, N_(Get network interfaces' addresses for a running domain)},
+{desc, N_(Get network interfaces' addresses for a running domain)},
+{NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domifaddr[] = {
+{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)},
+{interface, VSH_OT_DATA, VSH_OFLAG_NONE, N_(network interface name)},
+{full, VSH_OT_BOOL, VSH_OFLAG_NONE, N_(display full fields)},
+{NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom = NULL;
+const char *interface = NULL;
+virDomainInterfacePtr *ifaces = NULL;
+size_t i, j;
+int ifaces_count = 0;
+unsigned int flags = 0;
+bool ret = false;
+bool optFull = vshCommandOptBool(cmd, full);
+
+if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if (vshCommandOptString(cmd, interface, interface)  0) {
+goto cleanup;
+}
+
+if ((ifaces_count = virDomainInterfaceAddresses(dom, ifaces, flags))  0) 
{
+vshError(ctl, _(Failed to query for interfaces addresses));
+goto cleanup;
+}
+
+vshPrintExtra(ctl,  %-10s %-20s %-8s %s\n%s%s\n, _(Name),
+  _(MAC address), _(Protocol), _(Address),
+  _(-),
+  _(--));
+
+for (i = 0; i  ifaces_count; i++) {
+virDomainInterfacePtr iface = ifaces[i];
+const char *hwaddr = ;
+const char *ip_addr_str = NULL;
+const char *type = NULL;
+
+if (interface  STRNEQ(interface, iface-name))
+continue;
+
+if (iface-hwaddr)
+hwaddr = iface-hwaddr;
+
+/* When the interface has no IP address */
+if (!iface-naddrs) {
+vshPrintExtra(ctl,  %-10s %-17s\n,
+  iface-name, hwaddr);
+}
+
+for (j = 0; j  iface-naddrs; j++) {
+virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+switch (iface-addrs[j].type) {
+case VIR_IP_ADDR_TYPE_IPV4:
+type = ipv4;
+break;
+case VIR_IP_ADDR_TYPE_IPV6:
+type = ipv6;
+break;
+}
+
+virBufferAsprintf(buf, %-12s %s/%d,
+  type, iface-addrs[j].addr,
+  iface-addrs[j].prefix);
+
+if (virBufferError(buf)) {
+virBufferFreeAndReset(buf);
+virReportOOMError();
+return ret;
+}
+
+ip_addr_str = virBufferContentAndReset(buf);
+
+if (!ip_addr_str)
+ip_addr_str = ;
+
+/* Don't repeat interface name */
+if (optFull || !j)
+vshPrintExtra(ctl,  %-10s %-17s%s\n,
+  iface-name, hwaddr, ip_addr_str);
+else
+vshPrintExtra(ctl,  %-10s %-17s%s\n,
+  -,-,ip_addr_str);
+
+virBufferFreeAndReset(buf);
+}
+}
+
+ret = true;
+
+cleanup:
+if (ifaces)
+for (i = 0; i  ifaces_count; i++)
+virDomainInterfaceFree(ifaces[i]);
+VIR_FREE(ifaces);
+
+virDomainFree(dom);
+return ret;
+}
+
 const vshCmdDef domMonitoringCmds[] = {
 {.name = domblkerror,
  .handler = cmdDomBlkError,
@@ -1944,5 +2057,11 @@ const vshCmdDef domMonitoringCmds[] = {
  .info = info_list,
  .flags = 0
 },

[libvirt] [PATCHv5 5/5] domifaddr: Expose python binding

2013-09-01 Thread Nehal J Wani
Expose virDomainInterfaceAddresses to python binding

examples/python/Makefile.am:
  * Add new file domipaddrs.py

examples/python/README:
  * Add documentation for the python example

python/libvirt-override-api.xml:
  * Add new symbol for virDomainInterfaceAddresses

python/libvirt-override.c:
  * Hand written python api

Example:
  $ ./run python ./examples/python/domipaddrs.py f18
  Interface  MAC address  Protocol Address
  lo 00:00:00:00:00:00ipv4 127.0.0.1/8
  lo 00:00:00:00:00:00ipv6 ::1/128
  eth2   52:54:00:36:2a:e5
  eth1   52:54:00:b1:70:19ipv4 192.168.105.201/16
  eth1   52:54:00:b1:70:19ipv4 192.168.201.195/16
  eth1   52:54:00:b1:70:19ipv6 fe80::5054:ff:feb1:7019/64
  eth0   52:54:00:2e:45:ceipv4 10.1.33.188/24
  eth0   52:54:00:2e:45:ceipv6 2001:db8:0:f101::2/64
  eth0   52:54:00:2e:45:ceipv6 fe80::5054:ff:fe2e:45ce/64

---
 examples/python/Makefile.am |   2 +-
 examples/python/README  |   1 +
 examples/python/domipaddrs.py   |  50 ++
 python/libvirt-override-api.xml |   8 ++-
 python/libvirt-override.c   | 111 
 5 files changed, 170 insertions(+), 2 deletions(-)
 create mode 100755 examples/python/domipaddrs.py

diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am
index 2cacfa1..d33ee17 100644
--- a/examples/python/Makefile.am
+++ b/examples/python/Makefile.am
@@ -17,4 +17,4 @@
 EXTRA_DIST=\
README  \
consolecallback.py  \
-   dominfo.py domrestore.py domsave.py domstart.py esxlist.py
+   dominfo.py domrestore.py domsave.py domstart.py esxlist.py domipaddrs.py
diff --git a/examples/python/README b/examples/python/README
index f4db76c..1285d52 100644
--- a/examples/python/README
+++ b/examples/python/README
@@ -10,6 +10,7 @@ domsave.py  - save all running domU's into a directory
 domrestore.py - restore domU's from their saved files in a directory
 esxlist.py  - list active domains of an VMware ESX host and print some info.
   also demonstrates how to use the libvirt.openAuth() method
+domipaddrs.py - print domain interfaces along with their MAC and IP addresses
 
 The XML files in this directory are examples of the XML format that libvirt
 expects, and will have to be adapted for your setup. They are only needed
diff --git a/examples/python/domipaddrs.py b/examples/python/domipaddrs.py
new file mode 100755
index 000..679e0bf
--- /dev/null
+++ b/examples/python/domipaddrs.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# domipaddrds - print domain interfaces along with their MAC and IP addresses
+
+import libvirt
+import sys
+
+def usage():
+print Usage: %s [URI] DOMAIN % sys.argv[0]
+print Print domain interfaces along with their MAC and IP 
addresses
+
+uri = None
+name = None
+args = len(sys.argv)
+
+if args == 2:
+name = sys.argv[1]
+elif args == 3:
+uri = sys.argv[1]
+name = sys.argv[2]
+else:
+usage()
+sys.exit(2)
+
+conn = libvirt.openReadOnly(uri)
+if conn == None:
+print Unable to open connection to libvirt
+sys.exit(1)
+
+try:
+dom = conn.lookupByName(name)
+except libvirt.libvirtError:
+print Domain %s not found % name
+sys.exit(0)
+
+ifaces = dom.interfaceAddresses(0)
+if (ifaces == None):
+print Failed to get domain interfaces
+sys.exit(0)
+
+print  {0:10} {1:20} {2:12} {3}.format(Interface, MAC address, 
Protocol, Address)
+
+for (name, val) in ifaces.iteritems():
+if val['ip_addrs']:
+for addr in val['ip_addrs']:
+   print  {0:10} {1:19}.format(name, val['hwaddr']),
+   print  {0:12} {1}/{2} .format(addr['type'], addr['addr'], 
addr['prefix']),
+   print
+else:
+print  {0:10} {1:19}.format(name, val['hwaddr']),
+print
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 9a88215..60491de 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -602,5 +602,11 @@
   arg name='conn' type='virConnectPtr' info='pointer to the hypervisor 
connection'/
   arg name='flags' type='int' info='unused, pass 0'/
 /function
-  /symbols
+function name='virDomainInterfaceAddresses' file='python'
+  inforeturns a dictionary of domain interfaces along with their MAC and 
IP addresses/info
+  arg name='dom' type='virDomainPtr' info='pointer to the domain'/
+  arg name='flags' type='unsigned int' info='extra flags; not used yet, 
so callers should always pass 0'/
+  return type='virDomainInterfacePtr' info=dictionary of domain 
interfaces along with their MAC and IP addresses/
+/function
+/symbols
 /api
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index d16b9a2..67e0cb8 100644

[libvirt] [PATCHv5 3/5] domifaddr: Implement the API for qemu

2013-09-01 Thread Nehal J Wani
By querying the qemu guest agent with the QMP command
guest-network-get-interfaces and converting the received JSON
output to structured objects.

Although ifconfig is deprecated, IP aliases created by ifconfig
are supported by this API. The legacy syntax of an IP alias is:
ifname:alias-name. Since we want all aliases to be clubbed
under parent interface, simply stripping :alias-name suffices.
Note that IP aliases formed by ip aren't visible to ifconfig,
and aliases created by ip do not have any specific name. But
we are lucky, as qemuga detects aliases created by both.

src/qemu/qemu_agent.h:
  * Define qemuAgentGetInterfaces

src/qemu/qemu_agent.c:
  * Implement qemuAgentGetInterface

src/qemu/qemu_driver.c:
  * New function qemuDomainInterfaceAddresses

src/remote_protocol-sructs:
  * Define new structs

tests/qemuagenttest.c:
  * Add new test: testQemuAgentGetInterfaces
Test cases for IP aliases, 0 or multiple ipv4/ipv6 address(es)

---
 src/qemu/qemu_agent.c  | 193 +
 src/qemu/qemu_agent.h  |   3 +
 src/qemu/qemu_driver.c |  55 ++
 tests/qemuagenttest.c  | 149 ++
 4 files changed, 400 insertions(+)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 2cd0ccc..009ed77 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1320,6 +1320,199 @@ cleanup:
 }
 
 /*
+ * qemuAgentGetInterfaces:
+ * @mon: Agent
+ * @ifaces: pointer to an array of pointers pointing to interface objects
+ *
+ * Issue guest-network-get-interfaces to guest agent, which returns the
+ * list of a interfaces of a running domain along with their IP and MAC
+ * addresses.
+ *
+ * Returns: number of interfaces on success, -1 on error.
+ */
+int
+qemuAgentGetInterfaces(qemuAgentPtr mon,
+   virDomainInterfacePtr **ifaces)
+{
+int ret = -1;
+size_t i, j;
+int size = -1;
+virJSONValuePtr cmd = NULL;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr ret_array = NULL;
+size_t ifaces_count = 0;
+size_t addrs_count = 0;
+virDomainInterfacePtr *ifaces_ret = NULL;
+virHashTablePtr ifaces_store = NULL;
+
+/* Initially the bag of ifaces is empty */
+if (!(ifaces_store = virHashCreate(ifaces_count, NULL)))
+return -1;
+
+if (!(cmd = qemuAgentMakeCommand(guest-network-get-interfaces, NULL)))
+   return -1;
+
+if (qemuAgentCommand(mon, cmd, reply, 
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK)  0 ||
+qemuAgentCheckError(cmd, reply)  0) {
+goto cleanup;
+}
+
+if (!(ret_array = virJSONValueObjectGet(reply, return))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(qemu agent didn't provide 'return' field));
+goto cleanup;
+}
+
+if ((size = virJSONValueArraySize(ret_array))  0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(qemu agent didn't return an array of interfaces));
+goto cleanup;
+}
+
+for (i = 0; i  size; i++) {
+virJSONValuePtr tmp_iface = virJSONValueArrayGet(ret_array, i);
+virJSONValuePtr ip_addr_arr = NULL;
+const char *hwaddr, *ifname_s, *name = NULL;
+char **ifname = NULL;
+int ip_addr_arr_size;
+virDomainInterfacePtr iface = NULL;
+
+/* Shouldn't happen but doesn't hurt to check neither */
+if (!tmp_iface) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(something has went really wrong));
+goto error;
+}
+
+/* interface name is required to be presented */
+name = virJSONValueObjectGetString(tmp_iface, name);
+if (!name) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(qemu agent didn't provide 'name' field));
+goto error;
+}
+
+/* Handle aliases of type ifname:alias-name */
+ifname = virStringSplit(name, :, 2);
+ifname_s = ifname[0];
+
+iface = virHashLookup(ifaces_store, ifname_s);
+
+/* If the storage bag doesn't contain this iface, add it */
+if (!iface) {
+if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1)  0)
+goto cleanup;
+
+if (VIR_ALLOC(ifaces_ret[ifaces_count - 1])  0)
+goto cleanup;
+
+if (virHashAddEntry(ifaces_store, ifname_s,
+ifaces_ret[ifaces_count - 1])  0)
+goto cleanup;
+
+iface = ifaces_ret[ifaces_count - 1];
+iface-naddrs = 0;
+
+if (VIR_STRDUP(iface-name, ifname_s)  0)
+goto error;
+
+/* hwaddr might be omitted */
+hwaddr = virJSONValueObjectGetString(tmp_iface, 
hardware-address);
+if (hwaddr  VIR_STRDUP(iface-hwaddr, hwaddr)  0)
+goto error;
+}
+
+/* Has to be freed for each interface. */
+

Re: [libvirt] [PATCHv5 1/5] domifaddr: Implement the public APIs

2013-09-02 Thread Nehal J Wani
On Sun, Sep 1, 2013 at 7:13 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:
 Define a new API virDomainInterfaceAddresses, which returns
 the address information of a running domain's interfaces(s).
 If no interface name is specified, it returns the information
 of all interfaces, otherwise it only returns the information
 of the specificed interface. The address information includes
 the MAC and IP addresses.

 Define helper function virDomainInterfaceFree, which allows
 the upper layer application to free the domain interface object
 conveniently.

 The API is going to provide multiple methods by flags, e.g.

   * Query guest agent
   * Parse lease file of dnsmasq
   * DHCP snooping

 But at this stage, it will only work with guest agent, and flags
 won't be supported.

 include/libvirt/libvirt.h.in:
   * Define virDomainInterfaceAddresses, virDomainInterfaceFree
   * Define structs virDomainInterface, virDomainIPAddress

 python/generator.py:
   * Skip the auto-generation for virDomainInterfaceAddresses
 and virDomainInterfaceFree

 src/driver.h:
   * Define domainInterfaceAddresses

 src/libvirt.c:
   * Implement virDomainInterfaceAddresses
   * Implement virDomainInterfaceFree

 src/libvirt_public.syms:
   * Export the new symbols

 ---
  include/libvirt/libvirt.h.in |  32 
  python/generator.py  |   3 ++
  src/driver.h |   6 +++
  src/libvirt.c| 115 
 +++
  src/libvirt_public.syms  |   6 +++
  5 files changed, 162 insertions(+)

 diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
 index a47e33c..1a34d02 100644
 --- a/include/libvirt/libvirt.h.in
 +++ b/include/libvirt/libvirt.h.in
 @@ -2044,6 +2044,38 @@ int 
 virDomainGetInterfaceParameters (virDomainPtr dom,
   
 virTypedParameterPtr params,
   int *nparams, 
 unsigned int flags);

 +typedef enum {
 +VIR_IP_ADDR_TYPE_IPV4,
 +VIR_IP_ADDR_TYPE_IPV6,
 +
 +#ifdef VIR_ENUM_SENTINELS
 +VIR_IP_ADDR_TYPE_LAST
 +#endif
 +} virIPAddrType;
 +
 +typedef struct _virDomainInterfaceIPAddress virDomainIPAddress;
 +typedef virDomainIPAddress *virDomainIPAddressPtr;
 +struct _virDomainInterfaceIPAddress {
 +int type;/* virIPAddrType */
 +char *addr;  /* IP address */
 +unsigned int prefix; /* IP address prefix */
 +};
 +
 +typedef struct _virDomainInterface virDomainInterface;
 +typedef virDomainInterface *virDomainInterfacePtr;
 +struct _virDomainInterface {
 +char *name; /* interface name */
 +char *hwaddr;   /* hardware address */
 +unsigned int naddrs;/* number of items in @addrs */
 +virDomainIPAddressPtr addrs;/* array of IP addresses */
 +};
 +
 +int virDomainInterfaceAddresses(virDomainPtr dom,
 +virDomainInterfacePtr **ifaces,
 +unsigned int flags);
 +
 +void virDomainInterfaceFree(virDomainInterfacePtr iface);
 +
  /* Management of domain block devices */

  int virDomainBlockPeek (virDomainPtr dom,
 diff --git a/python/generator.py b/python/generator.py
 index fb321c6..50f779b 100755
 --- a/python/generator.py
 +++ b/python/generator.py
 @@ -458,6 +458,7 @@ skip_impl = (
  'virNodeGetMemoryParameters',
  'virNodeSetMemoryParameters',
  'virNodeGetCPUMap',
 +'virDomainInterfaceAddresses',
  'virDomainMigrate3',
  'virDomainMigrateToURI3',
  )
 @@ -560,6 +561,8 @@ skip_function = (
  virTypedParamsGetString,
  virTypedParamsGetUInt,
  virTypedParamsGetULLong,
 +
 +virDomainInterfaceFree, # Only useful in C
  )

  lxc_skip_function = (
 diff --git a/src/driver.h b/src/driver.h
 index be64333..eb4927b 100644
 --- a/src/driver.h
 +++ b/src/driver.h
 @@ -518,6 +518,11 @@ typedef int
unsigned int flags);

  typedef int
 +(*virDrvDomainInterfaceAddresses)(virDomainPtr dom,
 +  virDomainInterfacePtr **ifaces,
 +  unsigned int flags);
 +
 +typedef int
  (*virDrvDomainMemoryStats)(virDomainPtr domain,
 struct _virDomainMemoryStat *stats,
 unsigned int nr_stats,
 @@ -1238,6 +1243,7 @@ struct _virDriver {
  virDrvDomainInterfaceStats domainInterfaceStats;
  virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
  virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
 +virDrvDomainInterfaceAddressesdomainInterfaceAddresses;
  virDrvDomainMemoryStats domainMemoryStats;
  virDrvDomainBlockPeek domainBlockPeek;
  virDrvDomainMemoryPeek domainMemoryPeek;
 diff --git a/src/libvirt.c b/src/libvirt.c
 index 07a3fd5..82c117f 100644
 --- a/src/libvirt.c
 +++ b/src/libvirt.c

Re: [libvirt] [PATCHv5 5/5] domifaddr: Expose python binding

2013-09-02 Thread Nehal J Wani
On Sun, Sep 1, 2013 at 7:13 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:
 Expose virDomainInterfaceAddresses to python binding

 examples/python/Makefile.am:
   * Add new file domipaddrs.py

 examples/python/README:
   * Add documentation for the python example

 python/libvirt-override-api.xml:
   * Add new symbol for virDomainInterfaceAddresses

 python/libvirt-override.c:
   * Hand written python api

 Example:
   $ ./run python ./examples/python/domipaddrs.py f18
   Interface  MAC address  Protocol Address
   lo 00:00:00:00:00:00ipv4 127.0.0.1/8
   lo 00:00:00:00:00:00ipv6 ::1/128
   eth2   52:54:00:36:2a:e5
   eth1   52:54:00:b1:70:19ipv4 192.168.105.201/16
   eth1   52:54:00:b1:70:19ipv4 192.168.201.195/16
   eth1   52:54:00:b1:70:19ipv6 fe80::5054:ff:feb1:7019/64
   eth0   52:54:00:2e:45:ceipv4 10.1.33.188/24
   eth0   52:54:00:2e:45:ceipv6 2001:db8:0:f101::2/64
   eth0   52:54:00:2e:45:ceipv6 fe80::5054:ff:fe2e:45ce/64

 ---
  examples/python/Makefile.am |   2 +-
  examples/python/README  |   1 +
  examples/python/domipaddrs.py   |  50 ++
  python/libvirt-override-api.xml |   8 ++-
  python/libvirt-override.c   | 111 
 
  5 files changed, 170 insertions(+), 2 deletions(-)
  create mode 100755 examples/python/domipaddrs.py

 diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am
 index 2cacfa1..d33ee17 100644
 --- a/examples/python/Makefile.am
 +++ b/examples/python/Makefile.am
 @@ -17,4 +17,4 @@
  EXTRA_DIST=\
 README  \
 consolecallback.py  \
 -   dominfo.py domrestore.py domsave.py domstart.py esxlist.py
 +   dominfo.py domrestore.py domsave.py domstart.py esxlist.py 
 domipaddrs.py
 diff --git a/examples/python/README b/examples/python/README
 index f4db76c..1285d52 100644
 --- a/examples/python/README
 +++ b/examples/python/README
 @@ -10,6 +10,7 @@ domsave.py  - save all running domU's into a directory
  domrestore.py - restore domU's from their saved files in a directory
  esxlist.py  - list active domains of an VMware ESX host and print some info.
also demonstrates how to use the libvirt.openAuth() method
 +domipaddrs.py - print domain interfaces along with their MAC and IP addresses

  The XML files in this directory are examples of the XML format that libvirt
  expects, and will have to be adapted for your setup. They are only needed
 diff --git a/examples/python/domipaddrs.py b/examples/python/domipaddrs.py
 new file mode 100755
 index 000..679e0bf
 --- /dev/null
 +++ b/examples/python/domipaddrs.py
 @@ -0,0 +1,50 @@
 +#!/usr/bin/env python
 +# domipaddrds - print domain interfaces along with their MAC and IP addresses
 +
 +import libvirt
 +import sys
 +
 +def usage():
 +print Usage: %s [URI] DOMAIN % sys.argv[0]
 +print Print domain interfaces along with their MAC and IP 
 addresses
 +
 +uri = None
 +name = None
 +args = len(sys.argv)
 +
 +if args == 2:
 +name = sys.argv[1]
 +elif args == 3:
 +uri = sys.argv[1]
 +name = sys.argv[2]
 +else:
 +usage()
 +sys.exit(2)
 +
 +conn = libvirt.openReadOnly(uri)
 +if conn == None:
 +print Unable to open connection to libvirt
 +sys.exit(1)
 +
 +try:
 +dom = conn.lookupByName(name)
 +except libvirt.libvirtError:
 +print Domain %s not found % name
 +sys.exit(0)
 +
 +ifaces = dom.interfaceAddresses(0)
 +if (ifaces == None):
 +print Failed to get domain interfaces
 +sys.exit(0)
 +
 +print  {0:10} {1:20} {2:12} {3}.format(Interface, MAC address, 
 Protocol, Address)
 +
 +for (name, val) in ifaces.iteritems():
 +if val['ip_addrs']:
 +for addr in val['ip_addrs']:
 +   print  {0:10} {1:19}.format(name, val['hwaddr']),
 +   print  {0:12} {1}/{2} .format(addr['type'], addr['addr'], 
 addr['prefix']),
 +   print
 +else:
 +print  {0:10} {1:19}.format(name, val['hwaddr']),
 +print
 diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
 index 9a88215..60491de 100644
 --- a/python/libvirt-override-api.xml
 +++ b/python/libvirt-override-api.xml
 @@ -602,5 +602,11 @@
arg name='conn' type='virConnectPtr' info='pointer to the hypervisor 
 connection'/
arg name='flags' type='int' info='unused, pass 0'/
  /function
 -  /symbols
 +function name='virDomainInterfaceAddresses' file='python'
 +  inforeturns a dictionary of domain interfaces along with their MAC 
 and IP addresses/info
 +  arg name='dom' type='virDomainPtr' info='pointer to the domain'/
 +  arg name='flags' type='unsigned int' info='extra flags; not used yet, 
 so callers should always pass 0'/
 +  return type='virDomainInterfacePtr

Re: [libvirt] [PATCHv5 2/5] domifaddr: Implement the remote protocol

2013-09-03 Thread Nehal J Wani
On Mon, Sep 2, 2013 at 5:11 PM, Daniel P. Berrange berra...@redhat.com wrote:
 On Sun, Sep 01, 2013 at 07:13:32PM +0530, Nehal J Wani wrote:
 daemon/remote.c
* Define remoteSerializeDomainInterface, 
 remoteDispatchDomainInterfaceAddresses

 src/remote/remote_driver.c
* Define remoteDomainInterfaceAddresses

 src/remote/remote_protocol.x
* New RPC procedure: REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES
* Define structs remote_domain_ip_addr, remote_domain_interface,
  remote_domain_interfaces_addresse_args, 
 remote_domain_interface_addresses_ret
* Introduce upper bounds (to handle DDoS attacks):
  REMOTE_DOMAIN_INTERFACE_MAX = 2048
  REMOTE_DOMAIN_IP_ADDR_MAX = 2048
  Restrictions on the maximum number of aliases per interface were
  removed after kernel v2.0, and theoretically, at present, there
  are no upper limits on number of interfaces per virtual machine
  and on the number of IP addresses per interface.

 src/remote_protocol-structs
* New structs added

 ---
  daemon/remote.c  | 131 
 +++
  src/remote/remote_driver.c   |  99 
  src/remote/remote_protocol.x |  40 -
  src/remote_protocol-structs  |  24 
  4 files changed, 293 insertions(+), 1 deletion(-)

 diff --git a/daemon/remote.c b/daemon/remote.c
 index 6ace7af..7091cab 100644
 --- a/daemon/remote.c
 +++ b/daemon/remote.c
 @@ -5144,7 +5144,138 @@ cleanup:

 +
 +static int
 +remoteDispatchDomainInterfaceAddresses(
 +virNetServerPtr server ATTRIBUTE_UNUSED,
 +virNetServerClientPtr client,
 +virNetMessagePtr msg ATTRIBUTE_UNUSED,
 +virNetMessageErrorPtr rerr,
 +remote_domain_interface_addresses_args *args,
 +remote_domain_interface_addresses_ret *ret)

 Normal practice for this file is to layout args thus:

  static int
  remoteDispatchDomainInterfaceAddresses(virNetServerPtr server 
 ATTRIBUTE_UNUSED,
 virNetServerClientPtr client,
 virNetMessagePtr msg ATTRIBUTE_UNUSED,
 virNetMessageErrorPtr rerr,
 
 remote_domain_interface_addresses_args *args,
 remote_domain_interface_addresses_ret 
 *ret)



 ACK if the style issue is fixed



Style issue fix (File attached):

diff --git a/daemon/remote.c b/daemon/remote.c
index 7091cab..d46e3ea 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5230,13 +5230,12 @@ cleanup:
 }

 static int
-remoteDispatchDomainInterfaceAddresses(
-virNetServerPtr server ATTRIBUTE_UNUSED,
-virNetServerClientPtr client,
-virNetMessagePtr msg ATTRIBUTE_UNUSED,
-virNetMessageErrorPtr rerr,
-remote_domain_interface_addresses_args *args,
-remote_domain_interface_addresses_ret *ret)
+remoteDispatchDomainInterfaceAddresses(virNetServerPtr server ATTRIBUTE_UNUSED,
+   virNetServerClientPtr client,
+   virNetMessagePtr msg ATTRIBUTE_UNUSED,
+   virNetMessageErrorPtr rerr,
+
remote_domain_interface_addresses_args *args,
+
remote_domain_interface_addresses_ret *ret)
 {
 size_t i;
 int rv = -1;



PS: IMO, other functions like remoteDispatchDomainCreateWithFiles,
remoteDispatchDomainCreateXMLWithFiles,
remoteDispatchDomainMigrateFinish3Params, etc also need same style
change


 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 :|



-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com


2.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv5 3/5] domifaddr: Implement the API for qemu

2013-09-03 Thread Nehal J Wani
\,
-\hardware-address\:\52:54:00:36:2a:e5\
+\hardware-address\:\00:00:00:00:00:00\
}
 ]
 };
@@ -679,36 +679,75 @@ testQemuAgentGetInterfaces(const void *data)
 goto cleanup;
 }

-if (ifaces[0]-naddrs != 2 ||
+if (STRNEQ(ifaces[0]-name, eth2) ||
+STRNEQ(ifaces[1]-name, eth1) ||
+STRNEQ(ifaces[2]-name, eth0) ||
+STRNEQ(ifaces[3]-name, lo)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   unexpected return values for interface names);
+goto cleanup;
+}
+
+if (STRNEQ(ifaces[0]-hwaddr, 52:54:00:36:2a:e5) ||
+STRNEQ(ifaces[1]-hwaddr, 52:54:00:d3:39:ee) ||
+STRNEQ(ifaces[2]-hwaddr, 52:54:00:89:ad:35) ||
+STRNEQ(ifaces[3]-hwaddr, 00:00:00:00:00:00)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   unexpected return values for MAC addresses);
+goto cleanup;
+}
+
+if (ifaces[0]-naddrs != 0 ||
 ifaces[1]-naddrs != 4 ||
 ifaces[2]-naddrs != 4 ||
-ifaces[3]-naddrs != 0) {
+ifaces[3]-naddrs != 2) {
 virReportError(VIR_ERR_INTERNAL_ERROR, %s,
-   unexpected return value for number of IP addresses);
+   unexpected return values for number of IP addresses);
 goto cleanup;
 }

-if (STRNEQ(ifaces[0]-name, lo) ||
-STRNEQ(ifaces[0]-addrs[0].addr, 127.0.0.1) ||
-ifaces[0]-addrs[1].prefix != 128) {
+if (ifaces[1]-addrs[0].type != VIR_IP_ADDR_TYPE_IPV4 ||
+ifaces[1]-addrs[1].type != VIR_IP_ADDR_TYPE_IPV6 ||
+ifaces[1]-addrs[2].type != VIR_IP_ADDR_TYPE_IPV4 ||
+ifaces[1]-addrs[3].type != VIR_IP_ADDR_TYPE_IPV6 ||
+ifaces[2]-addrs[0].type != VIR_IP_ADDR_TYPE_IPV6 ||
+ifaces[2]-addrs[1].type != VIR_IP_ADDR_TYPE_IPV4 ||
+ifaces[2]-addrs[2].type != VIR_IP_ADDR_TYPE_IPV4 ||
+ifaces[2]-addrs[3].type != VIR_IP_ADDR_TYPE_IPV6 ||
+ifaces[3]-addrs[0].type != VIR_IP_ADDR_TYPE_IPV4 ||
+ifaces[3]-addrs[1].type != VIR_IP_ADDR_TYPE_IPV6) {
 virReportError(VIR_ERR_INTERNAL_ERROR, %s,
-   unexpected return values for interface: lo);
+   unexpected return values for IP address types);
 goto cleanup;
 }

-if (STRNEQ(ifaces[1]-hwaddr, 52:54:00:89:ad:35) ||
-ifaces[1]-addrs[0].prefix != 24 ||
-ifaces[1]-addrs[1].type != VIR_IP_ADDR_TYPE_IPV6) {
+if (ifaces[1]-addrs[0].prefix != 24 ||
+ifaces[1]-addrs[1].prefix != 64 ||
+ifaces[1]-addrs[2].prefix != 32 ||
+ifaces[1]-addrs[3].prefix != 64 ||
+ifaces[2]-addrs[0].prefix != 64 ||
+ifaces[2]-addrs[1].prefix != 24 ||
+ifaces[2]-addrs[2].prefix != 16 ||
+ifaces[2]-addrs[3].prefix != 64 ||
+ifaces[3]-addrs[0].prefix != 8 ||
+ifaces[3]-addrs[1].prefix != 128) {
 virReportError(VIR_ERR_INTERNAL_ERROR, %s,
-   unexpected return values for interface: eth0);
+   unexpected return values for IP address prefix);
 goto cleanup;
 }

-if (STRNEQ(ifaces[2]-name, eth1) ||
-ifaces[2]-addrs[0].type != VIR_IP_ADDR_TYPE_IPV4 ||
-STRNEQ(ifaces[2]-addrs[1].addr, fe80::5054:ff:fed3:39ee)) {
+if (STRNEQ(ifaces[1]-addrs[0].addr, 192.168.10.91) ||
+STRNEQ(ifaces[1]-addrs[1].addr, fe80::fc54:ff:fefe:4c4f) ||
+STRNEQ(ifaces[1]-addrs[2].addr, 192.168.103.83) ||
+STRNEQ(ifaces[1]-addrs[3].addr, fe80::5054:ff:fed3:39ee) ||
+STRNEQ(ifaces[2]-addrs[0].addr, fe80::5054:ff:fe89:ad35) ||
+STRNEQ(ifaces[2]-addrs[1].addr, 192.168.102.142) ||
+STRNEQ(ifaces[2]-addrs[2].addr, 192.168.234.152) ||
+STRNEQ(ifaces[2]-addrs[3].addr, fe80::5054:ff:fec3:68bb) ||
+STRNEQ(ifaces[3]-addrs[0].addr, 127.0.0.1) ||
+STRNEQ(ifaces[3]-addrs[1].addr, ::1)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, %s,
-   unexpected return values for interface: eth1);
+   unexpected return values for IP address values);
 goto cleanup;
 }


-- 
Nehal J Wani


3.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv5 3/5] domifaddr: Implement the API for qemu

2013-09-03 Thread Nehal J Wani
On Tue, Sep 3, 2013 at 7:46 PM, Osier Yang jy...@redhat.com wrote:

 Except what Daniel pointed out:


 On 01/09/13 21:43, Nehal J Wani wrote:

 By querying the qemu guest agent with the QMP command
 guest-network-get-interfaces and converting the received JSON
 output to structured objects.

 Although ifconfig is deprecated, IP aliases created by ifconfig
 are supported by this API. The legacy syntax of an IP alias is:
 ifname:alias-name. Since we want all aliases to be clubbed
 under parent interface, simply stripping :alias-name suffices.


 s/suffices/suffixes/,

Here, I by suffices, I meant: Be enough or adequate.




 Note that IP aliases formed by ip aren't visible to ifconfig,
 and aliases created by ip do not have any specific name. But
 we are lucky, as qemuga detects aliases created by both.


 s/qemuga/qemu guest agent/, or s/qemuga/qemu-ga/,



 src/qemu/qemu_agent.h:
   * Define qemuAgentGetInterfaces

 src/qemu/qemu_agent.c:
   * Implement qemuAgentGetInterface

 src/qemu/qemu_driver.c:
   * New function qemuDomainInterfaceAddresses

 src/remote_protocol-sructs:
   * Define new structs

 tests/qemuagenttest.c:
   * Add new test: testQemuAgentGetInterfaces
 Test cases for IP aliases, 0 or multiple ipv4/ipv6 address(es)

 ---
  src/qemu/qemu_agent.c  | 193
 +
  src/qemu/qemu_agent.h  |   3 +
  src/qemu/qemu_driver.c |  55 ++
  tests/qemuagenttest.c  | 149 ++
  4 files changed, 400 insertions(+)

 diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
 index 2cd0ccc..009ed77 100644
 --- a/src/qemu/qemu_agent.c
 +++ b/src/qemu/qemu_agent.c
 @@ -1320,6 +1320,199 @@ cleanup:
  }

  /*
 + * qemuAgentGetInterfaces:
 + * @mon: Agent


 s/Agent/Agent monitor/,


 + * @ifaces: pointer to an array of pointers pointing to interface objects
 + *
 + * Issue guest-network-get-interfaces to guest agent, which returns the


 s/the/a/,


 + * list of a interfaces of a running domain along with their IP and MAC


 s/of a/of/,


 + * addresses.
 + *
 + * Returns: number of interfaces on success, -1 on error.
 + */
 +int
 +qemuAgentGetInterfaces(qemuAgentPtr mon,
 +   virDomainInterfacePtr **ifaces)
 +{
 +int ret = -1;
 +size_t i, j;
 +int size = -1;
 +virJSONValuePtr cmd = NULL;
 +virJSONValuePtr reply = NULL;
 +virJSONValuePtr ret_array = NULL;
 +size_t ifaces_count = 0;
 +size_t addrs_count = 0;
 +virDomainInterfacePtr *ifaces_ret = NULL;
 +virHashTablePtr ifaces_store = NULL;
 +
 +/* Initially the bag of ifaces is empty */


 bag is magic here, how about:

 /* Hash table to handle the interface alias */


 +if (!(ifaces_store = virHashCreate(ifaces_count, NULL)))
 +return -1;
 +
 +if (!(cmd = qemuAgentMakeCommand(guest-network-get-interfaces,
 NULL)))
 +   return -1;


 You should free the created hash table.

In the label cleanup, I have freed the has table.




 +
 +if (qemuAgentCommand(mon, cmd, reply,
 VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK)  0 ||
 +qemuAgentCheckError(cmd, reply)  0) {
 +goto cleanup;
 +}
 +
 +if (!(ret_array = virJSONValueObjectGet(reply, return))) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(qemu agent didn't provide 'return' field));
 +goto cleanup;
 +}
 +
 +if ((size = virJSONValueArraySize(ret_array))  0) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(qemu agent didn't return an array of
 interfaces));
 +goto cleanup;
 +}
 +
 +for (i = 0; i  size; i++) {
 +virJSONValuePtr tmp_iface = virJSONValueArrayGet(ret_array, i);
 +virJSONValuePtr ip_addr_arr = NULL;
 +const char *hwaddr, *ifname_s, *name = NULL;
 +char **ifname = NULL;
 +int ip_addr_arr_size;
 +virDomainInterfacePtr iface = NULL;
 +
 +/* Shouldn't happen but doesn't hurt to check neither */
 +if (!tmp_iface) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(something has went really wrong));
 +goto error;
 +}
 +
 +/* interface name is required to be presented */
 +name = virJSONValueObjectGetString(tmp_iface, name);
 +if (!name) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(qemu agent didn't provide 'name' field));
 +goto error;
 +}
 +
 +/* Handle aliases of type ifname:alias-name */


 I think no need to mention the type here, since it only can be
 ifname:alias. So how about:

 /* Handle interface alias (ifname:alias


 +ifname = virStringSplit(name, :, 2);
 +ifname_s = ifname[0];
 +
 +iface = virHashLookup(ifaces_store, ifname_s);
 +
 +/* If the storage bag doesn't contain this iface, add it */


 s/storage bag/hash table/,


 +if (!iface

Re: [libvirt] [PATCHv5 3/5] domifaddr: Implement the API for qemu

2013-09-03 Thread Nehal J Wani
On Tue, Sep 3, 2013 at 8:21 PM, Osier Yang jy...@redhat.com wrote:
 On 03/09/13 22:37, Nehal J Wani wrote:

 On Tue, Sep 3, 2013 at 7:46 PM, Osier Yang jy...@redhat.com wrote:

 Except what Daniel pointed out:


 On 01/09/13 21:43, Nehal J Wani wrote:

 By querying the qemu guest agent with the QMP command
 guest-network-get-interfaces and converting the received JSON
 output to structured objects.

 Although ifconfig is deprecated, IP aliases created by ifconfig
 are supported by this API. The legacy syntax of an IP alias is:
 ifname:alias-name. Since we want all aliases to be clubbed
 under parent interface, simply stripping :alias-name suffices.


 s/suffices/suffixes/,

 Here, I by suffices, I meant: Be enough or adequate.



 Note that IP aliases formed by ip aren't visible to ifconfig,
 and aliases created by ip do not have any specific name. But
 we are lucky, as qemuga detects aliases created by both.


 s/qemuga/qemu guest agent/, or s/qemuga/qemu-ga/,



 src/qemu/qemu_agent.h:
* Define qemuAgentGetInterfaces

 src/qemu/qemu_agent.c:
* Implement qemuAgentGetInterface

 src/qemu/qemu_driver.c:
* New function qemuDomainInterfaceAddresses

 src/remote_protocol-sructs:
* Define new structs

 tests/qemuagenttest.c:
* Add new test: testQemuAgentGetInterfaces
  Test cases for IP aliases, 0 or multiple ipv4/ipv6 address(es)

 ---
   src/qemu/qemu_agent.c  | 193
 +
   src/qemu/qemu_agent.h  |   3 +
   src/qemu/qemu_driver.c |  55 ++
   tests/qemuagenttest.c  | 149 ++
   4 files changed, 400 insertions(+)

 diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
 index 2cd0ccc..009ed77 100644
 --- a/src/qemu/qemu_agent.c
 +++ b/src/qemu/qemu_agent.c
 @@ -1320,6 +1320,199 @@ cleanup:
   }

   /*
 + * qemuAgentGetInterfaces:
 + * @mon: Agent


 s/Agent/Agent monitor/,


 + * @ifaces: pointer to an array of pointers pointing to interface
 objects
 + *
 + * Issue guest-network-get-interfaces to guest agent, which returns the


 s/the/a/,


 + * list of a interfaces of a running domain along with their IP and MAC


 s/of a/of/,


 + * addresses.
 + *
 + * Returns: number of interfaces on success, -1 on error.
 + */
 +int
 +qemuAgentGetInterfaces(qemuAgentPtr mon,
 +   virDomainInterfacePtr **ifaces)
 +{
 +int ret = -1;
 +size_t i, j;
 +int size = -1;
 +virJSONValuePtr cmd = NULL;
 +virJSONValuePtr reply = NULL;
 +virJSONValuePtr ret_array = NULL;
 +size_t ifaces_count = 0;
 +size_t addrs_count = 0;
 +virDomainInterfacePtr *ifaces_ret = NULL;
 +virHashTablePtr ifaces_store = NULL;
 +
 +/* Initially the bag of ifaces is empty */


 bag is magic here, how about:

 /* Hash table to handle the interface alias */


 +if (!(ifaces_store = virHashCreate(ifaces_count, NULL)))
 +return -1;
 +
 +if (!(cmd = qemuAgentMakeCommand(guest-network-get-interfaces,
 NULL)))
 +   return -1;


 You should free the created hash table.

 In the label cleanup, I have freed the has table.


 But you returns -1 here.





 +
 +if (qemuAgentCommand(mon, cmd, reply,
 VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK)  0 ||
 +qemuAgentCheckError(cmd, reply)  0) {
 +goto cleanup;
 +}
 +
 +if (!(ret_array = virJSONValueObjectGet(reply, return))) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(qemu agent didn't provide 'return' field));
 +goto cleanup;
 +}
 +
 +if ((size = virJSONValueArraySize(ret_array))  0) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(qemu agent didn't return an array of
 interfaces));
 +goto cleanup;
 +}
 +
 +for (i = 0; i  size; i++) {
 +virJSONValuePtr tmp_iface = virJSONValueArrayGet(ret_array, i);
 +virJSONValuePtr ip_addr_arr = NULL;
 +const char *hwaddr, *ifname_s, *name = NULL;
 +char **ifname = NULL;
 +int ip_addr_arr_size;
 +virDomainInterfacePtr iface = NULL;
 +
 +/* Shouldn't happen but doesn't hurt to check neither */
 +if (!tmp_iface) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(something has went really wrong));
 +goto error;
 +}
 +
 +/* interface name is required to be presented */
 +name = virJSONValueObjectGetString(tmp_iface, name);
 +if (!name) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s,
 +   _(qemu agent didn't provide 'name' field));
 +goto error;
 +}
 +
 +/* Handle aliases of type ifname:alias-name */


 I think no need to mention the type here, since it only can be
 ifname:alias. So how about:

 /* Handle interface alias (ifname:alias


 +ifname = virStringSplit(name, :, 2);
 +ifname_s = ifname[0];
 +
 +iface = virHashLookup(ifaces_store

[libvirt] [PATCH] Fix: Syle issues (daemon/remote.c)

2013-09-03 Thread Nehal J Wani
Fix for argument layouts of various functions in daemon/remote.c. Refer:
https://www.redhat.com/archives/libvir-list/2013-September/msg00057.html

---
 daemon/remote.c | 117 ++--
 1 file changed, 55 insertions(+), 62 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 6ace7af..2aff7c1 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -3852,13 +3852,13 @@ cleanup:
 return rv;
 }
 
-static int remoteDispatchDomainGetDiskErrors(
-virNetServerPtr server ATTRIBUTE_UNUSED,
-virNetServerClientPtr client,
-virNetMessagePtr msg ATTRIBUTE_UNUSED,
-virNetMessageErrorPtr rerr,
-remote_domain_get_disk_errors_args *args,
-remote_domain_get_disk_errors_ret *ret)
+static int
+remoteDispatchDomainGetDiskErrors(virNetServerPtr server ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client,
+  virNetMessagePtr msg ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  remote_domain_get_disk_errors_args *args,
+  remote_domain_get_disk_errors_ret *ret)
 {
 int rv = -1;
 virDomainPtr dom = NULL;
@@ -4674,13 +4674,12 @@ cleanup:
 }
 
 static int
-remoteDispatchDomainMigrateBegin3Params(
-virNetServerPtr server ATTRIBUTE_UNUSED,
-virNetServerClientPtr client ATTRIBUTE_UNUSED,
-virNetMessagePtr msg ATTRIBUTE_UNUSED,
-virNetMessageErrorPtr rerr,
-remote_domain_migrate_begin3_params_args *args,
-remote_domain_migrate_begin3_params_ret *ret)
+remoteDispatchDomainMigrateBegin3Params(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+virNetMessagePtr msg ATTRIBUTE_UNUSED,
+virNetMessageErrorPtr rerr,
+
remote_domain_migrate_begin3_params_args *args,
+
remote_domain_migrate_begin3_params_ret *ret)
 {
 char *xml = NULL;
 virDomainPtr dom = NULL;
@@ -4733,13 +4732,12 @@ cleanup:
 }
 
 static int
-remoteDispatchDomainMigratePrepare3Params(
-virNetServerPtr server ATTRIBUTE_UNUSED,
-virNetServerClientPtr client ATTRIBUTE_UNUSED,
-virNetMessagePtr msg ATTRIBUTE_UNUSED,
-virNetMessageErrorPtr rerr,
-remote_domain_migrate_prepare3_params_args *args,
-remote_domain_migrate_prepare3_params_ret *ret)
+remoteDispatchDomainMigratePrepare3Params(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_migrate_prepare3_params_args *args,
+  
remote_domain_migrate_prepare3_params_ret *ret)
 {
 virTypedParameterPtr params = NULL;
 int nparams = 0;
@@ -4794,13 +4792,12 @@ cleanup:
 }
 
 static int
-remoteDispatchDomainMigratePrepareTunnel3Params(
-virNetServerPtr server ATTRIBUTE_UNUSED,
-virNetServerClientPtr client,
-virNetMessagePtr msg,
-virNetMessageErrorPtr rerr,
-remote_domain_migrate_prepare_tunnel3_params_args *args,
-remote_domain_migrate_prepare_tunnel3_params_ret *ret)
+remoteDispatchDomainMigratePrepareTunnel3Params(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+virNetServerClientPtr client,
+virNetMessagePtr msg,
+virNetMessageErrorPtr rerr,
+
remote_domain_migrate_prepare_tunnel3_params_args *args,
+
remote_domain_migrate_prepare_tunnel3_params_ret *ret)
 {
 virTypedParameterPtr params = NULL;
 int nparams = 0;
@@ -4865,13 +4862,12 @@ cleanup:
 
 
 static int
-remoteDispatchDomainMigratePerform3Params(
-virNetServerPtr server ATTRIBUTE_UNUSED,
-virNetServerClientPtr client ATTRIBUTE_UNUSED,
-virNetMessagePtr msg ATTRIBUTE_UNUSED,
-virNetMessageErrorPtr rerr,
-remote_domain_migrate_perform3_params_args *args,
-remote_domain_migrate_perform3_params_ret *ret)
+remoteDispatchDomainMigratePerform3Params(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_migrate_perform3_params_args *args,
+  

Re: [libvirt] [PATCHv5 1/5] domifaddr: Implement the public APIs

2013-09-05 Thread Nehal J Wani
On Wed, Sep 4, 2013 at 8:05 PM, Osier Yang jy...@redhat.com wrote:
 On 04/09/13 03:13, Eric Blake wrote:

 On 09/03/2013 01:07 PM, Eric Blake wrote:

 On 09/01/2013 07:43 AM, Nehal J Wani wrote:

 Define a new API virDomainInterfaceAddresses, which returns
 the address information of a running domain's interfaces(s).
 If no interface name is specified, it returns the information
 of all interfaces, otherwise it only returns the information
 of the specificed interface. The address information includes
 the MAC and IP addresses.

 Define helper function virDomainInterfaceFree, which allows
 the upper layer application to free the domain interface object
 conveniently.

 The API is going to provide multiple methods by flags, e.g.

   * Query guest agent
   * Parse lease file of dnsmasq
   * DHCP snooping

 But at this stage, it will only work with guest agent, and flags
 won't be supported.

 That worries me a bit.  Ultimately, we want our interfaces to behave as
 sane as possible when flags==0; rather than making the behavior be that
 'flags==0' implies 'only guest agent probe', I'd rather introduce a flag
 right away up front that says 'include guest agent probe in the set of
 attempted methods', and then document that 'flags==0 is shorthand for
 letting the hypervisor choose the best method(s) out of supported
 possibilities)'.  In other words, I want to make sure that this API will
 be similar to virDomainShutdownFlags, where a flags of 0 lets the
 hypervisor choose between methods, a single explicit flag forces the
 hypervisor to use that method alone, and more than one flag can be OR'd
 together to let the hypervisor choose among that subset of flags.

 Hmm.  I'm replying to myself - is that a good sign?

 If the guest agent returns names that are provided by the guest, and
 don't necessarily correspond to the domain XML, then maybe it's best to
 NEVER return guest results by default, but to make the user always
 explicitly request agent interaction.


 Hm, yes, the MAC address returned by guest agent might not
 match what the domain config specifies. It reminds me something,
 both the leases file and snooping will returns the interface name
 like vnetN, which is different with what guest agent returns (like
 ethN or emN). And since the MAC address from guest agent might
 be different with what domain config specifies, we have no way to
 convert it into the names in domain config. That says we will have
 different name styles for guest agent and the other two methods,
 which will need quite documentations to explain.

 That is, even if 'flags==0' is
 used to select between parsing the lease file vs. DHCP snoop results
 (both of which tie perfectly to guest XML naming), the agent approach
 can seriously confuse users if they passed flags==0 and don't know if
 they are getting XML names or guest-provided names.  Which argues that
 guest results should ALWAYS be an explicit non-zero flag, never an
 automatic action.



 --
 libvir-list mailing list
 libvir-list@redhat.com
 https://www.redhat.com/mailman/listinfo/libvir-list



Daniel, would like to throw some light on the discussion?

-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCHv5 1/5] domifaddr: Implement the public APIs

2013-09-06 Thread Nehal J Wani
On Tue, Sep 3, 2013 at 6:51 PM, Osier Yang jy...@redhat.com wrote:
 On 01/09/13 21:43, Nehal J Wani wrote:

 Define a new API virDomainInterfaceAddresses, which returns
 the address information of a running domain's interfaces(s).
 If no interface name is specified, it returns the information
 of all interfaces, otherwise it only returns the information
 of the specificed interface. The address information includes
 the MAC and IP addresses.


 This API only returns all of the interfaces' address info, it
 doesn't take an argument to specify an interface. My bad
 though, didn't find it out in previous reviewing.

 ACK with the commit log fixed.

 Osier

The optional argument interface is supported. I had forgotten to add
it in the example.

-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv6 3/5] domifaddr: Implement the API for qemu

2013-09-06 Thread Nehal J Wani
By querying the qemu guest agent with the QMP command
guest-network-get-interfaces and converting the received JSON
output to structured objects.

Although ifconfig is deprecated, IP aliases created by ifconfig
are supported by this API. The legacy syntax of an IP alias is:
ifname:alias-name. Since we want all aliases to be clubbed
under parent interface, simply stripping :alias-name suffices.
Note that IP aliases formed by ip aren't visible to ifconfig,
and aliases created by ip do not have any specific name. But
we are lucky, as qemu guest agent detects aliases created by both.

src/qemu/qemu_agent.h:
  * Define qemuAgentGetInterfaces

src/qemu/qemu_agent.c:
  * Implement qemuAgentGetInterface

src/qemu/qemu_driver.c:
  * New function qemuDomainInterfaceAddresses

src/remote_protocol-sructs:
  * Define new structs

tests/qemuagenttest.c:
  * Add new test: testQemuAgentGetInterfaces
Test cases for IP aliases, 0 or multiple ipv4/ipv6 address(es)

---
 src/qemu/qemu_agent.c  | 202 +
 src/qemu/qemu_agent.h  |   3 +
 src/qemu/qemu_driver.c |  74 ++
 tests/qemuagenttest.c  | 188 +
 4 files changed, 467 insertions(+)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 2cd0ccc..76f8e7c 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1320,6 +1320,208 @@ cleanup:
 }
 
 /*
+ * qemuAgentGetInterfaces:
+ * @mon: Agent monitor
+ * @ifaces: pointer to an array of pointers pointing to interface objects
+ *
+ * Issue guest-network-get-interfaces to guest agent, which returns a
+ * list of interfaces of a running domain along with their IP and MAC
+ * addresses.
+ *
+ * Returns: number of interfaces on success, -1 on error.
+ */
+int
+qemuAgentGetInterfaces(qemuAgentPtr mon,
+   virDomainInterfacePtr **ifaces)
+{
+int ret = -1;
+size_t i, j;
+int size = -1;
+virJSONValuePtr cmd = NULL;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr ret_array = NULL;
+size_t ifaces_count = 0;
+size_t addrs_count = 0;
+virDomainInterfacePtr *ifaces_ret = NULL;
+virHashTablePtr ifaces_store = NULL;
+char **ifname = NULL;
+
+/* Hash table to handle the interface alias */
+if (!(ifaces_store = virHashCreate(ifaces_count, NULL))) {
+virHashFree(ifaces_store);
+return -1;
+}
+
+if (!(cmd = qemuAgentMakeCommand(guest-network-get-interfaces, NULL))) {
+goto cleanup;
+}
+
+if (qemuAgentCommand(mon, cmd, reply, 
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK)  0 ||
+qemuAgentCheckError(cmd, reply)  0) {
+goto cleanup;
+}
+
+if (!(ret_array = virJSONValueObjectGet(reply, return))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(qemu agent didn't provide 'return' field));
+goto cleanup;
+}
+
+if ((size = virJSONValueArraySize(ret_array))  0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(qemu agent didn't return an array of interfaces));
+goto cleanup;
+}
+
+for (i = 0; i  size; i++) {
+virJSONValuePtr tmp_iface = virJSONValueArrayGet(ret_array, i);
+virJSONValuePtr ip_addr_arr = NULL;
+const char *hwaddr, *ifname_s, *name = NULL;
+int ip_addr_arr_size;
+virDomainInterfacePtr iface = NULL;
+
+/* Shouldn't happen but doesn't hurt to check neither */
+if (!tmp_iface) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(something has went really wrong));
+goto error;
+}
+
+/* interface name is required to be presented */
+name = virJSONValueObjectGetString(tmp_iface, name);
+if (!name) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(qemu agent didn't provide 'name' field));
+goto error;
+}
+
+/* Handle interface alias (ifname:alias) */
+ifname = virStringSplit(name, :, 2);
+ifname_s = ifname[0];
+
+iface = virHashLookup(ifaces_store, ifname_s);
+
+/* If the hash table doesn't contain this iface, add it */
+if (!iface) {
+if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1)  0)
+goto error;
+
+if (VIR_ALLOC(ifaces_ret[ifaces_count - 1])  0)
+goto error;
+
+if (virHashAddEntry(ifaces_store, ifname_s,
+ifaces_ret[ifaces_count - 1])  0)
+goto error;
+
+iface = ifaces_ret[ifaces_count - 1];
+iface-naddrs = 0;
+
+if (VIR_STRDUP(iface-name, ifname_s)  0)
+goto error;
+
+hwaddr = virJSONValueObjectGetString(tmp_iface, 
hardware-address);
+if (!hwaddr) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(qemu agent didn't provide
+ 

[libvirt] [PATCHv6 2/5] domifaddr: Implement the remote protocol

2013-09-06 Thread Nehal J Wani
daemon/remote.c
   * Define remoteSerializeDomainInterface, 
remoteDispatchDomainInterfaceAddresses

src/remote/remote_driver.c
   * Define remoteDomainInterfaceAddresses

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES
   * Define structs remote_domain_ip_addr, remote_domain_interface,
 remote_domain_interfaces_addresse_args, 
remote_domain_interface_addresses_ret
   * Introduce upper bounds (to handle DDoS attacks):
 REMOTE_DOMAIN_INTERFACE_MAX = 2048
 REMOTE_DOMAIN_IP_ADDR_MAX = 2048
 Restrictions on the maximum number of aliases per interface were
 removed after kernel v2.0, and theoretically, at present, there
 are no upper limits on number of interfaces per virtual machine
 and on the number of IP addresses per interface.

src/remote_protocol-structs
   * New structs added

---
 daemon/remote.c  | 130 +++
 src/remote/remote_driver.c   |  99 
 src/remote/remote_protocol.x |  40 -
 src/remote_protocol-structs  |  24 
 4 files changed, 292 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 2aff7c1..4dff602 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5137,7 +5137,137 @@ cleanup:
 return rv;
 }
 
+static int
+remoteSerializeDomainInterface(virDomainInterfacePtr *ifaces,
+   unsigned int ifaces_count,
+   remote_domain_interface_addresses_ret *ret)
+{
+size_t i, j;
+
+if (ifaces_count  REMOTE_DOMAIN_INTERFACE_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of interfaces, %d exceeds the max limit: %d),
+   ifaces_count, REMOTE_DOMAIN_INTERFACE_MAX);
+return -1;
+}
+
+if (VIR_ALLOC_N(ret-ifaces.ifaces_val, ifaces_count)  0)
+return -1;
+
+ret-ifaces.ifaces_len = ifaces_count;
+
+for (i = 0; i  ifaces_count; i++) {
+virDomainInterfacePtr iface = ifaces[i];
+remote_domain_interface *iface_ret = (ret-ifaces.ifaces_val[i]);
+
+if ((VIR_STRDUP(iface_ret-name, iface-name))  0)
+goto cleanup;
+
+if (iface-hwaddr) {
+char **hwaddr_p = NULL;
+if (VIR_ALLOC(hwaddr_p)  0)
+goto cleanup;
+if (VIR_STRDUP(*hwaddr_p, iface-hwaddr)  0) {
+VIR_FREE(hwaddr_p);
+goto cleanup;
+}
+
+iface_ret-hwaddr = hwaddr_p;
+}
+
+if (iface-naddrs  REMOTE_DOMAIN_IP_ADDR_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of interfaces, %d exceeds the max limit: 
%d),
+   iface-naddrs, REMOTE_DOMAIN_IP_ADDR_MAX);
+goto cleanup;
+}
+
+if (VIR_ALLOC_N(iface_ret-addrs.addrs_val,
+iface-naddrs)  0)
+goto cleanup;
+
+iface_ret-addrs.addrs_len = iface-naddrs;
+
+for (j = 0; j  iface-naddrs; j++) {
+virDomainIPAddressPtr ip_addr = (iface-addrs[j]);
+remote_domain_ip_addr *ip_addr_ret =
+(iface_ret-addrs.addrs_val[j]);
+
+if (VIR_STRDUP(ip_addr_ret-addr, ip_addr-addr)  0)
+goto cleanup;
+
+ip_addr_ret-prefix = ip_addr-prefix;
+ip_addr_ret-type = ip_addr-type;
+}
+}
+
+return 0;
+
+cleanup:
+if (ret-ifaces.ifaces_val) {
+for (i = 0; i  ifaces_count; i++) {
+remote_domain_interface *iface_ret = (ret-ifaces.ifaces_val[i]);
+VIR_FREE(iface_ret-name);
+VIR_FREE(iface_ret-hwaddr);
+for (j = 0; j  iface_ret-addrs.addrs_len; j++) {
+remote_domain_ip_addr *ip_addr =
+(iface_ret-addrs.addrs_val[j]);
+VIR_FREE(ip_addr-addr);
+}
+VIR_FREE(iface_ret);
+}
+VIR_FREE(ret-ifaces.ifaces_val);
+}
+
+return -1;
+}
+
+static int
+remoteDispatchDomainInterfaceAddresses(virNetServerPtr server ATTRIBUTE_UNUSED,
+   virNetServerClientPtr client,
+   virNetMessagePtr msg ATTRIBUTE_UNUSED,
+   virNetMessageErrorPtr rerr,
+   remote_domain_interface_addresses_args 
*args,
+   remote_domain_interface_addresses_ret 
*ret)
+{
+size_t i;
+int rv = -1;
+virDomainPtr dom = NULL;
+virDomainInterfacePtr *ifaces = NULL;
+int ifaces_count = 0;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv-conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open));
+goto cleanup;
+}
 
+if (!(dom = get_nonnull_domain(priv-conn, args-dom)))
+goto cleanup;
+

[libvirt] [PATCHv6 5/5] domifaddr: Expose python binding

2013-09-06 Thread Nehal J Wani
Expose virDomainInterfacesAddresses to python binding

examples/python/Makefile.am:
  * Add new file domipaddrs.py

examples/python/README:
  * Add documentation for the python example

python/libvirt-override-api.xml:
  * Add new symbol for virDomainInterfacesAddresses

python/libvirt-override.c:
  * Hand written python api

  Example:
  $ ./run ./examples/python/domipaddrs.py qemu:///system f18
  Interface  MAC address  Protocol Address
  lo 00:00:00:00:00:00ipv4 127.0.0.1/8
  lo 00:00:00:00:00:00ipv6 ::1/128
  eth3   52:54:00:20:70:3dipv4 192.168.105.240/16
  eth3   52:54:00:20:70:3dipv6 fe80::5054:ff:fe20:703d/64
  eth2   52:54:00:36:2a:e5N/A  N/A
  eth1   52:54:00:b1:70:19ipv4 192.168.105.201/16
  eth1   52:54:00:b1:70:19ipv4 192.168.201.195/16
  eth1   52:54:00:b1:70:19ipv6 fe80::5054:ff:feb1:7019/64
  eth0   52:54:00:2e:45:ceipv4 10.1.33.188/24
  eth0   52:54:00:2e:45:ceipv6 2001:db8:0:f101::2/64
  eth0   52:54:00:2e:45:ceipv6 fe80::5054:ff:fe2e:45ce/64

---
 examples/python/Makefile.am |   2 +-
 examples/python/README  |   1 +
 examples/python/domipaddrs.py   |  57 ++
 python/libvirt-override-api.xml |   8 +++-
 python/libvirt-override.c   | 102 
 5 files changed, 168 insertions(+), 2 deletions(-)
 create mode 100755 examples/python/domipaddrs.py

diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am
index 7823c20..b77154f 100644
--- a/examples/python/Makefile.am
+++ b/examples/python/Makefile.am
@@ -18,4 +18,4 @@ EXTRA_DIST=   \
README  \
consolecallback.py  \
topology.py \
-   dominfo.py domrestore.py domsave.py domstart.py esxlist.py
+   dominfo.py domrestore.py domsave.py domstart.py esxlist.py domipaddrs.py
diff --git a/examples/python/README b/examples/python/README
index f4db76c..1285d52 100644
--- a/examples/python/README
+++ b/examples/python/README
@@ -10,6 +10,7 @@ domsave.py  - save all running domU's into a directory
 domrestore.py - restore domU's from their saved files in a directory
 esxlist.py  - list active domains of an VMware ESX host and print some info.
   also demonstrates how to use the libvirt.openAuth() method
+domipaddrs.py - print domain interfaces along with their MAC and IP addresses
 
 The XML files in this directory are examples of the XML format that libvirt
 expects, and will have to be adapted for your setup. They are only needed
diff --git a/examples/python/domipaddrs.py b/examples/python/domipaddrs.py
new file mode 100755
index 000..4430f59
--- /dev/null
+++ b/examples/python/domipaddrs.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# domipaddrds - print domain interfaces along with their MAC and IP addresses
+
+import libvirt
+import sys
+
+def usage():
+print Usage: %s [URI] DOMAIN % sys.argv[0]
+print Print domain interfaces along with their MAC and IP 
addresses
+
+uri = None
+name = None
+args = len(sys.argv)
+
+if args == 2:
+name = sys.argv[1]
+elif args == 3:
+uri = sys.argv[1]
+name = sys.argv[2]
+else:
+usage()
+sys.exit(2)
+
+conn = libvirt.open(uri)
+if conn == None:
+print Unable to open connection to libvirt
+sys.exit(1)
+
+try:
+dom = conn.lookupByName(name)
+except libvirt.libvirtError:
+print Domain %s not found % name
+sys.exit(0)
+
+ifaces = dom.interfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_AGENT);
+if (ifaces == None):
+print Failed to get domain interfaces
+sys.exit(0)
+
+print  {0:10} {1:20} {2:12} {3}.format(Interface, MAC address, 
Protocol, Address)
+
+def toIPAddrType(addrType):
+if addrType == libvirt.VIR_IP_ADDR_TYPE_IPV4:
+return ipv4
+elif addrType == libvirt.VIR_IP_ADDR_TYPE_IPV6:
+return ipv6
+
+for (name, val) in ifaces.iteritems():
+if val['ip_addrs']:
+for addr in val['ip_addrs']:
+   print  {0:10} {1:19}.format(name, val['hwaddr']),
+   print  {0:12} {1}/{2} .format(toIPAddrType(addr['type']), 
addr['addr'], addr['prefix']),
+   print
+else:
+print  {0:10} {1:19}.format(name, val['hwaddr']),
+print  {0:12} {1}.format(N/A, N/A),
+print
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 9a88215..60491de 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -602,5 +602,11 @@
   arg name='conn' type='virConnectPtr' info='pointer to the hypervisor 
connection'/
   arg name='flags' type='int' info='unused, pass 0'/
 /function
-  /symbols
+function name='virDomainInterfaceAddresses' file='python'
+  inforeturns a 

[libvirt] [PATCHv6 0/5] Introduce API to query IP addresses for given domain

2013-09-06 Thread Nehal J Wani
This feature has been requested for a very long time. Since qemu guest
agent gives us reliable results, now the wait is over.

The RFC was first proposed by Michal Privoznik:
 http://www.redhat.com/archives/libvir-list/2012-February/msg00437.html
A patch was submitted, using structs:
 https://www.redhat.com/archives/libvir-list/2012-June/msg00220.html
Another patch was submitted, using XML:
 https://www.redhat.com/archives/libvir-list/2012-June/msg00904.html

Neither of the patches were accepted, probably due to lack of extensibility
and usability. Hence, we thought of using virTypedParameters for reporting
list of interfaces along with their MAC address and IP addresses. The RFC
can be found here:
 https://www.redhat.com/archives/libvir-list/2013-July/msg00084.html

The idea of extensibility was rejected and rendered out of scope of
libvirt. Hence, we were back to structs.

This API is called virDomainInterfaceAddresses which returns a dynamically
allocated array of virDomainInterface struct. The great disadvantage is
once this gets released, it's written in stone and we cannot change
or add an item into it.

The API supports two methods:

* Return information (list of all associated interfaces with MAC address
 and IP addresses) of all of the domain interfaces by default (if
 no interface name is provided)

* Return information for the specified interface (if an interface name
 is provided)

v6:
* Inclusion of flags, readonly check for guest agent connection
* Correction of memory leaks, other small nits.

v5:
* s/virDomainInterfacesAddresses/virDomainInterfaceAddresses.
* Case for IP aliasing handled using virHashTable.
* New test cases added, involving multiple and 0 IP addresse(s)
  per interface.
* IP prefix changed from int to unsigned int.
* Changes to practice libvirt habits.
* https://www.redhat.com/archives/libvir-list/2013-September/msg3.html

v4:
* Various style nits, indentation errors, memory leaks fixed.
* https://www.redhat.com/archives/libvir-list/2013-August/msg01265.html

v3:
* Upper bounds to number of interfaces and addresses per interface
  introduced.
* Change from array of structs to array of pointers
* ifaces_count moved from function argument to return value
* Changes in variable names
* Test cases added for qemuAgentGetInterfaces.
* https://www.redhat.com/archives/libvir-list/2013-August/msg01215.html

v2:
* Logical errors, memory leaks and few other errors fixed.
* https://www.redhat.com/archives/libvir-list/2013-August/msg00631.html

v1:
* http://www.redhat.com/archives/libvir-list/2013-July/msg01553.html


Nehal J Wani (5):
  domifaddr: Implement the public APIs
  domifaddr: Implement the remote protocol
  domifaddr: Implement the API for qemu
  domifaddr: Add virsh support
  domifaddr: Expose python binding

 daemon/remote.c | 130 ++
 examples/python/Makefile.am |   2 +-
 examples/python/README  |   1 +
 examples/python/domipaddrs.py   |  56 +++
 include/libvirt/libvirt.h.in|  38 
 python/generator.py |   3 +
 python/libvirt-override-api.xml |   8 +-
 python/libvirt-override.c   | 102 
 src/driver.h|   6 ++
 src/libvirt.c   | 135 +++
 src/libvirt_public.syms |   6 ++
 src/qemu/qemu_agent.c   | 201 
 src/qemu/qemu_agent.h   |   3 +
 src/qemu/qemu_driver.c  |  76 +++
 src/remote/remote_driver.c  |  99 
 src/remote/remote_protocol.x|  40 +++-
 src/remote_protocol-structs |  24 +
 tests/qemuagenttest.c   | 188 +
 tools/virsh-domain-monitor.c| 131 ++
 tools/virsh.pod |  18 
 20 files changed, 1264 insertions(+), 3 deletions(-)
 create mode 100755 examples/python/domipaddrs.py

-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv6 4/5] domifaddr: Add virsh support

2013-09-06 Thread Nehal J Wani
Use virDomainInterfaceAddresses in virsh

tools/virsh-domain-monitor.c
   * Introduce new command : domifaddr
 Usage: domifaddr domain [interface] [--full] [--snoop] [--lease] 
[--agent]

 Example outputs:
 virsh # domifaddr f18
 Name   MAC address  Protocol Address
 
---
 lo 00:00:00:00:00:00ipv4 127.0.0.1/8
 -  -ipv6 ::1/128
 eth0   52:54:00:2e:45:ceipv4 10.1.33.188/24
 -  -ipv6 2001:db8:0:f101::2/64
 -  -ipv6 fe80::5054:ff:fe2e:45ce/64
 eth1   52:54:00:b1:70:19ipv4 192.168.105.201/16
 -  -ipv4 192.168.201.195/16
 -  -ipv6 fe80::5054:ff:feb1:7019/64
 eth2   52:54:00:36:2a:e5N/A  N/A
 eth3   52:54:00:20:70:3dipv4 192.168.105.240/16
 -  -ipv6 fe80::5054:ff:fe20:703d/64

 virsh # domifaddr f18 eth1 --agent
 Name   MAC address  Protocol Address
 
---
 eth1   52:54:00:b1:70:19ipv4 192.168.105.201/16
 -  -ipv4 192.168.201.195/16
 -  -ipv6 fe80::5054:ff:feb1:7019/64

 virsh # domifaddr f18 eth0 --agent --full
 Name   MAC address  Protocol Address
 
---
 eth0   52:54:00:2e:45:ceipv4 10.1.33.188/24
 eth0   52:54:00:2e:45:ceipv6 2001:db8:0:f101::2/64
 eth0   52:54:00:2e:45:ceipv6 fe80::5054:ff:fe2e:45ce/64

tools/virsh.pod
   * Document new command

---
 tools/virsh-domain-monitor.c | 131 +++
 tools/virsh.pod  |  18 ++
 2 files changed, 149 insertions(+)

diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index b29b82a..3690776 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -1871,6 +1871,131 @@ cleanup:
 }
 #undef FILTER
 
+/* domifaddr command
+ */
+static const vshCmdInfo info_domifaddr[] = {
+{help, N_(Get network interfaces' addresses for a running domain)},
+{desc, N_(Get network interfaces' addresses for a running domain)},
+{NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domifaddr[] = {
+{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)},
+{interface, VSH_OT_DATA, VSH_OFLAG_NONE, N_(network interface name)},
+{full, VSH_OT_BOOL, VSH_OFLAG_NONE, N_(display full fields)},
+{snoop, VSH_OT_BOOL, VSH_OFLAG_NONE, N_(snoop network traffic)},
+{lease, VSH_OT_BOOL, VSH_OFLAG_NONE, N_(parse dhcp lease file)},
+{agent, VSH_OT_BOOL, VSH_OFLAG_NONE, N_(query qemu guest agent)},
+{NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom = NULL;
+const char *interface = NULL;
+virDomainInterfacePtr *ifaces = NULL;
+size_t i, j;
+int ifaces_count = 0;
+unsigned int flags = 0;
+bool ret = false;
+bool full = vshCommandOptBool(cmd, full);
+
+if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if (vshCommandOptString(cmd, interface, interface)  0) {
+goto cleanup;
+}
+
+if (vshCommandOptBool(cmd, snoop))
+flags |= VIR_DOMAIN_INTERFACE_ADDRESSES_SNOOP;
+
+if (vshCommandOptBool(cmd, lease))
+flags |= VIR_DOMAIN_INTERFACE_ADDRESSES_LEASE;
+
+if (vshCommandOptBool(cmd, agent))
+flags |= VIR_DOMAIN_INTERFACE_ADDRESSES_AGENT;
+
+if ((ifaces_count = virDomainInterfaceAddresses(dom, ifaces, flags))  0) 
{
+vshError(ctl, _(Failed to query for interfaces addresses));
+goto cleanup;
+}
+
+vshPrintExtra(ctl,  %-10s %-20s %-8s %s\n%s%s\n, _(Name),
+  _(MAC address), _(Protocol), _(Address),
+  _(-),
+  _(--));
+
+for (i = 0; i  ifaces_count; i++) {
+virDomainInterfacePtr iface = ifaces[i];
+const char *hwaddr = ;
+const char *ip_addr_str = NULL;
+const char *type = NULL;
+
+if (interface  STRNEQ(interface, iface-name))
+continue;
+
+hwaddr = iface-hwaddr;
+
+/* When the interface has no IP address */
+if (!iface-naddrs) {
+vshPrintExtra(ctl,  %-10s %-17s%-12s %s\n,
+  iface-name, hwaddr, N/A, N/A);
+continue;
+}
+
+for (j = 0; j  iface-naddrs; j++) {
+virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ 

[libvirt] [PATCHv6 1/5] domifaddr: Implement the public APIs

2013-09-06 Thread Nehal J Wani
Define helper function virDomainInterfaceFree, which allows
the upper layer application to free the domain interface object
conveniently.

The API is going to provide multiple methods by flags, e.g.
  * Query guest agent
  * Parse lease file of dnsmasq
  * DHCP snooping

At this stage, it will only work with guest agent. Passing other
flags will result in error: Method hasn't been implemented yet

include/libvirt/libvirt.h.in:
  * Define virDomainInterfaceAddresses, virDomainInterfaceFree
  * Define structs virDomainInterface, virDomainIPAddress

python/generator.py:
  * Skip the auto-generation for virDomainInterfaceAddresses
and virDomainInterfaceFree

src/driver.h:
  * Define domainInterfaceAddresses

src/libvirt.c:
  * Implement virDomainInterfaceAddresses
  * Implement virDomainInterfaceFree

src/libvirt_public.syms:
  * Export the new symbols

---
 include/libvirt/libvirt.h.in |  38 
 python/generator.py  |   3 +
 src/driver.h |   6 ++
 src/libvirt.c| 135 +++
 src/libvirt_public.syms  |   6 ++
 5 files changed, 188 insertions(+)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..0995080 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2044,6 +2044,44 @@ int virDomainGetInterfaceParameters 
(virDomainPtr dom,
  virTypedParameterPtr 
params,
  int *nparams, 
unsigned int flags);
 
+typedef enum {
+VIR_DOMAIN_INTERFACE_ADDRESSES_SNOOP = (1  0), /* Snoop traffic */
+VIR_DOMAIN_INTERFACE_ADDRESSES_LEASE = (1  1), /* Parse DHCP lease file 
*/
+VIR_DOMAIN_INTERFACE_ADDRESSES_AGENT = (1  2), /* Query qemu guest agent 
*/
+} virDomainInterfaceAddressesFlags;
+
+typedef enum {
+VIR_IP_ADDR_TYPE_IPV4 = 0,
+VIR_IP_ADDR_TYPE_IPV6 = 1,
+
+#ifdef VIR_ENUM_SENTINELS
+VIR_IP_ADDR_TYPE_LAST,
+#endif
+} virIPAddrType;
+
+typedef struct _virDomainInterfaceIPAddress virDomainIPAddress;
+typedef virDomainIPAddress *virDomainIPAddressPtr;
+struct _virDomainInterfaceIPAddress {
+int type;/* virIPAddrType */
+char *addr;  /* IP address */
+unsigned int prefix; /* IP address prefix */
+};
+
+typedef struct _virDomainInterface virDomainInterface;
+typedef virDomainInterface *virDomainInterfacePtr;
+struct _virDomainInterface {
+char *name; /* interface name */
+char *hwaddr;   /* hardware address */
+unsigned int naddrs;/* number of items in @addrs */
+virDomainIPAddressPtr addrs;/* array of IP addresses */
+};
+
+int virDomainInterfaceAddresses(virDomainPtr dom,
+virDomainInterfacePtr **ifaces,
+unsigned int flags);
+
+void virDomainInterfaceFree(virDomainInterfacePtr iface);
+
 /* Management of domain block devices */
 
 int virDomainBlockPeek (virDomainPtr dom,
diff --git a/python/generator.py b/python/generator.py
index fb321c6..50f779b 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -458,6 +458,7 @@ skip_impl = (
 'virNodeGetMemoryParameters',
 'virNodeSetMemoryParameters',
 'virNodeGetCPUMap',
+'virDomainInterfaceAddresses',
 'virDomainMigrate3',
 'virDomainMigrateToURI3',
 )
@@ -560,6 +561,8 @@ skip_function = (
 virTypedParamsGetString,
 virTypedParamsGetUInt,
 virTypedParamsGetULLong,
+
+virDomainInterfaceFree, # Only useful in C
 )
 
 lxc_skip_function = (
diff --git a/src/driver.h b/src/driver.h
index be64333..210a910 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -518,6 +518,11 @@ typedef int
   unsigned int flags);
 
 typedef int
+(*virDrvDomainInterfaceAddresses)(virDomainPtr dom,
+  virDomainInterfacePtr **ifaces,
+  unsigned int flags);
+
+typedef int
 (*virDrvDomainMemoryStats)(virDomainPtr domain,
struct _virDomainMemoryStat *stats,
unsigned int nr_stats,
@@ -1238,6 +1243,7 @@ struct _virDriver {
 virDrvDomainInterfaceStats domainInterfaceStats;
 virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;
 virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;
+virDrvDomainInterfaceAddresses domainInterfaceAddresses;
 virDrvDomainMemoryStats domainMemoryStats;
 virDrvDomainBlockPeek domainBlockPeek;
 virDrvDomainMemoryPeek domainMemoryPeek;
diff --git a/src/libvirt.c b/src/libvirt.c
index 07a3fd5..7a5759b 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -8643,6 +8643,116 @@ error:
 return -1;
 }
 
+ /**
+ * virDomainInterfaceAddresses:
+ * @dom: domain object
+ * @ifaces: pointer to an array of pointers pointing to interface objects
+ * 

Re: [libvirt] [PATCHv6 1/5] domifaddr: Implement the public APIs

2013-09-11 Thread Nehal J Wani
ping


On Sun, Sep 8, 2013 at 2:42 PM, Osier Yang jy...@redhat.com wrote:

 [..]



  + *
 + * If 0 is passed as @flags, libvirt will choose the best way, and
 won't
 + * include agent in it.


 I'm thinking if we don't need to be so complicated, by defaulting to one
 of _LEASE or _SNOOP explicitly.

 That says (conclusion of all of above), I'm wondering if define the enum
 like
 blow is better.


 typedef enum {
 VIR_DOMAIN_INTERFACE_**ADDRESSES_AGENT = (1  1), /* Query qemu
 guest agent */



 And s/AGENT/GUEST_AGENT/, since AGENT could mean too much than guest
 agent





-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 4/4] net-dhcp-leases: Add virsh support

2013-09-11 Thread Nehal J Wani
Use virNetworkGetDHCPLeases and virNetworkGetDHCPLeaseForMAC in virsh.

The new feature supports the follwing methods:

1. Retrieve leases info for a given virtual network

2. Retrieve leases info for given network interface

tools/virsh-domain-monitor.c
   * Introduce new command : net-dhcp-leases
 Example Usage: net-dhcp-leases network [mac]

 virsh # net-dhcp-leases default

 Expiry Time  MAC address  IP addressHostname 
ClientId
 
--
 11-09-2013 03:53:11  52:54:00:89:4e:97192.168.101.130   f18  *
 11-09-2013 03:45:20  52:54:00:fe:4c:4f192.168.101.197   **

tools/virsh.pod
   * Document new command



---
 tools/virsh-network.c | 92 +++
 tools/virsh.pod   |  6 
 2 files changed, 98 insertions(+)

diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 8ddd5ca..6319d29 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -1129,6 +1129,92 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd)
 
 return ret;
 }
+/*
+ * net-dhcp-leases command
+ */
+static const vshCmdInfo info_network_dhcp_leases[] = {
+{.name = help,
+ .data = N_(Print lease info for a given network)
+},
+{.name = desc,
+ .data = N_(Print lease info for a given network)
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_dhcp_leases[] = {
+{.name = network,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_(network name or uuid)
+},
+{.name = mac,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_NONE,
+ .help = N_(MAC address)
+},
+{.name = NULL}
+};
+
+static bool
+cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd)
+{
+const char *name = NULL;
+const char *mac = NULL;
+virNetworkDHCPLeasesPtr *leases = NULL;
+virNetworkDHCPLeases lease_mac;
+int nleases = 0;
+bool ret = false;
+size_t i;
+unsigned int flags = 0;
+virNetworkPtr network = NULL;
+
+if (vshCommandOptString(cmd, mac, mac)  0)
+goto cleanup;
+
+if (!(network = vshCommandOptNetworkBy(ctl, cmd, name,
+   VSH_BYNAME | VSH_BYUUID)))
+goto cleanup;
+
+nleases = mac ? virNetworkGetDHCPLeaseForMAC(network, mac, lease_mac, 
flags)
+  :virNetworkGetDHCPLeases(network, leases, flags);
+
+if (nleases  0) {
+vshError(ctl, _(Failed to get leases info for %s), name);
+goto cleanup;
+}
+
+vshPrintExtra(ctl,  %-20s %-20s %-17s %-12s %s\n%s%s\n,
+  _(Expiry Time), _(MAC address),
+  _(IP address), _(Hostname), _(ClientId),
+  ,
+  );
+
+for (i = 0; i  nleases; i++) {
+virNetworkDHCPLeasesPtr lease = mac ? lease_mac : leases[i];
+time_t expirytime_tmp = lease-expirytime;
+struct tm ts;
+char expirytime[32];
+ts = *localtime_r(expirytime_tmp, ts);
+strftime(expirytime, sizeof(expirytime), %d-%m-%Y %H:%M:%S, ts);
+
+vshPrintExtra(ctl,  %-20s %-20s %-17s %-12s %s\n,
+  expirytime, lease-mac, lease-ipaddr,
+  lease-hostname, lease-clientid);
+}
+
+ret = true;
+
+cleanup:
+if (leases) {
+for (i = 0; i  nleases; i++)
+virNetworkDHCPLeaseFree(leases[i]);
+}
+VIR_FREE(leases);
+if (network)
+virNetworkFree(network);
+return ret;
+}
 
 const vshCmdDef networkCmds[] = {
 {.name = net-autostart,
@@ -1209,5 +1295,11 @@ const vshCmdDef networkCmds[] = {
  .info = info_network_uuid,
  .flags = 0
 },
+{.name = net-dhcp-leases,
+ .handler = cmdNetworkDHCPLeases,
+ .opts = opts_network_dhcp_leases,
+ .info = info_network_dhcp_leases,
+ .flags = 0
+},
 {.name = NULL}
 };
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0ae5178..b87f646 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2325,6 +2325,12 @@ If I--current is specified, affect the current network 
state.
 Both I--live and I--config flags may be given, but I--current is
 exclusive. Not specifying any flag is the same as specifying I--current.
 
+=item Bnet-dhcp-leases Inetwork Imac
+
+Get a list of dhcp leases for all network interfaces connected to the given
+virtual Inetwork or limited output just for one interface if Imac is
+specified.
+
 =back
 
 =head1 INTERFACE COMMANDS
-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 2/4] net-dhcp-leases: Implement the remote protocol

2013-09-11 Thread Nehal J Wani
Implement RPC calls for virNetworkGetDHCPLeases, virNetworkGetDHCPLeaseForMAC

daemon/remote.c
   * Define remoteSerializeNetworkDHCPLeases,
remoteDispatchNetworkGetDHCPLeases
   * Define remoteDispatchNetworkGetDHCPLeaseForMAC

src/remote/remote_driver.c
   * Define remoteNetworkGetDHCPLeases
   * Define remoteNetworkGetDHCPLeaseForMAC

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES
   * Define structs remote_network_dhcp_leases, 
remote_network_get_dhcp_leases_args,
remote_network_get_dhcp_leases_ret
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASE_FOR_MAC
   * Define structs remote_network_dhcp_lease_for_mac, 
remote_network_get_dhcp_lease_for_mac_args,
remote_network_get_dhcp_lease_for_mac_ret

src/remote_protocol-structs
   * New structs added

src/rpc/gendispatch.pl
   * Add exception (s/Dhcp/DHCP) for auto-generating names of the remote 
functions
 in ./daemon/remote_dispatch.h



---
 daemon/remote.c  | 128 +++
 src/remote/remote_driver.c   | 117 +++
 src/remote/remote_protocol.x |  48 +++-
 src/remote_protocol-structs  |  27 +
 src/rpc/gendispatch.pl   |   1 +
 5 files changed, 320 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 2aff7c1..13be327 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5137,7 +5137,135 @@ cleanup:
 return rv;
 }
 
+static int
+remoteSerializeNetworkDHCPLeases(virNetworkDHCPLeasesPtr *leases,
+ int nleases,
+ remote_network_get_dhcp_leases_ret *ret)
+{
+size_t i;
+
+if (nleases  REMOTE_NETWORK_DHCPLEASES_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of leases is %d, which exceeds max limit: 
%d),
+   nleases, REMOTE_NETWORK_DHCPLEASES_MAX);
+return -1;
+}
+
+if (VIR_ALLOC_N(ret-leases.leases_val, nleases)  0)
+goto error;
+
+ret-leases.leases_len = nleases;
+
+for (i = 0; i  nleases; i++) {
+virNetworkDHCPLeasesPtr lease = leases[i];
+remote_network_dhcp_lease *lease_ret = (ret-leases.leases_val[i]);
+lease_ret-expirytime = lease-expirytime;
+
+if ((VIR_STRDUP(lease_ret-mac, lease-mac)  0) ||
+(VIR_STRDUP(lease_ret-ipaddr, lease-ipaddr)  0) ||
+(VIR_STRDUP(lease_ret-hostname, lease-hostname)  0) ||
+(VIR_STRDUP(lease_ret-clientid, lease-clientid)  0))
+goto error;
+}
+
+return 0;
+
+error:
+if (ret-leases.leases_val) {
+for (i = 0; i  nleases; i++) {
+remote_network_dhcp_lease *lease_ret = 
(ret-leases.leases_val[i]);
+virNetworkDHCPLeaseFree((virNetworkDHCPLeasesPtr)lease_ret);
+}
+}
+return -1;
+}
+
+static int
+remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server ATTRIBUTE_UNUSED,
+   virNetServerClientPtr client,
+   virNetMessagePtr msg ATTRIBUTE_UNUSED,
+   virNetMessageErrorPtr rerr,
+   remote_network_get_dhcp_leases_args *args,
+   remote_network_get_dhcp_leases_ret *ret)
+{
+int rv = -1;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virNetworkDHCPLeasesPtr *leases = NULL;
+virNetworkPtr net = NULL;
+int nleases = 0;
+
+if (!priv-conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open));
+goto cleanup;
+}
+
+if (!(net = get_nonnull_network(priv-conn, args-net)))
+goto cleanup;
+
+if ((nleases = virNetworkGetDHCPLeases(net,leases, args-flags))  0)
+goto cleanup;
 
+if (remoteSerializeNetworkDHCPLeases(leases, nleases, ret)  0)
+goto cleanup;
+
+rv = nleases;
+
+cleanup:
+if (rv  0)
+virNetMessageSaveError(rerr);
+if (leases) {
+size_t i;
+for (i = 0; i  nleases; i++) {
+virNetworkDHCPLeaseFree(leases[i]);
+}
+}
+VIR_FREE(leases);
+return rv;
+}
+
+static int
+remoteDispatchNetworkGetDHCPLeaseForMAC(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+virNetServerClientPtr client,
+virNetMessagePtr msg ATTRIBUTE_UNUSED,
+virNetMessageErrorPtr rerr,
+
remote_network_get_dhcp_lease_for_mac_args *args,
+
remote_network_get_dhcp_lease_for_mac_ret *ret)
+{
+int rv = -1;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virNetworkDHCPLeases lease;
+virNetworkPtr net = NULL;
+const char *mac;
+

[libvirt] [PATCH 1/4] net-dhcp-leases: Implement the public APIs

2013-09-11 Thread Nehal J Wani
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeaseForMAC
and virNetworkDHCPLeaseFree.

* virNetworkGetDHCPLeases: returns the dhcp leases information for a given
 virtual network. The information includes lease expirytime, MAC Address,
 IP Address, hostname and clientid.

* virNetworkGetDHCPLeaseForMAC: returns the dhcp lease information for a
 given virtual network and specified MAC Address.

* virNetworkDHCPLeaseFree: allows the upper layer application to free the
 network interface object conveniently.

There is no support for flags, so user is expected to pass 0 for
both the APIs.

include/libvirt/libvirt.h.in:
  * Define virNetworkGetDHCPLeases
  * Define virNetworkGetDHCPLeaseForMAC
  * Define virNetworkDHCPLeaseFree

python/generator.py:
  * Skip the auto-generation for virNetworkGetDHCPLeases
  * Skip the auto-generation for virNetworkGetDHCPLeaseForMAC
  * Skip the auto-generation for virNetworkDHCPLeaseFree

src/driver.h:
  * Define networkGetDHCPLeases
  * Define networkGetDHCPLeaseForMAC

src/libvirt.c:
  * Implement virNetworkGetDHCPLeases
  * Implement virNetworkGetDHCPLeaseForMAC
  * Implement virNetworkDHCPLeaseFree

src/libvirt_public.syms:
  * Export the new symbols

---
 include/libvirt/libvirt.h.in |  22 ++
 python/generator.py  |   3 +
 src/driver.h |  13 
 src/libvirt.c| 166 +++
 src/libvirt_public.syms  |   7 ++
 5 files changed, 211 insertions(+)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..3885baf 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2800,6 +2800,28 @@ int virConnectNumOfDefinedInterfaces 
(virConnectPtr conn);
 int virConnectListDefinedInterfaces  (virConnectPtr conn,
   char **const names,
   int maxnames);
+
+typedef struct _virNetworkDHCPLeases virNetworkDHCPLeases;
+typedef virNetworkDHCPLeases *virNetworkDHCPLeasesPtr;
+struct _virNetworkDHCPLeases {
+long long expirytime;
+char *mac;
+char *ipaddr;
+char *hostname;
+char *clientid;
+};
+
+void virNetworkDHCPLeaseFree(virNetworkDHCPLeasesPtr lease);
+
+int virNetworkGetDHCPLeases(virNetworkPtr network,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
+int virNetworkGetDHCPLeaseForMAC(virNetworkPtr network,
+ const char *mac,
+ virNetworkDHCPLeasesPtr leases,
+ unsigned int flags);
+
 /*
  * virConnectListAllInterfaces:
  *
diff --git a/python/generator.py b/python/generator.py
index a91dde8..708657a 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -460,6 +460,8 @@ skip_impl = (
 'virNodeGetCPUMap',
 'virDomainMigrate3',
 'virDomainMigrateToURI3',
+'virNetworkGetDHCPLeases',
+'virNetworkGetDHCPLeaseForMAC',
 )
 
 lxc_skip_impl = (
@@ -560,6 +562,7 @@ skip_function = (
 virTypedParamsGetString,
 virTypedParamsGetUInt,
 virTypedParamsGetULLong,
+'virNetworkDHCPLeaseFree',
 )
 
 lxc_skip_function = (
diff --git a/src/driver.h b/src/driver.h
index be64333..4c835b2 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1121,6 +1121,17 @@ typedef int
  int cookieinlen,
  unsigned int flags,
  int cancelled);
+typedef int
+(*virDrvNetworkGetDHCPLeases)(virNetworkPtr network,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
+typedef int
+(*virDrvNetworkGetDHCPLeaseForMAC)(virNetworkPtr network,
+   const char *mac,
+   virNetworkDHCPLeasesPtr leases,
+   unsigned int flags);
+
 
 typedef struct _virDriver virDriver;
 typedef virDriver *virDriverPtr;
@@ -1451,6 +1462,8 @@ struct _virNetworkDriver {
 virDrvNetworkSetAutostart networkSetAutostart;
 virDrvNetworkIsActive networkIsActive;
 virDrvNetworkIsPersistent networkIsPersistent;
+virDrvNetworkGetDHCPLeases networkGetDHCPLeases;
+virDrvNetworkGetDHCPLeaseForMAC networkGetDHCPLeaseForMAC;
 };
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
index 665b30b..63afdac 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -68,6 +68,7 @@
 #include virstring.h
 #include virutil.h
 #include virtypedparam.h
+#include virmacaddr.h
 
 #ifdef WITH_TEST
 # include test/test_driver.h
@@ -21961,3 +21962,168 @@ error:
 virDispatchError(dom-conn);
 return -1;
 }
+
+/**
+ * virNetworkGetDHCPLeases:
+ * @network: pointer to network object
+ * @leases: pointer to an array of pointers pointing to the obtained leases
+ * @flags: extra 

[libvirt] [PATCH 3/4] net-dhcp-leases: Private implementation inside network driver

2013-09-11 Thread Nehal J Wani
By querying the driver for the path of the leases file for the given virtual
network and parsing it to retrieve info.

src/network/bridge_driver.c:
  * Implement networkGetDHCPLeases
  * Implement networkGetDHCPLeaseForMAC
  * Implement networkGetDHCPLeasesHelper

---
 src/network/bridge_driver.c | 222 
 1 file changed, 222 insertions(+)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 3a8be90..e5923eb 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -109,6 +109,35 @@ static int networkPlugBandwidth(virNetworkObjPtr net,
 virDomainNetDefPtr iface);
 static int networkUnplugBandwidth(virNetworkObjPtr net,
   virDomainNetDefPtr iface);
+/**
+ * VIR_NETWORK_DHCPLEASE_LENGTH_MAX:
+ *
+ * Macro providing the maximum length of an entry in the leases file
+ * Refer: 
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2013q3/007402.html
+ */
+#define VIR_NETWORK_DHCPLEASE_LENGTH_MAX 2048
+
+/**
+ * VIR_NETWORK_DHCPLEASE_PARAMS:
+ *
+ * Macro providing the maximum number of parameters in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCPLEASE_FIELDS 5
+
+static int networkGetDHCPLeases(virNetworkPtr network,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
+static int networkGetDHCPLeaseForMAC(virNetworkPtr network,
+ const char *mac,
+ virNetworkDHCPLeasesPtr lease,
+ unsigned int flags);
+
+static int networkGetDHCPLeasesHelper(virNetworkPtr network,
+  const char *mac,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
 
 static virNetworkDriverStatePtr driverState = NULL;
 
@@ -2980,6 +3009,197 @@ cleanup:
 return ret;
 }
 
+static int
+networkGetDHCPLeases(virNetworkPtr network,
+ virNetworkDHCPLeasesPtr **leases,
+ unsigned int flags)
+{
+int rv = -1;
+virNetworkDriverStatePtr driver = network-conn-networkPrivateData;
+virNetworkObjPtr obj;
+
+virCheckFlags(0, -1);
+
+networkDriverLock(driver);
+obj = virNetworkFindByName(driver-networks, network-name);
+networkDriverUnlock(driver);
+
+if (virNetworkGetDHCPLeasesEnsureACL(network-conn, obj-def)  0)
+goto cleanup;
+
+rv = networkGetDHCPLeasesHelper(network, NULL, leases, flags);
+
+cleanup:
+if (obj)
+virNetworkObjUnlock(obj);
+return rv;
+}
+
+static int
+networkGetDHCPLeaseForMAC(virNetworkPtr network,
+  const char *mac,
+  virNetworkDHCPLeasesPtr lease,
+  unsigned int flags)
+{
+virNetworkDHCPLeasesPtr *leases = NULL;
+int nleases = 0;
+int rv = -1;
+size_t i;
+
+virNetworkDriverStatePtr driver = network-conn-networkPrivateData;
+virNetworkObjPtr obj;
+
+virCheckFlags(0, -1);
+
+networkDriverLock(driver);
+obj = virNetworkFindByName(driver-networks, network-name);
+networkDriverUnlock(driver);
+
+if (virNetworkGetDHCPLeaseForMACEnsureACL(network-conn, obj-def)  0)
+goto cleanup;
+
+if ((nleases = networkGetDHCPLeasesHelper(network, mac,
+  leases, flags)) = 0)
+goto error;
+
+if (nleases  1) {
+/* Hmm, can DHCP give more than one lease for same MAC? */
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(Something is wrong. MAC address 
+ can't repeat in the leases));
+goto error;
+}
+
+lease-expirytime = leases[0]-expirytime;
+
+if ((VIR_STRDUP(lease-mac, leases[0]-mac)  0) ||
+(VIR_STRDUP(lease-ipaddr, leases[0]-ipaddr)  0) ||
+(VIR_STRDUP(lease-hostname, leases[0]-hostname)  0) ||
+(VIR_STRDUP(lease-clientid, leases[0]-clientid)  0))
+goto error;
+
+rv = nleases;
+
+cleanup:
+if (obj)
+virNetworkObjUnlock(obj);
+return rv;
+
+error:
+if (leases) {
+for (i = 0; i  nleases; i++)
+virNetworkDHCPLeaseFree(leases[i]);
+}
+VIR_FREE(leases);
+goto cleanup;
+}
+
+static int
+networkGetDHCPLeasesHelper(virNetworkPtr network,
+   const char *mac,
+   virNetworkDHCPLeasesPtr **leases,
+   unsigned int flags)
+{
+char *leasefile;
+char **leaseparams;
+char dhcpentry[VIR_NETWORK_DHCPLEASE_LENGTH_MAX];
+FILE *fp = NULL;
+int rv = -1;
+
+virNetworkDHCPLeasesPtr *leases_ret = NULL;
+size_t nleases = 0;
+size_t i = 0;
+
+
+virCheckFlags(0, -1);
+
+if (!network) {
+virReportError(VIR_ERR_NO_NETWORK, %s,
+   _(no 

[libvirt] [PATCH 0/4] Introduce APIs to extract DHCP leases info

2013-09-11 Thread Nehal J Wani
This API returns the information stored in the DHCP leases file
created by dnsmasq for a given virtual network. It contacts the
bridge network driver, which parses the leases file.

It supports two methods:

1. Return info for all network interfaces connected to a given
   virtual network
2. Return information for a particular network interface in a
   given virtual network by providing its MAC Address

* The need for these APIs were result of a RFC was proposed on the list.
  Refer: http://www.redhat.com/archives/libvir-list/2013-July/msg01603.html

Nehal J Wani (4):
  net-dhcp-leases: Implement the public APIs
  net-dhcp-leases: Implement the remote protocol
  net-dhcp-leases: Private implementation inside network driver
  net-dhcp-leases: Add virsh support

 daemon/remote.c  | 128 +
 include/libvirt/libvirt.h.in |  22 +
 python/generator.py  |   3 +
 src/driver.h |  13 +++
 src/libvirt.c| 166 
 src/libvirt_public.syms  |   7 ++
 src/network/bridge_driver.c  | 222 +++
 src/remote/remote_driver.c   | 117 +++
 src/remote/remote_protocol.x |  48 +-
 src/remote_protocol-structs  |  27 ++
 src/rpc/gendispatch.pl   |   1 +
 tools/virsh-network.c|  92 ++
 tools/virsh.pod  |   6 ++
 13 files changed, 851 insertions(+), 1 deletion(-)

-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] rpmbuild libvirt 1.1.2 problem

2013-09-11 Thread Nehal J Wani
On Wed, Sep 11, 2013 at 10:17 AM,  jsjshaowen...@21cn.com wrote:
 hi:
 i build rpm in centos 6.2,   libvirt version 1.1.2,i found an error
 FAIL: virsh-uriprecedence

 Details in the attachment,thanks !Wait for a response


 ---
 21CN手机邮Android客户端,邮件随身享!

 --
 libvir-list mailing list
 libvir-list@redhat.com
 https://www.redhat.com/mailman/listinfo/libvir-list

Reproducible on Cent OS 6.4 x86_64
See attached log for details.

-- 
Nehal J Wani
PASS: virshtest
PASS: sockettest
PASS: nodeinfotest
PASS: virbuftest
PASS: commandtest
PASS: seclabeltest
PASS: virhashtest
PASS: virnetmessagetest
PASS: virnetsockettest
PASS: viratomictest
PASS: utiltest
PASS: shunloadtest
PASS: virtimetest
PASS: viruritest
PASS: virkeyfiletest
PASS: virauthconfigtest
PASS: virbitmaptest
PASS: vircgrouptest
PASS: virendiantest
PASS: viridentitytest
PASS: virkeycodetest
PASS: virlockspacetest
PASS: virstringtest
PASS: virportallocatortest
PASS: sysinfotest
PASS: virstoragetest
PASS: fdstreamtest
PASS: fchosttest
PASS: virnettlscontexttest
PASS: virnettlssessiontest
SKIP: securityselinuxtest
SKIP: securityselinuxlabeltest
PASS: virdrivermoduletest
PASS: qemuxml2argvtest
PASS: qemuxml2xmltest
PASS: qemuxmlnstest
PASS: qemuargv2xmltest
PASS: qemuhelptest
PASS: domainsnapshotxml2xmltest
PASS: qemumonitortest
PASS: qemumonitorjsontest
PASS: qemuhotplugtest
PASS: qemuagenttest
PASS: lxcxml2xmltest
PASS: esxutilstest
PASS: vmx2xmltest
PASS: xml2vmxtest
PASS: jsontest
PASS: networkxml2xmltest
PASS: networkxml2xmlupdatetest
PASS: networkxml2conftest
PASS: nwfilterxml2xmltest
PASS: storagevolxml2argvtest
PASS: storagevolxml2xmltest
PASS: storagepoolxml2xmltest
PASS: nodedevxml2xmltest
PASS: interfacexml2xmltest
PASS: cputest
PASS: eventtest
PASS: libvirtdconftest
PASS: capabilityschematest
PASS: interfaceschematest
PASS: networkschematest
PASS: storagepoolschematest
PASS: storagevolschematest
PASS: domainschematest
PASS: nodedevschematest
PASS: nwfilterschematest
PASS: domainsnapshotschematest
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include stdlib.h
PASS: test_conf.sh
PASS: cpuset
PASS: define-dev-segfault
PASS: int-overflow
PASS: libvirtd-fail
PASS: libvirtd-pool
PASS: read-bufsiz
PASS: read-non-seekable
PASS: start
FAIL: virsh-uriprecedence
PASS: vcpupin
PASS: virsh-all
PASS: virsh-optparse
PASS: virsh-schedinfo
PASS: virsh-synopsis
PASS: virsh-undefine
make[4]: Entering directory `/root/rpmbuild/BUILD/libvirt-1.1.2/tests'
make[4]: Nothing to be done for `all'.
make[4]: Leaving directory `/root/rpmbuild/BUILD/libvirt-1.1.2/tests'

Testsuite summary for libvirt 1.1.2

# TOTAL: 85
# PASS:  82
# SKIP:  2
# XFAIL: 0
# FAIL:  1
# XPASS: 0
# ERROR: 0

See tests/test-suite.log
Please report to libvir-list@redhat.com

make[3]: *** [test-suite.log] Error 1
make[3]: Leaving directory `/root/rpmbuild/BUILD/libvirt-1.1.2/tests'
make[2]: *** [check-TESTS] Error 2
make[2]: Leaving directory `/root/rpmbuild/BUILD/libvirt-1.1.2/tests'
make[1]: *** [check-am] Error 2
make[1]: Leaving directory `/root/rpmbuild/BUILD/libvirt-1.1.2/tests'
+ cat test-suite.log
=
   libvirt 1.1.2: tests/test-suite.log
=

# TOTAL: 85
# PASS:  82
# SKIP:  2
# XFAIL: 0
# FAIL:  1
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

SKIP: securityselinuxtest
=

TEST: securityselinuxtest

SKIP: securityselinuxlabeltest
==

TEST: securityselinuxlabeltest

FAIL: virsh-uriprecedence
=

error: failed to connect to the hypervisor
error: no valid connection
error: internal error: Unable to locate libvirtd daemon in /usr/sbin (to 
override, set $LIBVIRTD_PATH to the name of the libvirtd binary)
  1) User config file ... FAILED
  2) LIBVIRT_DEFAULT_URI  ... OK
  3) VIRSH_DEFAULT_CONNECT_URI... OK
  4) Parameter... OK

+ exit 1
error: Bad exit status from /var/tmp/rpm-tmp.oRWBuD (%check)


RPM build errors:
Bad exit status from /var/tmp/rpm-tmp.oRWBuD (%check)
make: *** [rpm] Error 1
[root@ldap libvirt-1.1.2]# #include sys/types.h
[root@ldap libvirt-1.1.2]# #include sys/stat.h
[root@ldap libvirt-1.1.2]# #include fcntl.h
[root@ldap libvirt-1.1.2]# #include unistd.h
[root@ldap libvirt-1.1.2]# #include stdlib.h

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 1/4] net-dhcp-leases: Implement the public APIs

2013-09-11 Thread Nehal J Wani
On Wed, Sep 11, 2013 at 9:25 PM, Daniel P. Berrange berra...@redhat.com wrote:

 On Wed, Sep 11, 2013 at 09:00:09PM +0530, Nehal J Wani wrote:
  diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
  index a47e33c..3885baf 100644
  --- a/include/libvirt/libvirt.h.in
  +++ b/include/libvirt/libvirt.h.in
  @@ -2800,6 +2800,28 @@ int 
  virConnectNumOfDefinedInterfaces (virConnectPtr conn);
   int virConnectListDefinedInterfaces  (virConnectPtr 
  conn,
 char **const 
  names,
 int maxnames);
  +
  +typedef struct _virNetworkDHCPLeases virNetworkDHCPLeases;
  +typedef virNetworkDHCPLeases *virNetworkDHCPLeasesPtr;
  +struct _virNetworkDHCPLeases {
  +long long expirytime;
  +char *mac;
  +char *ipaddr;
  +char *hostname;
  +char *clientid;
  +};

 This is missing

 int type;/* virIPAddrType */

 since it can be IPv4 or IPv6 in general.

 Also we have no 'prefix' field here. Although the 'prefix' is present in
 the network XML config, I think it would be useful to include it here
 too, for parity with the virDomainInterfaceIPAddress struct


The virNetworkDHCPLeases struct was made according to the lease
parameters returned by dnsmasq. Are you suggesting that libvirt might
shift to some other DHCP server in future? Also, in case the DHCP server
doesn't return the IP address type and/or prefix, in that case, should these
values be NULL, when returned to the user?


  +
  +void virNetworkDHCPLeaseFree(virNetworkDHCPLeasesPtr lease);
  +
  +int virNetworkGetDHCPLeases(virNetworkPtr network,
  +virNetworkDHCPLeasesPtr **leases,
  +unsigned int flags);
  +
  +int virNetworkGetDHCPLeaseForMAC(virNetworkPtr network,
  + const char *mac,
  + virNetworkDHCPLeasesPtr leases,

 This should be '**leases' as with the other method. While our dnsmasq
 setup only supports a single lease, for IPv4, that is not suitably
 generic. We may well need to support DHCP v6 in the future which would
 mean we had multiple leases to return per MAC address.

  + unsigned int flags);
  +
   /*
* virConnectListAllInterfaces:
*

 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 :|




-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 2/4] net-dhcp-leases: Implement the remote protocol

2013-09-11 Thread Nehal J Wani
 +
 +ret-leases.leases_len = nleases;
 +
 +for (i = 0; i  nleases; i++) {
 +virNetworkDHCPLeasesPtr lease = leases[i];
 +remote_network_dhcp_lease *lease_ret =
(ret-leases.leases_val[i]);
 +lease_ret-expirytime = lease-expirytime;
 +
 +if ((VIR_STRDUP(lease_ret-mac, lease-mac)  0) ||
 +(VIR_STRDUP(lease_ret-ipaddr, lease-ipaddr)  0) ||
 +(VIR_STRDUP(lease_ret-hostname, lease-hostname)  0) ||
 +(VIR_STRDUP(lease_ret-clientid, lease-clientid)  0))
 +goto error;
 +}
 +

This above code is reported so many times in the patch, in
networkGetDHCPLeaseForMAC, remoteNetworkGetDHCPLeaseForMAC,
remoteNetworkGetDHCPLeases, remoteDispatchNetworkGetDHCPLeaseForMAC
and remoteSerializeNetworkDHCPLeases.

Hence I was wondering, whether it would be useful to introduce a helper
function, say virNetworkDHCPLeaseCopy, which would copy lease contents
from one lease pointer to another, something like:
/**
 * virNetworkDHCPLeaseCopy:
 * @dst: pointer to the destination lease object
 * @src: pointer to the source lease object
 *
 * Copies contents of @src to @dst.
 *
 * Returns 0 on success, -1 otherwise.
 */
int
virNetworkDHCPLeaseCopy(virNetworkDHCPLeasesPtr dst,
virNetworkDHCPLeasesPtr src)
{
dst-expirytime = src-expirytime;
if ((VIR_STRDUP(dst-macaddr, src-macaddr)  0) ||
(VIR_STRDUP(dst-ipaddr, src-ipaddr)  0) ||
(VIR_STRDUP(dst-hostname, src-hostname)  0) ||
(VIR_STRDUP(dst-clientid, src-clientid)  0))
return -1;
return 0;
}

But the issue with this is that it wants the user to allocate memory
to the dst pointer (As the code in remote protocols does).
Also, will it be ever used by the users? If not, then should we be
introducing this function to some place in /src/util, so that
code redundancy can be removed?



-- 
Nehal J Wani
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv6 1/5] domifaddr: Implement the public APIs

2013-09-12 Thread Nehal J Wani
Eric, could you please share your views on the discussion?


On Sun, Sep 8, 2013 at 2:42 PM, Osier Yang jy...@redhat.com wrote:

 [..]



  + *
 + * If 0 is passed as @flags, libvirt will choose the best way, and
 won't
 + * include agent in it.


 I'm thinking if we don't need to be so complicated, by defaulting to one
 of _LEASE or _SNOOP explicitly.

 That says (conclusion of all of above), I'm wondering if define the enum
 like
 blow is better.


 typedef enum {
 VIR_DOMAIN_INTERFACE_**ADDRESSES_AGENT = (1  1), /* Query qemu
 guest agent */



 And s/AGENT/GUEST_AGENT/, since AGENT could mean too much than guest
 agent





-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] rpmbuild libvirt 1.1.2 problem

2013-09-12 Thread Nehal J Wani
The issue is being fixed by the patch:
https://www.redhat.com/archives/libvir-list/2013-September/msg00703.html


On Thu, Sep 12, 2013 at 8:35 PM, Alex Jia a...@redhat.com wrote:

 Hi Martin,
 BTW, I met the same question, and I ran 'make check' under root.

 --
 Regards,
 Alex


 - Original Message -
 From: Martin Kletzander mklet...@redhat.com
 To: Nehal J Wani nehaljw.k...@gmail.com
 Cc: libvir-list libvir-list@redhat.com, jsjshaowen...@21cn.com
 Sent: Thursday, September 12, 2013 4:29:32 PM
 Subject: Re: [libvirt] rpmbuild libvirt 1.1.2 problem

 On 09/11/2013 07:18 PM, Nehal J Wani wrote:
  On Wed, Sep 11, 2013 at 10:17 AM,  jsjshaowen...@21cn.com wrote:
  hi:
  i build rpm in centos 6.2,   libvirt version 1.1.2,i found an error
  FAIL: virsh-uriprecedence
 
  Details in the attachment,thanks !Wait for a response
 
 
  Reproducible on Cent OS 6.4 x86_64
  See attached log for details.
 

 I've identified the problem; we aren't correctly reading file paths when
 running as root.  Are you running make check under root?

 Martin

 --
 libvir-list mailing list
 libvir-list@redhat.com
 https://www.redhat.com/mailman/listinfo/libvir-list




-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCHv2 2/4] net-dhcp-leases: Implement the remote protocol

2013-09-12 Thread Nehal J Wani
Implement RPC calls for virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC

daemon/remote.c
   * Define remoteSerializeNetworkDHCPLeases,
remoteDispatchNetworkGetDHCPLeases
   * Define remoteDispatchNetworkGetDHCPLeasesForMAC

src/remote/remote_driver.c
   * Define remoteNetworkGetDHCPLeases
   * Define remoteNetworkGetDHCPLeasesForMAC

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES
   * Define structs remote_network_dhcp_leases, 
remote_network_get_dhcp_leases_args,
remote_network_get_dhcp_leases_ret
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC
   * Define structs remote_network_dhcp_leases_for_mac, 
remote_network_get_dhcp_leases_for_mac_args,
remote_network_get_dhcp_leases_for_mac_ret

src/remote_protocol-structs
   * New structs added

src/rpc/gendispatch.pl
   * Add exception (s/Dhcp/DHCP) for auto-generating names of the remote 
functions
 in ./daemon/remote_dispatch.h

---
 daemon/remote.c  | 133 ++
 src/remote/remote_driver.c   | 150 +++
 src/remote/remote_protocol.x |  50 ++-
 src/remote_protocol-structs  |  32 +
 src/rpc/gendispatch.pl   |   1 +
 5 files changed, 365 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 2aff7c1..de03739 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5137,7 +5137,140 @@ cleanup:
 return rv;
 }
 
+static int
+remoteSerializeNetworkDHCPLeases(virNetworkDHCPLeasesPtr *leases,
+ int nleases,
+ remote_network_get_dhcp_leases_ret *ret)
+{
+size_t i;
+
+if (nleases  REMOTE_NETWORK_DHCPLEASES_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of leases is %d, which exceeds max limit: 
%d),
+   nleases, REMOTE_NETWORK_DHCPLEASES_MAX);
+return -1;
+}
+
+if (VIR_ALLOC_N(ret-leases.leases_val, nleases)  0)
+goto error;
+
+ret-leases.leases_len = nleases;
+
+for (i = 0; i  nleases; i++) {
+virNetworkDHCPLeasesPtr lease = leases[i];
+remote_network_dhcp_lease *lease_ret = (ret-leases.leases_val[i]);
+lease_ret-expirytime = lease-expirytime;
+lease_ret-type = lease-type;
+lease_ret-prefix = lease-prefix;
+
+if ((VIR_STRDUP(lease_ret-mac, lease-mac)  0) ||
+(VIR_STRDUP(lease_ret-ipaddr, lease-ipaddr)  0) ||
+(VIR_STRDUP(lease_ret-hostname, lease-hostname)  0) ||
+(VIR_STRDUP(lease_ret-clientid, lease-clientid)  0))
+goto error;
+}
+
+return 0;
+
+error:
+if (ret-leases.leases_val) {
+for (i = 0; i  nleases; i++) {
+remote_network_dhcp_lease *lease_ret = 
(ret-leases.leases_val[i]);
+virNetworkDHCPLeaseFree((virNetworkDHCPLeasesPtr)lease_ret);
+}
+}
+return -1;
+}
+
+static int
+remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server ATTRIBUTE_UNUSED,
+   virNetServerClientPtr client,
+   virNetMessagePtr msg ATTRIBUTE_UNUSED,
+   virNetMessageErrorPtr rerr,
+   remote_network_get_dhcp_leases_args *args,
+   remote_network_get_dhcp_leases_ret *ret)
+{
+int rv = -1;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virNetworkDHCPLeasesPtr *leases = NULL;
+virNetworkPtr net = NULL;
+int nleases = 0;
+
+if (!priv-conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open));
+goto cleanup;
+}
+
+if (!(net = get_nonnull_network(priv-conn, args-net)))
+goto cleanup;
+
+if ((nleases = virNetworkGetDHCPLeases(net, leases, args-flags))  0)
+goto cleanup;
+
+if (remoteSerializeNetworkDHCPLeases(leases, nleases, ret)  0)
+goto cleanup;
 
+rv = nleases;
+
+cleanup:
+if (rv  0)
+virNetMessageSaveError(rerr);
+if (leases) {
+size_t i;
+for (i = 0; i  nleases; i++) {
+virNetworkDHCPLeaseFree(leases[i]);
+}
+}
+VIR_FREE(leases);
+return rv;
+}
+
+static int
+remoteDispatchNetworkGetDHCPLeasesForMAC(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ 
remote_network_get_dhcp_leases_for_mac_args *args,
+ 
remote_network_get_dhcp_leases_for_mac_ret *ret)
+{
+int rv = -1;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+

[libvirt] [PATCHv2 1/4] net-dhcp-leases: Implement the public APIs

2013-09-12 Thread Nehal J Wani
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC
and virNetworkDHCPLeaseFree.

* virNetworkGetDHCPLeases: returns the dhcp leases information for a given
 virtual network. The information includes lease expirytime, MAC Address,
 IP Address, hostname and clientid.

* virNetworkGetDHCPLeasesForMAC: returns the dhcp leases information for a
 given virtual network and specified MAC Address.

* virNetworkDHCPLeaseFree: allows the upper layer application to free the
 network interface object conveniently.

There is no support for flags, so user is expected to pass 0 for
both the APIs.

include/libvirt/libvirt.h.in:
  * Define virNetworkGetDHCPLeases
  * Define virNetworkGetDHCPLeasesForMAC
  * Define virNetworkDHCPLeaseFree

python/generator.py:
  * Skip the auto-generation for virNetworkGetDHCPLeases
  * Skip the auto-generation for virNetworkGetDHCPLeasesForMAC
  * Skip the auto-generation for virNetworkDHCPLeaseFree

src/driver.h:
  * Define networkGetDHCPLeases
  * Define networkGetDHCPLeasesForMAC

src/libvirt.c:
  * Implement virNetworkGetDHCPLeases
  * Implement virNetworkGetDHCPLeasesForMAC
  * Implement virNetworkDHCPLeaseFree

src/libvirt_public.syms:
  * Export the new symbols

src/libvirt_private.syms:
  * Export the symbol: virSocketAddrGetNumNetmaskBits

---
 include/libvirt/libvirt.h.in |  33 +
 python/generator.py  |   3 +
 src/driver.h |  13 
 src/libvirt.c| 173 +++
 src/libvirt_private.syms |   1 +
 src/libvirt_public.syms  |   7 ++
 6 files changed, 230 insertions(+)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..d92a720 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2800,6 +2800,39 @@ int virConnectNumOfDefinedInterfaces 
(virConnectPtr conn);
 int virConnectListDefinedInterfaces  (virConnectPtr conn,
   char **const names,
   int maxnames);
+
+typedef enum {
+VIR_IP_ADDR_TYPE_IPV4,
+VIR_IP_ADDR_TYPE_IPV6,
+
+#ifdef VIR_ENUM_SENTINELS
+VIR_IP_ADDR_TYPE_LAST
+#endif
+} virIPAddrType;
+
+typedef struct _virNetworkDHCPLeases virNetworkDHCPLeases;
+typedef virNetworkDHCPLeases *virNetworkDHCPLeasesPtr;
+struct _virNetworkDHCPLeases {
+long long expirytime;
+char *mac;  /* MAC address */
+char *ipaddr;   /* IP address */
+char *hostname; /* Hostname */
+char *clientid; /* Client ID */
+int type;   /* virIPAddrType */
+unsigned int prefix;/* IP address prefix */
+};
+
+void virNetworkDHCPLeaseFree(virNetworkDHCPLeasesPtr lease);
+
+int virNetworkGetDHCPLeases(virNetworkPtr network,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
+int virNetworkGetDHCPLeasesForMAC(virNetworkPtr network,
+  const char *mac,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
 /*
  * virConnectListAllInterfaces:
  *
diff --git a/python/generator.py b/python/generator.py
index a91dde8..e76cbfc 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -460,6 +460,8 @@ skip_impl = (
 'virNodeGetCPUMap',
 'virDomainMigrate3',
 'virDomainMigrateToURI3',
+'virNetworkGetDHCPLeases',
+'virNetworkGetDHCPLeasesForMAC',
 )
 
 lxc_skip_impl = (
@@ -560,6 +562,7 @@ skip_function = (
 virTypedParamsGetString,
 virTypedParamsGetUInt,
 virTypedParamsGetULLong,
+'virNetworkDHCPLeaseFree',
 )
 
 lxc_skip_function = (
diff --git a/src/driver.h b/src/driver.h
index be64333..698e0ca 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1121,6 +1121,17 @@ typedef int
  int cookieinlen,
  unsigned int flags,
  int cancelled);
+typedef int
+(*virDrvNetworkGetDHCPLeases)(virNetworkPtr network,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
+typedef int
+(*virDrvNetworkGetDHCPLeasesForMAC)(virNetworkPtr network,
+const char *mac,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
 
 typedef struct _virDriver virDriver;
 typedef virDriver *virDriverPtr;
@@ -1451,6 +1462,8 @@ struct _virNetworkDriver {
 virDrvNetworkSetAutostart networkSetAutostart;
 virDrvNetworkIsActive networkIsActive;
 virDrvNetworkIsPersistent networkIsPersistent;
+virDrvNetworkGetDHCPLeases networkGetDHCPLeases;
+virDrvNetworkGetDHCPLeasesForMAC networkGetDHCPLeasesForMAC;
 };
 

[libvirt] [PATCHv2 4/4] net-dhcp-leases: Add virsh support

2013-09-12 Thread Nehal J Wani
Use virNetworkGetDHCPLeases and virNetworkGetDHCPLeasesForMAC in virsh.

The new feature supports the follwing methods:

1. Retrieve leases info for a given virtual network

2. Retrieve leases info for given network interface

tools/virsh-domain-monitor.c
   * Introduce new command : net-dhcp-leases
 Example Usage: net-dhcp-leases network [mac]

 virsh # net-dhcp-leases default

 Expiry Time  MAC address  Protocol   IP address   
Hostname ClientId
 

 13-09-2013 03:45:31  52:54:00:20:70:3dipv4   192.168.105.240/24
f18  *
 13-09-2013 03:32:31  52:54:00:b1:70:19ipv4   192.168.105.201/24
LDAP *

tools/virsh.pod
   * Document new command

---
 tools/virsh-network.c | 101 ++
 tools/virsh.pod   |   6 +++
 2 files changed, 107 insertions(+)

diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 8ddd5ca..571bf2e 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -1129,6 +1129,101 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd)
 
 return ret;
 }
+/*
+ * net-dhcp-leases command
+ */
+static const vshCmdInfo info_network_dhcp_leases[] = {
+{.name = help,
+ .data = N_(Print lease info for a given network)
+},
+{.name = desc,
+ .data = N_(Print lease info for a given network)
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_dhcp_leases[] = {
+{.name = network,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_(network name or uuid)
+},
+{.name = mac,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_NONE,
+ .help = N_(MAC address)
+},
+{.name = NULL}
+};
+
+static bool
+cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd)
+{
+const char *name = NULL;
+const char *mac = NULL;
+virNetworkDHCPLeasesPtr *leases = NULL;
+int nleases = 0;
+bool ret = false;
+size_t i;
+unsigned int flags = 0;
+virNetworkPtr network = NULL;
+
+if (vshCommandOptString(cmd, mac, mac)  0)
+goto cleanup;
+
+if (!(network = vshCommandOptNetworkBy(ctl, cmd, name,
+   VSH_BYNAME | VSH_BYUUID)))
+goto cleanup;
+
+nleases = mac ? virNetworkGetDHCPLeasesForMAC(network, mac, leases, flags)
+:virNetworkGetDHCPLeases(network, leases, flags);
+
+if (nleases  0) {
+vshError(ctl, _(Failed to get leases info for %s), name);
+goto cleanup;
+}
+
+vshPrintExtra(ctl,  %-20s %-20s %-10s %-20s %-12s %s\n%s%s\n,
+  _(Expiry Time), _(MAC address), _(Protocol),
+  _(IP address), _(Hostname), _(ClientId),
+  ,
+  );
+
+for (i = 0; i  nleases; i++) {
+const char *type = NULL;
+virNetworkDHCPLeasesPtr lease = leases[i];
+time_t expirytime_tmp = lease-expirytime;
+struct tm ts;
+char expirytime[32];
+ts = *localtime_r(expirytime_tmp, ts);
+strftime(expirytime, sizeof(expirytime), %d-%m-%Y %H:%M:%S, ts);
+
+switch (lease-type) {
+case VIR_IP_ADDR_TYPE_IPV4:
+type = ipv4;
+break;
+case VIR_IP_ADDR_TYPE_IPV6:
+type = ipv6;
+break;
+}
+
+vshPrintExtra(ctl,  %-20s %-20s %-10s %s/%-5d %-12s %s\n,
+  expirytime, lease-mac, type, lease-ipaddr,
+  lease-prefix, lease-hostname, lease-clientid);
+}
+
+ret = true;
+
+cleanup:
+if (leases) {
+for (i = 0; i  nleases; i++)
+virNetworkDHCPLeaseFree(leases[i]);
+}
+VIR_FREE(leases);
+if (network)
+virNetworkFree(network);
+return ret;
+}
 
 const vshCmdDef networkCmds[] = {
 {.name = net-autostart,
@@ -1209,5 +1304,11 @@ const vshCmdDef networkCmds[] = {
  .info = info_network_uuid,
  .flags = 0
 },
+{.name = net-dhcp-leases,
+ .handler = cmdNetworkDHCPLeases,
+ .opts = opts_network_dhcp_leases,
+ .info = info_network_dhcp_leases,
+ .flags = 0
+},
 {.name = NULL}
 };
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0ae5178..b87f646 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2325,6 +2325,12 @@ If I--current is specified, affect the current network 
state.
 Both I--live and I--config flags may be given, but I--current is
 exclusive. Not specifying any flag is the same as specifying I--current.
 
+=item Bnet-dhcp-leases Inetwork Imac
+
+Get a list of dhcp leases for all network interfaces connected to the given
+virtual Inetwork or limited output just for one interface if Imac is
+specified.
+
 =back
 
 =head1 INTERFACE COMMANDS
-- 
1.7.11.7

--
libvir-list mailing list

[libvirt] [PATCHv2 0/4] Introduce APIs to extract DHCP leases info

2013-09-12 Thread Nehal J Wani
This API returns the information stored in the DHCP leases file
created by dnsmasq for a given virtual network. It contacts the
bridge network driver, which parses the leases file.

It supports two methods:

1. Return info for all network interfaces connected to a given
   virtual network
2. Return information for a particular network interface in a
   given virtual network by providing its MAC Address

v2
* Since DHCPv6 is supposed to be suported in future, 
virNetworkGetDHCPLeasesForMAC
  changed, prefix and virIPAddrType added in virNetworkDHCPLeases struct.

v1
* Refer: 
https://www.redhat.com/archives/libvir-list/2013-September/msg00620.html

* The need for these APIs were result of a RFC was proposed on the list.
  Refer: http://www.redhat.com/archives/libvir-list/2013-July/msg01603.html

Nehal J Wani (4):
  net-dhcp-leases: Implement the public APIs
  net-dhcp-leases: Implement the remote protocol
  net-dhcp-leases: Private implementation inside network driver
  net-dhcp-leases: Add virsh support

 daemon/remote.c  | 133 +
 include/libvirt/libvirt.h.in |  33 
 python/generator.py  |   3 +
 src/driver.h |  13 +++
 src/libvirt.c| 173 ++
 src/libvirt_private.syms |   1 +
 src/libvirt_public.syms  |   7 ++
 src/network/bridge_driver.c  | 193 +++
 src/remote/remote_driver.c   | 150 +
 src/remote/remote_protocol.x |  50 ++-
 src/remote_protocol-structs  |  32 +++
 src/rpc/gendispatch.pl   |   1 +
 tools/virsh-network.c| 101 ++
 tools/virsh.pod  |   6 ++
 14 files changed, 895 insertions(+), 1 deletion(-)

-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCHv2 3/4] net-dhcp-leases: Private implementation inside network driver

2013-09-13 Thread Nehal J Wani
Just realized that obj should be non-null. Small diff to fix this:

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 2cdea56..3e93893 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -3020,7 +3020,8 @@ networkGetDHCPLeases(virNetworkPtr network,

 virCheckFlags(0, -1);

-obj = networkObjFromNetwork(network);
+if (!(obj = networkObjFromNetwork(network)))
+return rv;

 if (virNetworkGetDHCPLeasesEnsureACL(network-conn, obj-def)  0)
 goto cleanup;
@@ -3044,7 +3045,8 @@ networkGetDHCPLeasesForMAC(virNetworkPtr network,

 virCheckFlags(0, -1);

-obj = networkObjFromNetwork(network);
+if (!(obj = networkObjFromNetwork(network)))
+return rv;

 if (virNetworkGetDHCPLeasesForMACEnsureACL(network-conn, obj-def) 
0)
 goto cleanup;


3.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCHv2 3/4] net-dhcp-leases: Private implementation inside network driver

2013-09-13 Thread Nehal J Wani
By querying the driver for the path of the leases file for the given virtual
network and parsing it to retrieve info.

src/network/bridge_driver.c:
  * Implement networkGetDHCPLeases
  * Implement networkGetDHCPLeasesForMAC
  * Implement networkGetDHCPLeasesHelper

---
 src/network/bridge_driver.c | 193 
 1 file changed, 193 insertions(+)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 3a8be90..2cdea56 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -109,6 +109,36 @@ static int networkPlugBandwidth(virNetworkObjPtr net,
 virDomainNetDefPtr iface);
 static int networkUnplugBandwidth(virNetworkObjPtr net,
   virDomainNetDefPtr iface);
+/**
+ * VIR_NETWORK_DHCPLEASE_LENGTH_MAX:
+ *
+ * Macro providing the maximum length of an entry in the leases file
+ * Refer: 
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2013q3/007402.html
+ */
+#define VIR_NETWORK_DHCPLEASE_LENGTH_MAX 2048
+
+/**
+ * VIR_NETWORK_DHCPLEASE_PARAMS:
+ *
+ * Macro providing the maximum number of parameters in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCPLEASE_FIELDS 5
+
+static int networkGetDHCPLeases(virNetworkPtr network,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
+static int networkGetDHCPLeasesForMAC(virNetworkPtr network,
+  const char *mac,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
+static int networkGetDHCPLeasesHelper(virNetworkPtr network,
+  virNetworkObjPtr obj,
+  const char *mac,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
 
 static virNetworkDriverStatePtr driverState = NULL;
 
@@ -2980,6 +3010,167 @@ cleanup:
 return ret;
 }
 
+static int
+networkGetDHCPLeases(virNetworkPtr network,
+ virNetworkDHCPLeasesPtr **leases,
+ unsigned int flags)
+{
+int rv = -1;
+virNetworkObjPtr obj;
+
+virCheckFlags(0, -1);
+
+obj = networkObjFromNetwork(network);
+
+if (virNetworkGetDHCPLeasesEnsureACL(network-conn, obj-def)  0)
+goto cleanup;
+
+rv = networkGetDHCPLeasesHelper(network, obj, NULL, leases, flags);
+
+cleanup:
+if (obj)
+virNetworkObjUnlock(obj);
+return rv;
+}
+
+static int
+networkGetDHCPLeasesForMAC(virNetworkPtr network,
+   const char *mac,
+   virNetworkDHCPLeasesPtr **leases,
+   unsigned int flags)
+{
+int rv = -1;
+virNetworkObjPtr obj;
+
+virCheckFlags(0, -1);
+
+obj = networkObjFromNetwork(network);
+
+if (virNetworkGetDHCPLeasesForMACEnsureACL(network-conn, obj-def)  0)
+goto cleanup;
+
+rv = networkGetDHCPLeasesHelper(network, obj, mac, leases, flags);
+
+cleanup:
+if (obj)
+virNetworkObjUnlock(obj);
+return rv;
+}
+
+/* This function parese the leases file generated by dnsmasq.
+ * Example content:
+ * ::
+ * /var/lib/libvirt/dnsmasq/TestNetwork1.leases
+ * ::
+ * 1379024255 52:54:00:20:70:3d 192.168.105.240 * *
+ * 1379023351 52:54:00:b1:70:19 192.168.105.201 * *
+ */
+static int
+networkGetDHCPLeasesHelper(virNetworkPtr network,
+   virNetworkObjPtr obj,
+   const char *mac,
+   virNetworkDHCPLeasesPtr **leases,
+   unsigned int flags)
+{
+int rv = -1;
+size_t i = 0;
+char *leasefile;
+FILE *fp = NULL;
+size_t nleases = 0;
+char **leaseparams;
+virNetworkDHCPLeasesPtr *leases_ret = NULL;
+char dhcpentry[VIR_NETWORK_DHCPLEASE_LENGTH_MAX];
+
+virCheckFlags(0, -1);
+
+if (!network) {
+virReportError(VIR_ERR_NO_NETWORK, %s,
+   _(no network with matching name));
+return -1;
+}
+
+/* Retrive leases file location */
+leasefile = networkDnsmasqLeaseFileNameDefault(network-name);
+if (!(fp = fopen(leasefile, r))) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Unable to open leases file: %s), leasefile);
+goto error;
+}
+
+while (fgets(dhcpentry, sizeof(dhcpentry), fp) != NULL) {
+virNetworkDHCPLeasesPtr lease = NULL;
+
+/* Remove newline */
+dhcpentry[strlen(dhcpentry) - 1] = '\0';
+
+/* split the lease line */
+leaseparams = virStringSplit(dhcpentry,  , 
VIR_NETWORK_DHCPLEASE_FIELDS);
+
+if (virStringListLength(leaseparams) != VIR_NETWORK_DHCPLEASE_FIELDS) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of lease 

[libvirt] [PATCHv3 0/4] Introduce APIs to extract DHCP leases info

2013-09-15 Thread Nehal J Wani
This API returns the leases information stored in the DHCP leases
file of dnsmasq for a given virtual network. It contacts the
bridge network driver, which parses the leases file.

It supports two methods:

1. Return info for all network interfaces connected to a given
   virtual network
2. Return information for a particular network interface in a
   given virtual network by providing its MAC Address

v3
* Mostly small nits, change in MACRO names, use of virSocketAddrGetIpPrefix to
  retrieve IP prefix from @dom XML.

v2
* Since DHCPv6 is supposed to be suported in future, 
virNetworkGetDHCPLeasesForMAC
  changed, prefix and virIPAddrType added in virNetworkDHCPLeases struct.
  Refer: 
https://www.redhat.com/archives/libvir-list/2013-September/msg00732.html

v1
* Refer: 
https://www.redhat.com/archives/libvir-list/2013-September/msg00620.html

* The need for these APIs were result of a RFC was proposed on the list.
  Refer: http://www.redhat.com/archives/libvir-list/2013-July/msg01603.html

Nehal J Wani (4):
  net-dhcp-leases: Implement the public APIs
  net-dhcp-leases: Implement the remote protocol
  net-dhcp-leases: Private implementation inside network driver
  net-dhcp-leases: Add virsh support

 daemon/remote.c  | 133 
 include/libvirt/libvirt.h.in |  33 
 python/generator.py  |   3 +
 src/driver.h |  13 
 src/libvirt.c| 173 ++
 src/libvirt_public.syms  |   7 ++
 src/network/bridge_driver.c  | 177 +++
 src/remote/remote_driver.c   | 150 
 src/remote/remote_protocol.x |  50 +++-
 src/remote_protocol-structs  |  32 
 src/rpc/gendispatch.pl   |   1 +
 tools/virsh-network.c| 100 
 tools/virsh.pod  |   6 ++
 13 files changed, 877 insertions(+), 1 deletion(-)

-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv3 1/4] net-dhcp-leases: Implement the public APIs

2013-09-15 Thread Nehal J Wani
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC
and virNetworkDHCPLeaseFree.

* virNetworkGetDHCPLeases: returns the dhcp leases information for a given
 virtual network. The information includes lease expirytime, MAC Address,
 IP Address (with type and prefix), hostname and clientid.

* virNetworkGetDHCPLeasesForMAC: returns the dhcp leases information for a
 given virtual network and specified MAC Address.

* virNetworkDHCPLeaseFree: allows the upper layer application to free the
 network interface object conveniently.

There is no support for flags, so user is expected to pass 0 for
both the APIs.

include/libvirt/libvirt.h.in:
  * Define virNetworkGetDHCPLeases
  * Define virNetworkGetDHCPLeasesForMAC
  * Define virNetworkDHCPLeaseFree

python/generator.py:
  * Skip the auto-generation for virNetworkGetDHCPLeases
  * Skip the auto-generation for virNetworkGetDHCPLeasesForMAC
  * Skip the auto-generation for virNetworkDHCPLeaseFree

src/driver.h:
  * Define networkGetDHCPLeases
  * Define networkGetDHCPLeasesForMAC

src/libvirt.c:
  * Implement virNetworkGetDHCPLeases
  * Implement virNetworkGetDHCPLeasesForMAC
  * Implement virNetworkDHCPLeaseFree

src/libvirt_public.syms:
  * Export the new symbols

---
 include/libvirt/libvirt.h.in |  33 +
 python/generator.py  |   3 +
 src/driver.h |  13 
 src/libvirt.c| 173 +++
 src/libvirt_public.syms  |   7 ++
 5 files changed, 229 insertions(+)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..d92a720 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2800,6 +2800,39 @@ int virConnectNumOfDefinedInterfaces 
(virConnectPtr conn);
 int virConnectListDefinedInterfaces  (virConnectPtr conn,
   char **const names,
   int maxnames);
+
+typedef enum {
+VIR_IP_ADDR_TYPE_IPV4,
+VIR_IP_ADDR_TYPE_IPV6,
+
+#ifdef VIR_ENUM_SENTINELS
+VIR_IP_ADDR_TYPE_LAST
+#endif
+} virIPAddrType;
+
+typedef struct _virNetworkDHCPLeases virNetworkDHCPLeases;
+typedef virNetworkDHCPLeases *virNetworkDHCPLeasesPtr;
+struct _virNetworkDHCPLeases {
+long long expirytime;
+char *mac;  /* MAC address */
+char *ipaddr;   /* IP address */
+char *hostname; /* Hostname */
+char *clientid; /* Client ID */
+int type;   /* virIPAddrType */
+unsigned int prefix;/* IP address prefix */
+};
+
+void virNetworkDHCPLeaseFree(virNetworkDHCPLeasesPtr lease);
+
+int virNetworkGetDHCPLeases(virNetworkPtr network,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
+int virNetworkGetDHCPLeasesForMAC(virNetworkPtr network,
+  const char *mac,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
 /*
  * virConnectListAllInterfaces:
  *
diff --git a/python/generator.py b/python/generator.py
index a91dde8..e76cbfc 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -460,6 +460,8 @@ skip_impl = (
 'virNodeGetCPUMap',
 'virDomainMigrate3',
 'virDomainMigrateToURI3',
+'virNetworkGetDHCPLeases',
+'virNetworkGetDHCPLeasesForMAC',
 )
 
 lxc_skip_impl = (
@@ -560,6 +562,7 @@ skip_function = (
 virTypedParamsGetString,
 virTypedParamsGetUInt,
 virTypedParamsGetULLong,
+'virNetworkDHCPLeaseFree',
 )
 
 lxc_skip_function = (
diff --git a/src/driver.h b/src/driver.h
index be64333..698e0ca 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1121,6 +1121,17 @@ typedef int
  int cookieinlen,
  unsigned int flags,
  int cancelled);
+typedef int
+(*virDrvNetworkGetDHCPLeases)(virNetworkPtr network,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
+typedef int
+(*virDrvNetworkGetDHCPLeasesForMAC)(virNetworkPtr network,
+const char *mac,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
 
 typedef struct _virDriver virDriver;
 typedef virDriver *virDriverPtr;
@@ -1451,6 +1462,8 @@ struct _virNetworkDriver {
 virDrvNetworkSetAutostart networkSetAutostart;
 virDrvNetworkIsActive networkIsActive;
 virDrvNetworkIsPersistent networkIsPersistent;
+virDrvNetworkGetDHCPLeases networkGetDHCPLeases;
+virDrvNetworkGetDHCPLeasesForMAC networkGetDHCPLeasesForMAC;
 };
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
index a6fcab0..05d20e9 100644
--- a/src/libvirt.c

[libvirt] [PATCHv3 3/4] net-dhcp-leases: Private implementation inside network driver

2013-09-15 Thread Nehal J Wani
By querying the driver for the path of the leases file for the given virtual
network and parsing it to retrieve info.

src/network/bridge_driver.c:
  * Implement networkGetDHCPLeases
  * Implement networkGetDHCPLeasesForMAC
  * Implement networkGetDHCPLeasesHelper

---
 src/network/bridge_driver.c | 177 
 1 file changed, 177 insertions(+)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 3a8be90..f5adb97 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -109,6 +109,21 @@ static int networkPlugBandwidth(virNetworkObjPtr net,
 virDomainNetDefPtr iface);
 static int networkUnplugBandwidth(virNetworkObjPtr net,
   virDomainNetDefPtr iface);
+/**
+ * VIR_NETWORK_DHCP_LEASE_LENGTH_MAX:
+ *
+ * Macro providing the maximum length of an entry in the leases file
+ * Refer: 
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2013q3/007402.html
+ */
+#define VIR_NETWORK_DHCP_LEASE_LENGTH_MAX 2048
+
+/**
+ * VIR_NETWORK_DHCPLEASE_PARAMS:
+ *
+ * Macro providing the maximum number of parameters in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FIELDS 5
 
 static virNetworkDriverStatePtr driverState = NULL;
 
@@ -2980,6 +2995,166 @@ cleanup:
 return ret;
 }
 
+/* This function parese the leases file of dnsmasq.
+ *
+ * An example of leases file content:
+ *
+ * 1379024255 52:54:00:20:70:3d 192.168.105.240 * *
+ * 1379023351 52:54:00:b1:70:19 192.168.105.201 * *
+ */
+static int
+networkGetDHCPLeasesHelper(virNetworkPtr network,
+   virNetworkObjPtr obj,
+   const char *mac,
+   virNetworkDHCPLeasesPtr **leases)
+{
+int rv = -1;
+size_t i = 0;
+size_t nleases = 0;
+char *leasefile;
+char **lease_fields;
+char dhcpentry[VIR_NETWORK_DHCP_LEASE_LENGTH_MAX];
+virNetworkDHCPLeasesPtr *leases_ret = NULL;
+FILE *fp = NULL;
+
+if (!network) {
+virReportError(VIR_ERR_NO_NETWORK, %s,
+   _(no network with matching name));
+return -1;
+}
+
+/* Retrieve leases file location */
+leasefile = networkDnsmasqLeaseFileNameDefault(network-name);
+if (!(fp = fopen(leasefile, r))) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Unable to open leases file: %s), leasefile);
+goto cleanup;
+}
+
+while (fgets(dhcpentry, sizeof(dhcpentry), fp) != NULL) {
+virNetworkDHCPLeasesPtr lease = NULL;
+
+/* Remove newline */
+dhcpentry[strlen(dhcpentry) - 1] = '\0';
+
+/* Split the lease line */
+lease_fields = virStringSplit(dhcpentry,  , 
VIR_NETWORK_DHCP_LEASE_FIELDS);
+
+if (virStringListLength(lease_fields) != 
VIR_NETWORK_DHCP_LEASE_FIELDS) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of lease params aren't equal to: %d),
+   VIR_NETWORK_DHCP_LEASE_FIELDS);
+goto error;
+}
+
+if (mac  STRNEQ(mac, lease_fields[1]))
+continue;
+
+if (VIR_EXPAND_N(leases_ret, nleases, 1)  0)
+goto error;
+
+if (VIR_ALLOC(leases_ret[nleases - 1])  0)
+goto error;
+
+lease = leases_ret[nleases - 1];
+
+/* Convert expirytime here */
+if (virStrToLong_ll(lease_fields[0], NULL, 10, (lease-expirytime))  
0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Unable to convert lease expiry time to integer: 
%s),
+   lease_fields[0]);
+goto error;
+}
+
+/* Hardcoded, as dnsmasq uses ipv4 */
+lease-type = VIR_IP_ADDR_TYPE_IPV4;
+lease-prefix = virSocketAddrGetIpPrefix(obj-def-ips-address,
+ obj-def-ips-netmask,
+ obj-def-ips-prefix);
+
+if ((VIR_STRDUP(lease-mac, lease_fields[1])  0) ||
+(VIR_STRDUP(lease-ipaddr, lease_fields[2])  0) ||
+(VIR_STRDUP(lease-hostname, lease_fields[3])  0) ||
+(VIR_STRDUP(lease-clientid, lease_fields[4])  0))
+goto error;
+}
+
+if (mac  !leases_ret) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(no lease with matching MAC address: %s), mac);
+goto error;
+}
+
+if (leases_ret) {
+/* NULL terminated array */
+ignore_value(VIR_REALLOC_N(leases_ret, nleases + 1));
+*leases = leases_ret;
+leases_ret = NULL;
+rv = nleases;
+}
+
+cleanup:
+VIR_FORCE_FCLOSE(fp);
+VIR_FREE(leasefile);
+return rv;
+
+error:
+if (leases_ret) {
+for (i = 0; i  nleases; i++)
+virNetworkDHCPLeaseFree(leases_ret[i]);
+}
+VIR_FREE(leases_ret);
+goto cleanup;
+}
+
+static int

[libvirt] [PATCHv3 2/4] net-dhcp-leases: Implement the remote protocol

2013-09-15 Thread Nehal J Wani
Implement RPC calls for virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC

daemon/remote.c
   * Define remoteSerializeNetworkDHCPLeases,
remoteDispatchNetworkGetDHCPLeases
   * Define remoteDispatchNetworkGetDHCPLeasesForMAC

src/remote/remote_driver.c
   * Define remoteNetworkGetDHCPLeases
   * Define remoteNetworkGetDHCPLeasesForMAC

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES
   * Define structs remote_network_dhcp_leases, 
remote_network_get_dhcp_leases_args,
remote_network_get_dhcp_leases_ret
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC
   * Define structs remote_network_dhcp_leases_for_mac, 
remote_network_get_dhcp_leases_for_mac_args,
remote_network_get_dhcp_leases_for_mac_ret

src/remote_protocol-structs
   * New structs added

src/rpc/gendispatch.pl
   * Add exception (s/Dhcp/DHCP) for auto-generating names of the remote 
functions
 in daemon/remote_dispatch.h

---
 daemon/remote.c  | 133 ++
 src/remote/remote_driver.c   | 150 +++
 src/remote/remote_protocol.x |  50 ++-
 src/remote_protocol-structs  |  32 +
 src/rpc/gendispatch.pl   |   1 +
 5 files changed, 365 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 2aff7c1..5252893 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5137,7 +5137,140 @@ cleanup:
 return rv;
 }
 
+static int
+remoteSerializeNetworkDHCPLeases(virNetworkDHCPLeasesPtr *leases,
+ int nleases,
+ remote_network_get_dhcp_leases_ret *ret)
+{
+size_t i;
+
+if (nleases  REMOTE_NETWORK_DHCP_LEASES_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of leases is %d, which exceeds max limit: 
%d),
+   nleases, REMOTE_NETWORK_DHCP_LEASES_MAX);
+return -1;
+}
+
+if (VIR_ALLOC_N(ret-leases.leases_val, nleases)  0)
+return -1;
+
+ret-leases.leases_len = nleases;
+
+for (i = 0; i  nleases; i++) {
+virNetworkDHCPLeasesPtr lease = leases[i];
+remote_network_dhcp_lease *lease_ret = (ret-leases.leases_val[i]);
+lease_ret-expirytime = lease-expirytime;
+lease_ret-type = lease-type;
+lease_ret-prefix = lease-prefix;
+
+if ((VIR_STRDUP(lease_ret-mac, lease-mac)  0) ||
+(VIR_STRDUP(lease_ret-ipaddr, lease-ipaddr)  0) ||
+(VIR_STRDUP(lease_ret-hostname, lease-hostname)  0) ||
+(VIR_STRDUP(lease_ret-clientid, lease-clientid)  0))
+goto error;
+}
+
+return 0;
+
+error:
+for (i = 0; i  nleases; i++) {
+remote_network_dhcp_lease *lease_ret = (ret-leases.leases_val[i]);
+virNetworkDHCPLeaseFree((virNetworkDHCPLeasesPtr)lease_ret);
+}
+return -1;
+}
+
+static int
+remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server ATTRIBUTE_UNUSED,
+   virNetServerClientPtr client,
+   virNetMessagePtr msg ATTRIBUTE_UNUSED,
+   virNetMessageErrorPtr rerr,
+   remote_network_get_dhcp_leases_args *args,
+   remote_network_get_dhcp_leases_ret *ret)
+{
+int rv = -1;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virNetworkDHCPLeasesPtr *leases = NULL;
+virNetworkPtr net = NULL;
+int nleases = 0;
+
+if (!priv-conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open));
+goto cleanup;
+}
+
+if (!(net = get_nonnull_network(priv-conn, args-net)))
+goto cleanup;
+
+if ((nleases = virNetworkGetDHCPLeases(net, leases, args-flags))  0)
+goto cleanup;
+
+if (remoteSerializeNetworkDHCPLeases(leases, nleases, ret)  0)
+goto cleanup;
 
+rv = nleases;
+
+cleanup:
+if (rv  0)
+virNetMessageSaveError(rerr);
+if (leases) {
+size_t i;
+for (i = 0; i  nleases; i++) {
+virNetworkDHCPLeaseFree(leases[i]);
+}
+}
+VIR_FREE(leases);
+virNetworkFree(net);
+return rv;
+}
+
+static int
+remoteDispatchNetworkGetDHCPLeasesForMAC(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ 
remote_network_get_dhcp_leases_for_mac_args *args,
+ 
remote_network_get_dhcp_leases_for_mac_ret *ret)
+{
+int rv = -1;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virNetworkDHCPLeasesPtr *leases = NULL;
+

[libvirt] [PATCHv3 4/4] net-dhcp-leases: Add virsh support

2013-09-15 Thread Nehal J Wani
Use virNetworkGetDHCPLeases and virNetworkGetDHCPLeasesForMAC in virsh.

The new feature supports the follwing methods:

1. Retrieve leases info for a given virtual network

2. Retrieve leases info for given network interface

tools/virsh-domain-monitor.c
   * Introduce new command : net-dhcp-leases
 Example Usage: net-dhcp-leases network [mac]

 virsh # net-dhcp-leases default

 Expiry Time  MAC address  Protocol   IP address   
Hostname ClientId
 

 13-09-2013 03:45:31  52:54:00:20:70:3dipv4   192.168.105.240/24
f18  *
 13-09-2013 03:32:31  52:54:00:b1:70:19ipv4   192.168.105.201/24
LDAP *

tools/virsh.pod
   * Document new command

---
 tools/virsh-network.c | 100 ++
 tools/virsh.pod   |   6 +++
 2 files changed, 106 insertions(+)

diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 8ddd5ca..9543c64 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -1129,6 +1129,100 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd)
 
 return ret;
 }
+/*
+ * net-dhcp-leases command
+ */
+static const vshCmdInfo info_network_dhcp_leases[] = {
+{.name = help,
+ .data = N_(Print lease info for a given network)
+},
+{.name = desc,
+ .data = N_(Print lease info for a given network)
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_dhcp_leases[] = {
+{.name = network,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_(network name or uuid)
+},
+{.name = mac,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_NONE,
+ .help = N_(MAC address)
+},
+{.name = NULL}
+};
+
+static bool
+cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd)
+{
+const char *name = NULL;
+const char *mac = NULL;
+virNetworkDHCPLeasesPtr *leases = NULL;
+int nleases = 0;
+bool ret = false;
+size_t i;
+unsigned int flags = 0;
+virNetworkPtr network = NULL;
+
+if (vshCommandOptString(cmd, mac, mac)  0)
+return false;
+
+if (!(network = vshCommandOptNetworkBy(ctl, cmd, name,
+   VSH_BYNAME | VSH_BYUUID)))
+return false;
+
+nleases = mac ? virNetworkGetDHCPLeasesForMAC(network, mac, leases, flags)
+: virNetworkGetDHCPLeases(network, leases, flags);
+
+if (nleases  0) {
+vshError(ctl, _(Failed to get leases info for %s), name);
+goto cleanup;
+}
+
+vshPrintExtra(ctl,  %-20s %-20s %-10s %-20s %-12s %s\n%s%s\n,
+  _(Expiry Time), _(MAC address), _(Protocol),
+  _(IP address), _(Hostname), _(ClientId),
+  ,
+  );
+
+for (i = 0; i  nleases; i++) {
+const char *type = NULL;
+virNetworkDHCPLeasesPtr lease = leases[i];
+time_t expirytime_tmp = lease-expirytime;
+struct tm ts;
+char expirytime[32];
+ts = *localtime_r(expirytime_tmp, ts);
+strftime(expirytime, sizeof(expirytime), %d-%m-%Y %H:%M:%S, ts);
+
+switch (lease-type) {
+case VIR_IP_ADDR_TYPE_IPV4:
+type = ipv4;
+break;
+case VIR_IP_ADDR_TYPE_IPV6:
+type = ipv6;
+break;
+}
+
+vshPrintExtra(ctl,  %-20s %-20s %-10s %s/%-5d %-12s %s\n,
+  expirytime, lease-mac, type, lease-ipaddr,
+  lease-prefix, lease-hostname, lease-clientid);
+}
+
+ret = true;
+
+cleanup:
+if (leases) {
+for (i = 0; i  nleases; i++)
+virNetworkDHCPLeaseFree(leases[i]);
+}
+VIR_FREE(leases);
+virNetworkFree(network);
+return ret;
+}
 
 const vshCmdDef networkCmds[] = {
 {.name = net-autostart,
@@ -1209,5 +1303,11 @@ const vshCmdDef networkCmds[] = {
  .info = info_network_uuid,
  .flags = 0
 },
+{.name = net-dhcp-leases,
+ .handler = cmdNetworkDHCPLeases,
+ .opts = opts_network_dhcp_leases,
+ .info = info_network_dhcp_leases,
+ .flags = 0
+},
 {.name = NULL}
 };
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0ae5178..b87f646 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2325,6 +2325,12 @@ If I--current is specified, affect the current network 
state.
 Both I--live and I--config flags may be given, but I--current is
 exclusive. Not specifying any flag is the same as specifying I--current.
 
+=item Bnet-dhcp-leases Inetwork Imac
+
+Get a list of dhcp leases for all network interfaces connected to the given
+virtual Inetwork or limited output just for one interface if Imac is
+specified.
+
 =back
 
 =head1 INTERFACE COMMANDS
-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com

Re: [libvirt] [PATCHv3 1/4] net-dhcp-leases: Implement the public APIs

2013-09-16 Thread Nehal J Wani
On Mon, Sep 16, 2013 at 3:22 PM, Daniel P. Berrange berra...@redhat.com wrote:

 On Mon, Sep 16, 2013 at 11:19:13AM +0530, Nehal J Wani wrote:
  +int
  +virNetworkGetDHCPLeasesForMAC(virNetworkPtr network,
  +  const char *mac,
  +  virNetworkDHCPLeasesPtr **leases,
  +  unsigned int flags)
  +{
  +virConnectPtr conn;
  +virMacAddr addr;
  +
  +VIR_DEBUG(network=%p, mac=%s, leases=%p, flags=%x,
  +   network, mac, leases, flags);
  +
  +virResetLastError();
  +
  +virCheckNonNullArgGoto(network, error);
  +virCheckNonNullArgGoto(mac, error);
  +
  +if (leases)
  +*leases = NULL;
  +
  +if (!VIR_IS_CONNECTED_NETWORK(network)) {
  +virLibNetworkError(VIR_ERR_INVALID_NETWORK, __FUNCTION__);
  +virDispatchError(NULL);
  +return -1;
  +}
  +
  +/* Validate the MAC address */
  +if (mac  virMacAddrParse(mac, addr)  0) {
  +virReportInvalidArg(mac,
  +_(Given MAC Address doesn't comply 
  +  with the standard (IEEE 802) format in %s),
  +__FUNCTION__);

 Don't pass __FUNCTION__ in this error message - that is already done 
 automatically

  +goto error;
  +}

 'mac' should be a mandatory parameter here.

Attached diff should fix it.

But there are still calls to virReportInvalidArg() with __FUNCTION__
as one of its arguments in src/libvirt.c


  +
  +conn = network-conn;
  +
  +if (conn-networkDriver 
  +conn-networkDriver-networkGetDHCPLeasesForMAC) {
  +int ret;
  +ret = conn-networkDriver-networkGetDHCPLeasesForMAC(network, mac,
  +  leases, 
  flags);
  +if (ret  0)
  +goto error;
  +return ret;
  +}
  +
  +virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
  +
  +error:
  +virDispatchError(network-conn);
  +return -1;
  +}

 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 :|




-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCHv3 1/4] net-dhcp-leases: Implement the public APIs

2013-09-16 Thread Nehal J Wani
PFA: Diff

On Mon, Sep 16, 2013 at 8:44 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:
 On Mon, Sep 16, 2013 at 3:22 PM, Daniel P. Berrange berra...@redhat.com 
 wrote:

 On Mon, Sep 16, 2013 at 11:19:13AM +0530, Nehal J Wani wrote:
  +int
  +virNetworkGetDHCPLeasesForMAC(virNetworkPtr network,
  +  const char *mac,
  +  virNetworkDHCPLeasesPtr **leases,
  +  unsigned int flags)
  +{
  +virConnectPtr conn;
  +virMacAddr addr;
  +
  +VIR_DEBUG(network=%p, mac=%s, leases=%p, flags=%x,
  +   network, mac, leases, flags);
  +
  +virResetLastError();
  +
  +virCheckNonNullArgGoto(network, error);
  +virCheckNonNullArgGoto(mac, error);
  +
  +if (leases)
  +*leases = NULL;
  +
  +if (!VIR_IS_CONNECTED_NETWORK(network)) {
  +virLibNetworkError(VIR_ERR_INVALID_NETWORK, __FUNCTION__);
  +virDispatchError(NULL);
  +return -1;
  +}
  +
  +/* Validate the MAC address */
  +if (mac  virMacAddrParse(mac, addr)  0) {
  +virReportInvalidArg(mac,
  +_(Given MAC Address doesn't comply 
  +  with the standard (IEEE 802) format in 
  %s),
  +__FUNCTION__);

 Don't pass __FUNCTION__ in this error message - that is already done 
 automatically

  +goto error;
  +}

 'mac' should be a mandatory parameter here.

 Attached diff should fix it.

 But there are still calls to virReportInvalidArg() with __FUNCTION__
 as one of its arguments in src/libvirt.c


  +
  +conn = network-conn;
  +
  +if (conn-networkDriver 
  +conn-networkDriver-networkGetDHCPLeasesForMAC) {
  +int ret;
  +ret = conn-networkDriver-networkGetDHCPLeasesForMAC(network, 
  mac,
  +  leases, 
  flags);
  +if (ret  0)
  +goto error;
  +return ret;
  +}
  +
  +virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
  +
  +error:
  +virDispatchError(network-conn);
  +return -1;
  +}

 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 :|




 --
 Nehal J Wani
 UG3, BTech CS+MS(CL)
 IIIT-Hyderabad
 http://commandlinewani.blogspot.com



-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com


1.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH] Add helper program to create custom leases

2013-12-19 Thread Nehal J Wani
Introduce helper program to catch events from dnsmasq and maintain a custom
lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
interface-name.status. 

The format of each lease is:
expiry-time (epoch time) mac iaid ip-address hostname clientid

Example of custom leases file content:
1385245780 52:54:00:2f:ba:76 * 192.168.150.153 * *
1385245781 52:54:00:2f:ba:76 3127926 2001:db8:ca2:2:1::6c * 
00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 iiit-ad885e4aa1 
01:52:54:00:44:7c:d7
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 * 01:52:54:00:44:7c:d7
1385246016 52:54:00:5d:99:92 * 192.168.150.212 iiit-ad885e4aa1 
01:52:54:00:5d:99:92
1385246041 52:54:00:3b:16:e0 * 192.168.150.207 * *
1385246081 52:54:00:db:dd:98 * 192.168.150.234 * *
1385246088 52:54:00:db:dd:98 14409112 2001:db8:ca2:2:1::6d * 
00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec

---
 src/util/leaseshelper.c | 232 
 1 file changed, 232 insertions(+)
 create mode 100644 src/util/leaseshelper.c

diff --git a/src/util/leaseshelper.c b/src/util/leaseshelper.c
new file mode 100644
index 000..9ed22a6
--- /dev/null
+++ b/src/util/leaseshelper.c
@@ -0,0 +1,232 @@
+/*
+ * leasehelper.c: Helper program to create custom leases file
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * Author: Nehal J Wani nehaljw.k...@gmail.com
+ *
+ */
+
+#include config.h
+
+#include stdio.h
+#include stdlib.h
+
+#include virutil.h
+#include virthread.h
+#include virfile.h
+#include virbuffer.h
+#include virstring.h
+#include virerror.h
+#include viralloc.h
+#include configmake.h
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FIELDS:
+ *
+ * Macro providing the maximum number of fields in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FIELDS 6
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152
+
+/*
+ * Use this when passing possibly-NULL strings to printf-a-likes.
+ */
+# define EMPTY_STR(s) ((s) ? (s) : *)
+
+int
+main(int argc, char **argv) {
+
+FILE *g = fopen(/tmp/wtf, a);
+int j;
+for (j = 0; j  argc; j++)
+fprintf(g, called :: : %s, , argv[j]);
+fprintf(g, \n);
+fclose(g);
+
+/* Doesn't hurt to check */
+if (argc  4) {
+/* Refer man page of dnsmasq --dhcp-script for more details */
+fprintf(stderr, Usage: $program $action ${mac|clientid} $ip\n);
+return -1;
+}
+
+const char *program_name = argv[0];
+const char *action = argv[1];
+const char *interface = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_INTERFACE));
+const char *expirytime = 
EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_LEASE_EXPIRES));
+const char *mac = argv[2];
+const char *ip = argv[3];
+const char *iaid = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_IAID));
+const char *hostname = 
EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_SUPPLIED_HOSTNAME));
+const char *clientid = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_CLIENT_ID));
+const char *leases_str = NULL;
+char *lease_file = NULL;
+char *lease_entries = NULL;
+char *lease_entry = NULL;
+char **lease_fields = NULL;
+bool delete = false;
+bool add = false;
+int rv = -1;
+int lease_file_len = 0;
+FILE *fp = NULL;
+long long expirytime_tmp = 0;
+virBuffer buf_new_lease = VIR_BUFFER_INITIALIZER;
+virBuffer buf_all_leases = VIR_BUFFER_INITIALIZER;
+
+if (setlocale(LC_ALL, ) == NULL ||
+bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+textdomain(PACKAGE) == NULL) {
+fprintf(stderr, _(%s: initialization failed\n), program_name);
+exit(EXIT_FAILURE);
+}
+
+if (virThreadInitialize()  0 ||
+virErrorInitialize()  0) {
+fprintf(stderr, _(%s: initialization failed\n), program_name);
+exit(EXIT_FAILURE);
+}
+
+if (virAsprintf(lease_file, %s/%s.status, LOCALSTATEDIR
+/lib/libvirt/dnsmasq/, interface)  0)
+goto cleanup;
+
+if (virGetEnvAllowSUID(DNSMASQ_IAID)) {
+mac = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_MAC));
+clientid = argv[2];
+}
+
+/* Make sure

[libvirt] [PATCH] Fix memory leak in testDomainCreateXMLMixed()

2014-01-14 Thread Nehal J Wani
While running objecteventtest, it was found that valgrind pointed out the
following memory leak:

==13025== 538 (56 direct, 482 indirect) bytes in 1 blocks are definitely lost 
in loss record 216 of 226
==13025==at 0x4A06B6F: calloc (vg_replace_malloc.c:593)
==13025==by 0x4C65D8D: virAllocVar (viralloc.c:558)
==13025==by 0x4C9F055: virObjectNew (virobject.c:190)
==13025==by 0x4D2B2E8: virGetDomain (datatypes.c:220)
==13025==by 0x4D79180: testDomainDefineXML (test_driver.c:2962)
==13025==by 0x4D4977D: virDomainDefineXML (libvirt.c:8512)
==13025==by 0x4029C2: testDomainCreateXMLMixed (objecteventtest.c:226)
==13025==by 0x403A21: virtTestRun (testutils.c:138)
==13025==by 0x4021C2: mymain (objecteventtest.c:549)
==13025==by 0x4040C2: virtTestMain (testutils.c:593)
==13025==by 0x341F421A04: (below main) (libc-start.c:225)
==13025==

---
 tests/objecteventtest.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/tests/objecteventtest.c b/tests/objecteventtest.c
index 65642a2..de57970 100644
--- a/tests/objecteventtest.c
+++ b/tests/objecteventtest.c
@@ -245,6 +245,12 @@ testDomainCreateXMLMixed(const void *data)
 if (id2  0)
 goto cleanup;
 
+if (dom != NULL) {
+virDomainUndefine(dom);
+virDomainDestroy(dom);
+virDomainFree(dom);
+}
+
 dom = virDomainCreateXML(test-conn, domainDef, 0);
 if (dom == NULL || virEventRunDefaultImpl()  0)
 goto cleanup;
-- 
1.8.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] Add helper program to create custom leases

2014-01-14 Thread Nehal J Wani
Ignore this. It has missing lines for compilation and addition in
network driver. I am sending Patch v2.

On Thu, Dec 19, 2013 at 1:09 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:
 Introduce helper program to catch events from dnsmasq and maintain a custom
 lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
 interface-name.status.

 The format of each lease is:
 expiry-time (epoch time) mac iaid ip-address hostname clientid

 Example of custom leases file content:
 1385245780 52:54:00:2f:ba:76 * 192.168.150.153 * *
 1385245781 52:54:00:2f:ba:76 3127926 2001:db8:ca2:2:1::6c * 
 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
 1385245964 52:54:00:44:7c:d7 * 192.168.150.219 iiit-ad885e4aa1 
 01:52:54:00:44:7c:d7
 1385245964 52:54:00:44:7c:d7 * 192.168.150.219 * 01:52:54:00:44:7c:d7
 1385246016 52:54:00:5d:99:92 * 192.168.150.212 iiit-ad885e4aa1 
 01:52:54:00:5d:99:92
 1385246041 52:54:00:3b:16:e0 * 192.168.150.207 * *
 1385246081 52:54:00:db:dd:98 * 192.168.150.234 * *
 1385246088 52:54:00:db:dd:98 14409112 2001:db8:ca2:2:1::6d * 
 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec

 ---
  src/util/leaseshelper.c | 232 
 
  1 file changed, 232 insertions(+)
  create mode 100644 src/util/leaseshelper.c

 diff --git a/src/util/leaseshelper.c b/src/util/leaseshelper.c
 new file mode 100644
 index 000..9ed22a6
 --- /dev/null
 +++ b/src/util/leaseshelper.c
 @@ -0,0 +1,232 @@
 +/*
 + * leasehelper.c: Helper program to create custom leases file
 + *
 + * Copyright (C) 2013 Red Hat, Inc.
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library.  If not, see
 + * http://www.gnu.org/licenses/.
 + *
 + * Author: Nehal J Wani nehaljw.k...@gmail.com
 + *
 + */
 +
 +#include config.h
 +
 +#include stdio.h
 +#include stdlib.h
 +
 +#include virutil.h
 +#include virthread.h
 +#include virfile.h
 +#include virbuffer.h
 +#include virstring.h
 +#include virerror.h
 +#include viralloc.h
 +#include configmake.h
 +
 +#define VIR_FROM_THIS VIR_FROM_NETWORK
 +
 +/**
 + * VIR_NETWORK_DHCP_LEASE_FIELDS:
 + *
 + * Macro providing the maximum number of fields in an entry in
 + * the leases file
 + */
 +#define VIR_NETWORK_DHCP_LEASE_FIELDS 6
 +/**
 + * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
 + *
 + * Macro providing the upper limit on the size of leases file
 + */
 +#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152
 +
 +/*
 + * Use this when passing possibly-NULL strings to printf-a-likes.
 + */
 +# define EMPTY_STR(s) ((s) ? (s) : *)
 +
 +int
 +main(int argc, char **argv) {
 +
 +FILE *g = fopen(/tmp/wtf, a);
 +int j;
 +for (j = 0; j  argc; j++)
 +fprintf(g, called :: : %s, , argv[j]);
 +fprintf(g, \n);
 +fclose(g);
 +
 +/* Doesn't hurt to check */
 +if (argc  4) {
 +/* Refer man page of dnsmasq --dhcp-script for more details */
 +fprintf(stderr, Usage: $program $action ${mac|clientid} $ip\n);
 +return -1;
 +}
 +
 +const char *program_name = argv[0];
 +const char *action = argv[1];
 +const char *interface = 
 EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_INTERFACE));
 +const char *expirytime = 
 EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_LEASE_EXPIRES));
 +const char *mac = argv[2];
 +const char *ip = argv[3];
 +const char *iaid = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_IAID));
 +const char *hostname = 
 EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_SUPPLIED_HOSTNAME));
 +const char *clientid = 
 EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_CLIENT_ID));
 +const char *leases_str = NULL;
 +char *lease_file = NULL;
 +char *lease_entries = NULL;
 +char *lease_entry = NULL;
 +char **lease_fields = NULL;
 +bool delete = false;
 +bool add = false;
 +int rv = -1;
 +int lease_file_len = 0;
 +FILE *fp = NULL;
 +long long expirytime_tmp = 0;
 +virBuffer buf_new_lease = VIR_BUFFER_INITIALIZER;
 +virBuffer buf_all_leases = VIR_BUFFER_INITIALIZER;
 +
 +if (setlocale(LC_ALL, ) == NULL ||
 +bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
 +textdomain(PACKAGE) == NULL) {
 +fprintf(stderr, _(%s: initialization failed\n), program_name);
 +exit(EXIT_FAILURE);
 +}
 +
 +if (virThreadInitialize()  0 ||
 +virErrorInitialize()  0) {
 +fprintf(stderr, _(%s: initialization failed\n), program_name);
 +exit

[libvirt] [PATCH v2] Add helper program to create custom leases

2014-01-14 Thread Nehal J Wani
Introduce helper program to catch events from dnsmasq and maintain a custom
lease file per network. It supports DHCPv4 and DHCPv6. The file is saved as
interface-name.status.

The format of each lease is:
expiry-time (epoch time) mac iaid ip-address hostname clientid

Example of custom leases file content:
1385245780 52:54:00:2f:ba:76 * 192.168.150.153 * *
1385245781 52:54:00:2f:ba:76 3127926 2001:db8:ca2:2:1::6c * 
00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 iiit-ad885e4aa1 
01:52:54:00:44:7c:d7
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 * 01:52:54:00:44:7c:d7
1385246016 52:54:00:5d:99:92 * 192.168.150.212 iiit-ad885e4aa1 
01:52:54:00:5d:99:92
1385246041 52:54:00:3b:16:e0 * 192.168.150.207 * *
1385246081 52:54:00:db:dd:98 * 192.168.150.234 * *
1385246088 52:54:00:db:dd:98 14409112 2001:db8:ca2:2:1::6d * 
00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec

---
 As danpb suggested, I have split the previous patch into helper program  API
 Refer: https://www.redhat.com/archives/libvir-list/2013-December/msg00694.html
 Once this get ACKed, I'll send in the patches for the Leases API v6

 src/Makefile.am |  20 
 src/network/bridge_driver.c |   4 +
 src/util/leaseshelper.c | 225 
 3 files changed, 249 insertions(+)
 create mode 100644 src/util/leaseshelper.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 57e163f..6e5b03c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -838,6 +838,9 @@ STORAGE_HELPER_DISK_SOURCES =   
\
 UTIL_IO_HELPER_SOURCES =   \
util/iohelper.c
 
+UTIL_LEASES_HELPER_SOURCES =   \
+   util/leaseshelper.c
+
 # Network filters
 NWFILTER_DRIVER_SOURCES =  \
nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c   \
@@ -2408,6 +2411,23 @@ libvirt_iohelper_CFLAGS = \
$(NULL)
 endif WITH_LIBVIRTD
 
+if WITH_LIBVIRTD
+libexec_PROGRAMS += libvirt_leaseshelper
+libvirt_leaseshelper_SOURCES = $(UTIL_LEASES_HELPER_SOURCES)
+libvirt_leaseshelper_LDFLAGS = \
+   $(NULL)
+libvirt_leaseshelper_LDADD =   \
+   libvirt_util.la \
+   ../gnulib/lib/libgnu.la
+if WITH_DTRACE_PROBES
+libvirt_leaseshelper_LDADD += libvirt_probes.lo
+endif WITH_DTRACE_PROBES
+
+libvirt_leaseshelper_CFLAGS = \
+   $(PIE_CFLAGS) \
+   $(NULL)
+endif WITH_LIBVIRTD
+
 if WITH_STORAGE_DISK
 if WITH_LIBVIRTD
 libexec_PROGRAMS += libvirt_parthelper
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 95e4b65..2278dba 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1063,6 +1063,10 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr 
network,
 
 cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps));
 virCommandAddArgFormat(cmd, --conf-file=%s, configfile);
+
+/* This helper is used to create cutom leases file for libvirt */
+virCommandAddArgFormat(cmd, --dhcp-script=%s, LIBEXECDIR 
/libvirt_leaseshelper);
+
 *cmdout = cmd;
 ret = 0;
 cleanup:
diff --git a/src/util/leaseshelper.c b/src/util/leaseshelper.c
new file mode 100644
index 000..486ebe3
--- /dev/null
+++ b/src/util/leaseshelper.c
@@ -0,0 +1,225 @@
+/*
+ * leasehelper.c: Helper program to create custom leases file
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * Author: Nehal J Wani nehaljw.k...@gmail.com
+ *
+ */
+
+#include config.h
+
+#include stdio.h
+#include stdlib.h
+
+#include virutil.h
+#include virthread.h
+#include virfile.h
+#include virbuffer.h
+#include virstring.h
+#include virerror.h
+#include viralloc.h
+#include configmake.h
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FIELDS:
+ *
+ * Macro providing the maximum number of fields in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FIELDS 6
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152
+
+/*
+ * Use this when passing possibly-NULL strings to printf-a-likes.
+ */
+# define

Re: [libvirt] [PATCH v2] Add helper program to create custom leases

2014-01-16 Thread Nehal J Wani
On Thu, Jan 16, 2014 at 9:07 AM, Doug Goldstein car...@cardoe.com wrote:
 On Jan 14, 2014, at 2:09 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:

 Introduce helper program to catch events from dnsmasq and maintain a custom
 lease file per network. It supports DHCPv4 and DHCPv6. The file is saved as
 interface-name.status.

 The format of each lease is:
 expiry-time (epoch time) mac iaid ip-address hostname clientid


 I feel like I'm bikesheding but is it the best idea to have a custom file 
 format? I know our string handling code makes this really easy to do but it 
 just has a slight code smell to make our own format. We link to stuff like 
 yajl and libxml for JSON/XML support and its really simple to do so we could 
 easily write out a JSON/XML file and read it in.

 Definitely don't rework the patch based on my comments because we'll 99.9% go 
 with this way, I'm just asking a question I felt should be asked.


I understand the point you are trying to raise here. A similar
discussion had taken place when I had posted the RFC:
http://www.redhat.com/archives/libvir-list/2013-October/msg01024.html
. If y'all still think that we should be using a format we already
have a parser for, I'll be happy to rewrite the patch :-)


-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2] Add helper program to create custom leases

2014-01-27 Thread Nehal J Wani

 I feel like I'm bikesheding but is it the best idea to have a custom file 
 format? I know our string handling code makes this really easy to do but it 
 just has a slight code smell to make our own format. We link to stuff like 
 yajl and libxml for JSON/XML support and its really simple to do so we could 
 easily write out a JSON/XML file and read it in.

 Definitely don't rework the patch based on my comments because we'll 99.9% 
 go with this way, I'm just asking a question I felt should be asked.



Seems like nobody liked this format. I am sending the updated patch
which uses JSON as the format for storing leases.

 --
 Nehal J Wani



-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2] Add helper program to create custom leases

2014-01-27 Thread Nehal J Wani
 redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * Author: Nehal J Wani nehaljw.k...@gmail.com
+ *
+ */
+
+#include config.h
+
+#include stdio.h
+#include stdlib.h
+
+#include virutil.h
+#include virthread.h
+#include virfile.h
+#include virbuffer.h
+#include virstring.h
+#include virerror.h
+#include viralloc.h
+#include virjson.h
+#include configmake.h
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152
+
+/*
+ * Use this when passing possibly-NULL strings to printf-a-likes.
+ */
+# define EMPTY_STR(s) ((s) ? (s) : *)
+
+int
+main(int argc, char **argv) {
+
+/* Doesn't hurt to check */
+if (argc  4) {
+/* Refer man page of dnsmasq --dhcp-script for more details */
+fprintf(stderr, Usage: $program $action ${mac|clientid} $ip\n);
+return -1;
+}
+
+char *lease_file = NULL;
+char *lease_entries = NULL;
+const char *ip = argv[3];
+const char *mac = argv[2];
+const char *action = argv[1];
+const char *program_name = argv[0];
+const char *iaid = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_IAID));
+const char *clientid = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_CLIENT_ID));
+const char *interface = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_INTERFACE));
+const char *exptime = 
EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_LEASE_EXPIRES));
+const char *hostname = 
EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_SUPPLIED_HOSTNAME));
+const char *leases_str = NULL;
+size_t i = 0;
+int rv = -1;
+int size = 0;
+int lease_file_len = 0;
+FILE *fp = NULL;
+bool add = false;
+bool delete = false;
+virJSONValuePtr lease_new;
+virJSONValuePtr lease_tmp;
+virJSONValuePtr leases_array;
+virJSONValuePtr lease_new_tmp;
+virJSONValuePtr leases_array_new;
+
+if (setlocale(LC_ALL, ) == NULL ||
+bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+textdomain(PACKAGE) == NULL) {
+fprintf(stderr, _(%s: initialization failed\n), program_name);
+exit(EXIT_FAILURE);
+}
+
+if (virThreadInitialize()  0 ||
+virErrorInitialize()  0) {
+fprintf(stderr, _(%s: initialization failed\n), program_name);
+exit(EXIT_FAILURE);
+}
+
+if (virAsprintf(lease_file, %s/%s.status, LOCALSTATEDIR
+/lib/libvirt/dnsmasq/, interface)  0)
+goto cleanup;
+
+if (virGetEnvAllowSUID(DNSMASQ_IAID)) {
+mac = EMPTY_STR(virGetEnvAllowSUID(DNSMASQ_MAC));
+clientid = argv[2];
+}
+
+/* Make sure dnsmasq knows the interface, otherwise something is wrong */
+if (STREQ(interface, *))
+goto cleanup;
+
+/* Make sure the file exists. If not, 'touch' it */
+if (virFileTouch(lease_file, 0644)  0)
+goto cleanup;
+
+/* Read entire contents */
+if ((lease_file_len = virFileReadAll(lease_file,
+ VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
+ lease_entries))  0) {
+goto cleanup;
+}
+
+if (STREQ(action, add) || STREQ(action, old) || STREQ(action, del)) {
+if (mac || STREQ(action, del)) {
+/* Delete the corresponding lease */
+delete = true;
+if (STREQ(action, add) || STREQ(action, old)) {
+add = true;
+/* Enter new lease */
+if (!(lease_new = virJSONValueNewObject())) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(failed to create json));
+goto cleanup;
+}
+if (virJSONValueObjectAppendString(lease_new, expiry-time,
+   exptime)  0 ||
+virJSONValueObjectAppendString(lease_new, mac-address,
+   mac)  0 ||
+virJSONValueObjectAppendString(lease_new, iaid,
+   iaid)  0 ||
+virJSONValueObjectAppendString(lease_new, ip-address,
+   ip)  0 ||
+virJSONValueObjectAppendString(lease_new, hostname

Re: [libvirt] [PATCH v2] Add helper program to create custom leases

2014-02-02 Thread Nehal J Wani
On Mon, Jan 27, 2014 at 2:17 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:

 Introduce helper program to catch events from dnsmasq and maintain a custom
 lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
 interface-name.status.

 Each lease contains the following info:
 expiry-time (epoch time) mac iaid ip-address hostname clientid

 Example of custom leases file content:
 [
 {
 expiry-time: 1390775837,
 mac-address: 52:54:00:93:8c:63,
 iaid: *,
 ip-address: 192.168.150.209,
 hostname: iit-ad885e4aa1,
 client-id: 01:52:54:00:44:7c:d7
 },
 {
 expiry-time: 1390775950,
 mac-address: 52:54:00:7b:6f:ba,
 iaid: 8089530,
 ip-address: 2001:db8:ca2:2:1::6d,
 hostname: *,
 client-id: 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
 }
 ]

 src/Makefile.am:
* Add options to compile the helper program

 src/network/bridge_driver.c:
* Introduce networkDnsmasqLeaseFileNameCustom()
* Invoke helper program along with dnsmasq
* Delete the .status file when corresponding n/w is destroyed.

 src/util/leaseshelper.c
* Helper program to create the custom lease file

 ---
  v2:
  * Changed format to JSON

  v1:
  * Refer: 
 https://www.redhat.com/archives/libvir-list/2014-January/msg00626.html

  src/Makefile.am |  20 
  src/network/bridge_driver.c |  19 
  src/util/leaseshelper.c | 271 
 
  3 files changed, 310 insertions(+)
  create mode 100644 src/util/leaseshelper.c


Ping!

-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] Fix memory leak in virDomainSnapshotDiskDefClear()

2014-02-22 Thread Nehal J Wani
While running domainsnapshotxml2xmltest, it was found that valgrind pointed out
the following memory leaks:

==32176== 42 (32 direct, 10 indirect) bytes in 1 blocks are definitely lost in 
loss record 42 of 66
==32176==at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==32176==by 0x4A06B62: realloc (vg_replace_malloc.c:662)
==32176==by 0x4C65A07: virReallocN (viralloc.c:243)
==32176==by 0x4C65B2E: virExpandN (viralloc.c:292)
==32176==by 0x4C65E30: virInsertElementsN (viralloc.c:434)
==32176==by 0x4CD71F3: virDomainDiskSourceDefParse (domain_conf.c:5078)
==32176==by 0x4CF6EF4: virDomainSnapshotDefParseNode (snapshot_conf.c:151)
==32176==by 0x4CF7314: virDomainSnapshotDefParseString (snapshot_conf.c:410)
==32176==by 0x41FB8D: testCompareXMLToXMLHelper 
(domainsnapshotxml2xmltest.c:100)
==32176==by 0x420FD1: virtTestRun (testutils.c:199)
==32176==by 0x41F859: mymain (domainsnapshotxml2xmltest.c:222)
==32176==by 0x42174D: virtTestMain (testutils.c:782)
==32176==
==32176== 128 (96 direct, 32 indirect) bytes in 1 blocks are definitely lost in 
loss record 51 of 66
==32176==at 0x4A06BE0: realloc (vg_replace_malloc.c:662)
==32176==by 0x4C65A07: virReallocN (viralloc.c:243)
==32176==by 0x4C65B2E: virExpandN (viralloc.c:292)
==32176==by 0x4C65E30: virInsertElementsN (viralloc.c:434)
==32176==by 0x4CD71F3: virDomainDiskSourceDefParse (domain_conf.c:5078)
==32176==by 0x4CF6EF4: virDomainSnapshotDefParseNode (snapshot_conf.c:151)
==32176==by 0x4CF7314: virDomainSnapshotDefParseString (snapshot_conf.c:410)
==32176==by 0x41FB8D: testCompareXMLToXMLHelper 
(domainsnapshotxml2xmltest.c:100)
==32176==by 0x420FD1: virtTestRun (testutils.c:199)
==32176==by 0x41F859: mymain (domainsnapshotxml2xmltest.c:222)
==32176==by 0x42174D: virtTestMain (testutils.c:782)
==32176==by 0x3E6CE1ED1C: (below main) (libc-start.c:226)
==32176==

---
 src/conf/snapshot_conf.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index 12b0930..475525f 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -82,6 +82,7 @@ virDomainSnapshotDiskDefClear(virDomainSnapshotDiskDefPtr 
disk)
 {
 VIR_FREE(disk-name);
 VIR_FREE(disk-file);
+virDomainDiskHostDefFree(disk-nhosts, disk-hosts);
 }
 
 void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def)
-- 
1.7.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] Fix memory leak in virSCSIDeviceListDel()

2014-02-22 Thread Nehal J Wani
While running virscsitest, it was found that valgrind pointed out the following
memory leak:

==320== 5 bytes in 1 blocks are definitely lost in loss record 4 of 37
==320==at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==320==by 0x3E6CE81171: strdup (strdup.c:43)
==320==by 0x4CB28DF: virStrdup (virstring.c:554)
==320==by 0x4CAC987: virSCSIDeviceSetUsedBy (virscsi.c:289)
==320==by 0x402321: test2 (virscsitest.c:100)
==320==by 0x403231: virtTestRun (testutils.c:199)
==320==by 0x402121: mymain (virscsitest.c:180)
==320==by 0x4039AD: virtTestMain (testutils.c:782)
==320==by 0x3E6CE1ED1C: (below main) (libc-start.c:226)
==320==

---
 src/util/virscsi.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/util/virscsi.c b/src/util/virscsi.c
index acc3815..2f469f2 100644
--- a/src/util/virscsi.c
+++ b/src/util/virscsi.c
@@ -435,6 +435,7 @@ virSCSIDeviceListDel(virSCSIDeviceListPtr list,
 for (i = 0; i  dev-n_used_by; i++) {
 if (STREQ_NULLABLE(dev-used_by[i], name)) {
 if (dev-n_used_by  1) {
+VIR_FREE(dev-used_by[i]);
 VIR_DELETE_ELEMENT(dev-used_by, i, dev-n_used_by);
 } else {
 tmp = virSCSIDeviceListSteal(list, dev);
-- 
1.7.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3] Add helper program to create custom leases

2014-02-24 Thread Nehal J Wani
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * Author: Nehal J Wani nehaljw.k...@gmail.com
+ */
+
+#include config.h
+
+#include stdio.h
+#include stdlib.h
+#include sys/stat.h
+
+#include virutil.h
+#include virthread.h
+#include virfile.h
+#include virbuffer.h
+#include virstring.h
+#include virerror.h
+#include viralloc.h
+#include virjson.h
+#include configmake.h
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX (2 * 1024 * 1024)
+
+static const char *program_name;
+
+/* Display version information. */
+static void
+helperVersion(const char *argv0)
+{
+printf(%s (%s) %s\n, argv0, PACKAGE_NAME, PACKAGE_VERSION);
+}
+
+ATTRIBUTE_NORETURN static void
+usage(int status)
+{
+if (status) {
+fprintf(stderr, _(%s: try --help for more details\n), program_name);
+} else {
+printf(_(Usage: %s ACTION MAC|CLIENTID IP HOSTNAME\n
+or: %s ACTION MAC|CLIENTID IP\n),
+   program_name, program_name);
+}
+exit(status);
+}
+
+static int
+customLeaseRewriteFile(int fd, void *opaque)
+{
+char **data = opaque;
+
+if (safewrite(fd, *data, strlen(*data))  0)
+return -1;
+
+return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+char *lease_entries = NULL;
+char *custom_lease_file = NULL;
+const char *ip = NULL;
+const char *mac = NULL;
+const char *action = NULL;
+const char *iaid = virGetEnvAllowSUID(DNSMASQ_IAID);
+const char *clientid = virGetEnvAllowSUID(DNSMASQ_CLIENT_ID);
+const char *interface = virGetEnvAllowSUID(DNSMASQ_INTERFACE);
+const char *exptime = virGetEnvAllowSUID(DNSMASQ_LEASE_EXPIRES);
+const char *hostname = virGetEnvAllowSUID(DNSMASQ_SUPPLIED_HOSTNAME);
+const char *leases_str = NULL;
+long long expirytime = 0;
+size_t i = 0;
+int rv = EXIT_FAILURE;
+int size = 0;
+int custom_lease_file_len = 0;
+bool add = false;
+bool delete = false;
+virJSONValuePtr lease_new = NULL;
+virJSONValuePtr lease_tmp = NULL;
+virJSONValuePtr leases_array = NULL;
+virJSONValuePtr leases_array_new = NULL;
+
+virSetErrorFunc(NULL, NULL);
+virSetErrorLogPriorityFunc(NULL);
+
+program_name = argv[0];
+
+if (setlocale(LC_ALL, ) == NULL ||
+bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+textdomain(PACKAGE) == NULL) {
+fprintf(stderr, _(%s: initialization failed\n), program_name);
+exit(EXIT_FAILURE);
+}
+
+if (virThreadInitialize()  0 ||
+virErrorInitialize()  0) {
+fprintf(stderr, _(%s: initialization failed\n), program_name);
+exit(EXIT_FAILURE);
+}
+
+/* Doesn't hurt to check */
+if (argc  1) {
+if(STREQ(argv[1], --help))
+usage(EXIT_SUCCESS);
+
+if (STREQ(argv[1], --version)) {
+helperVersion(argv[0]);
+exit(EXIT_SUCCESS);
+}
+}
+
+if (argc != 4  argc != 5) {
+/* Refer man page of dnsmasq --dhcp-script for more details */
+usage(EXIT_FAILURE);
+}
+
+/* Make sure dnsmasq knows the interface. The interface name is not known
+ * when dnsmasq (re)starts and throws 'del' events for expired leases.
+ * So, if any old lease has expired, it will be automatically removed the
+ * next time this program is invoked */
+if (!interface)
+goto cleanup;
+
+ip = argv[3];
+mac = argv[2];
+action = argv[1];
+
+/* In case hostname is known, it is the 5th argument */
+if (argc == 5)
+   hostname = argv[4];
+
+if (virAsprintf(custom_lease_file, %s/%s.status, LOCALSTATEDIR
+/lib/libvirt/dnsmasq/, interface)  0)
+goto cleanup;
+
+/* Check if it is an IPv6 lease */
+if (virGetEnvAllowSUID(DNSMASQ_IAID)) {
+mac = virGetEnvAllowSUID(DNSMASQ_MAC);
+clientid=argv[2];
+}
+
+/* Since interfaces can be hot plugged, we need to make sure that the
+ * corresponding custom lease file exists. If not, 'touch' it */
+if (virFileTouch(custom_lease_file, 0644)  0)
+goto cleanup;
+
+/* Read entire contents */
+if ((custom_lease_file_len = virFileReadAll(custom_lease_file

Re: [libvirt] [PATCH v3] Add helper program to create custom leases

2014-03-03 Thread Nehal J Wani
On Mon, Feb 24, 2014 at 5:27 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:
 Introduce helper program to catch events from dnsmasq and maintain a custom
 lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
 interface-name.status.

 Each lease contains the following info:
 expiry-time (epoch time) mac iaid ip-address hostname clientid

 Example of custom leases file content:
 [
 {
 iaid: 1221229,
 ip-address: 2001:db8:ca2:2:1::95,
 mac-address: 52:54:00:12:a2:6d,
 hostname: Fedora20,
 client-id: 00:04:1a:c1:d9:6b:5a:0a:e2:bc:f8:4b:1e:37:2e:38:22:55,
 expiry-time: 1393244216
 },
 {
 ip-address: 192.168.150.208,
 mac-address: 52:54:00:11:56:b3,
 hostname: Wani-PC,
 client-id: 01:52:54:00:11:56:b3,
 expiry-time: 1393244248
 }
 ]

 src/Makefile.am:
* Add options to compile the helper program

 src/network/bridge_driver.c:
* Introduce networkDnsmasqLeaseFileNameCustom()
* Invoke helper program along with dnsmasq
* Delete the .status file when corresponding n/w is destroyed.

 src/util/leaseshelper.c
* Helper program to create the custom lease file

 ---
  v3:
  * Improved file handling, removed redundant copying, introduced --help and 
 --version

  v2:
  * Changed format to JSON
  * Refer: 
 https://www.redhat.com/archives/libvir-list/2014-January/msg01234.html

  v1:
  * Refer: 
 https://www.redhat.com/archives/libvir-list/2014-January/msg00626.html

  src/Makefile.am |   16 +++
  src/network/bridge_driver.c |   19 +++
  src/util/leaseshelper.c |  303 
 +++
  3 files changed, 338 insertions(+), 0 deletions(-)
  create mode 100644 src/util/leaseshelper.c


Ping!

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] Fix memory leak in virDomainSnapshotDiskDefClear()

2014-03-03 Thread Nehal J Wani
 ---
  src/conf/snapshot_conf.c |1 +
  1 files changed, 1 insertions(+), 0 deletions(-)

 diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
 index 12b0930..475525f 100644
 --- a/src/conf/snapshot_conf.c
 +++ b/src/conf/snapshot_conf.c
 @@ -82,6 +82,7 @@ virDomainSnapshotDiskDefClear(virDomainSnapshotDiskDefPtr 
 disk)
  {
  VIR_FREE(disk-name);
  VIR_FREE(disk-file);
 +virDomainDiskHostDefFree(disk-nhosts, disk-hosts);

 This leaves nhosts and hosts at their original values, which seems to be OK
 everywhere this function is called, but it might be a problem if someone tries
 to reuse the disk definition instead of freeing it.

 I'd rather write this as:

 while (disk-nhosts)
 virDomainDiskHostDefClear(disk-hosts[--def-nhosts])
 VIR_FREE(disk-hosts)

 Jan


1. Since virDomainDiskHostDefFree() already calls VIR_FREE(hosts),
shouldn't the modified patch just be:
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index 12b0930..a233e8e 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -82,6 +82,8 @@
virDomainSnapshotDiskDefClear(virDomainSnapshotDiskDefPtr disk)
 {
 VIR_FREE(disk-name);
 VIR_FREE(disk-file);
+virDomainDiskHostDefFree(disk-nhosts, disk-hosts);
+disk-nhosts = 0;
 }

 void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def)

2. I have a question. Why don't we have disk-nhosts = 0; each time
someone calls virDomainDiskHostDefFree(disk-nhosts, disk-hosts) in
./src/conf/domain_conf.c, ./src/storage/storage_driver.c and
./src/qemu/qemu_conf.c?
Or we can change the definition of virDomainDiskHostDefFree to
virDomainDiskHostDefFree(size_t *nhosts, virDomainDiskHostDefPtr hosts)
and make *nhosts = 0 inside the function itself and make the necessary
changes wherever this function is called?

-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3] Add helper program to create custom leases

2014-03-10 Thread Nehal J Wani
On Tue, Mar 4, 2014 at 12:18 AM, Nehal J Wani nehaljw.k...@gmail.com wrote:

 On Mon, Feb 24, 2014 at 5:27 PM, Nehal J Wani nehaljw.k...@gmail.com wrote:
  Introduce helper program to catch events from dnsmasq and maintain a custom
  lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
  interface-name.status.
 
  Each lease contains the following info:
  expiry-time (epoch time) mac iaid ip-address hostname clientid
 
  Example of custom leases file content:
  [
  {
  iaid: 1221229,
  ip-address: 2001:db8:ca2:2:1::95,
  mac-address: 52:54:00:12:a2:6d,
  hostname: Fedora20,
  client-id: 
  00:04:1a:c1:d9:6b:5a:0a:e2:bc:f8:4b:1e:37:2e:38:22:55,
  expiry-time: 1393244216
  },
  {
  ip-address: 192.168.150.208,
  mac-address: 52:54:00:11:56:b3,
  hostname: Wani-PC,
  client-id: 01:52:54:00:11:56:b3,
  expiry-time: 1393244248
  }
  ]
 
  src/Makefile.am:
 * Add options to compile the helper program
 
  src/network/bridge_driver.c:
 * Introduce networkDnsmasqLeaseFileNameCustom()
 * Invoke helper program along with dnsmasq
 * Delete the .status file when corresponding n/w is destroyed.
 
  src/util/leaseshelper.c
 * Helper program to create the custom lease file
 
  ---
   v3:
   * Improved file handling, removed redundant copying, introduced --help and 
  --version
 
   v2:
   * Changed format to JSON
   * Refer: 
  https://www.redhat.com/archives/libvir-list/2014-January/msg01234.html
 
   v1:
   * Refer: 
  https://www.redhat.com/archives/libvir-list/2014-January/msg00626.html
 
   src/Makefile.am |   16 +++
   src/network/bridge_driver.c |   19 +++
   src/util/leaseshelper.c |  303 
  +++
   3 files changed, 338 insertions(+), 0 deletions(-)
   create mode 100644 src/util/leaseshelper.c


 Ping!


Ping!

-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCHv3 2/4] net-dhcp-leases: Implement the remote protocol

2013-09-16 Thread Nehal J Wani
 +static int
 +remoteSerializeNetworkDHCPLeases(virNetworkDHCPLeasesPtr *leases,
 + int nleases,
 + remote_network_get_dhcp_leases_ret *ret)
 +{
 +size_t i;
 +
 +if (nleases  REMOTE_NETWORK_DHCP_LEASES_MAX) {
 +virReportError(VIR_ERR_INTERNAL_ERROR,
 +   _(Number of leases is %d, which exceeds max
limit: %d),
 +   nleases, REMOTE_NETWORK_DHCP_LEASES_MAX);
 +return -1;
 +}
 +
 +if (VIR_ALLOC_N(ret-leases.leases_val, nleases)  0)
 +return -1;
 +
 +ret-leases.leases_len = nleases;
 +
 +for (i = 0; i  nleases; i++) {
 +virNetworkDHCPLeasesPtr lease = leases[i];
 +remote_network_dhcp_lease *lease_ret =
(ret-leases.leases_val[i]);
 +lease_ret-expirytime = lease-expirytime;
 +lease_ret-type = lease-type;
 +lease_ret-prefix = lease-prefix;
 +
 +if ((VIR_STRDUP(lease_ret-mac, lease-mac)  0) ||
 +(VIR_STRDUP(lease_ret-ipaddr, lease-ipaddr)  0) ||
 +(VIR_STRDUP(lease_ret-hostname, lease-hostname)  0) ||
 +(VIR_STRDUP(lease_ret-clientid, lease-clientid)  0))
 +goto error;
 +}
 +
 +return 0;
 +
 +error:
 +for (i = 0; i  nleases; i++) {
 +remote_network_dhcp_lease *lease_ret =
(ret-leases.leases_val[i]);
 +virNetworkDHCPLeaseFree((virNetworkDHCPLeasesPtr)lease_ret);

[1]

 +}
 +return -1;
 +}
 +
 +static int
 +remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server
ATTRIBUTE_UNUSED,
 +   virNetServerClientPtr client,
 +   virNetMessagePtr msg ATTRIBUTE_UNUSED,
 +   virNetMessageErrorPtr rerr,
 +   remote_network_get_dhcp_leases_args
*args,
 +   remote_network_get_dhcp_leases_ret
*ret)
 +{
 +int rv = -1;
 +struct daemonClientPrivate *priv =
virNetServerClientGetPrivateData(client);
 +virNetworkDHCPLeasesPtr *leases = NULL;
 +virNetworkPtr net = NULL;
 +int nleases = 0;
 +
 +if (!priv-conn) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not
open));
 +goto cleanup;
 +}
 +
 +if (!(net = get_nonnull_network(priv-conn, args-net)))
 +goto cleanup;
 +
 +if ((nleases = virNetworkGetDHCPLeases(net, leases, args-flags)) 
0)
 +goto cleanup;
 +
 +if (remoteSerializeNetworkDHCPLeases(leases, nleases, ret)  0)
 +goto cleanup;

 +rv = nleases;
 +
 +cleanup:
 +if (rv  0)
 +virNetMessageSaveError(rerr);
 +if (leases) {
 +size_t i;
 +for (i = 0; i  nleases; i++) {
 +virNetworkDHCPLeaseFree(leases[i]);
 +}
 +}
 +VIR_FREE(leases);
 +virNetworkFree(net);
 +return rv;
 +}
 +
 +static int
 +remoteDispatchNetworkGetDHCPLeasesForMAC(virNetServerPtr server
ATTRIBUTE_UNUSED,
 + virNetServerClientPtr client,
 + virNetMessagePtr msg
ATTRIBUTE_UNUSED,
 + virNetMessageErrorPtr rerr,
 +
remote_network_get_dhcp_leases_for_mac_args *args,
 +
remote_network_get_dhcp_leases_for_mac_ret *ret)
 +{
 +int rv = -1;
 +struct daemonClientPrivate *priv =
virNetServerClientGetPrivateData(client);
 +virNetworkDHCPLeasesPtr *leases = NULL;
 +virNetworkPtr net = NULL;
 +int nleases = 0;
 +const char *mac = NULL;
 +
 +if (!priv-conn) {
 +virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not
open));
 +goto cleanup;
 +}
 +
 +if (!(net = get_nonnull_network(priv-conn, args-net)))
 +goto cleanup;
 +
 +mac = args-mac ? *args-mac : NULL;
 +
 +if ((nleases = virNetworkGetDHCPLeasesForMAC(net, mac, leases,
args-flags))  0)
 +goto cleanup;
 +
 +if (remoteSerializeNetworkDHCPLeases(leases, nleases,
 +
(remote_network_get_dhcp_leases_ret *)ret)  0)
[2]

 +goto cleanup;
 +
 +rv = nleases;
 +


I am a little skeptical about the typecasts involved in [1] and [2]

Specifically for [2], although the APIs are different, the struct is same,
only the name is different. But, what would be the other options?

One option: (Suggested by Osier)
Change remoteSerializeNetworkDHCPLeases to

+remoteSerializeNetworkDHCPLeases(virNetworkDHCPLeasesPtr *leases,
+ int nleases,
+ (void *) ret,
+ int method)

where the datatype for variable in which ret will be copied, will be
decided based on the method (method's value will be taken from an enum
or something similar, e.g: 1-DHCPLeases, 2-DHCPLeasesForMAC)

OR

Second Option: Since the APIs should be independent, make another function:
remoteSerializeNetworkDHCPLeasesForMAC(...), but that will lead to code
redundancy.

Eric, what would you do in 

Re: [libvirt] [PATCHv3 1/4] net-dhcp-leases: Implement the public APIs

2013-09-16 Thread Nehal J Wani
On Mon, Sep 16, 2013 at 8:55 PM, Daniel P. Berrange berra...@redhat.com wrote:

 On Mon, Sep 16, 2013 at 08:45:09PM +0530, Nehal J Wani wrote:
  PFA: Diff
 
  On Mon, Sep 16, 2013 at 8:44 PM, Nehal J Wani nehaljw.k...@gmail.com 
  wrote:
   On Mon, Sep 16, 2013 at 3:22 PM, Daniel P. Berrange berra...@redhat.com 
   wrote:
  
   On Mon, Sep 16, 2013 at 11:19:13AM +0530, Nehal J Wani wrote:
+int
+virNetworkGetDHCPLeasesForMAC(virNetworkPtr network,
+  const char *mac,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags)
+{
+virConnectPtr conn;
+virMacAddr addr;
+
+VIR_DEBUG(network=%p, mac=%s, leases=%p, flags=%x,
+   network, mac, leases, flags);
+
+virResetLastError();
+
+virCheckNonNullArgGoto(network, error);
+virCheckNonNullArgGoto(mac, error);
+
+if (leases)
+*leases = NULL;
+
+if (!VIR_IS_CONNECTED_NETWORK(network)) {
+virLibNetworkError(VIR_ERR_INVALID_NETWORK, __FUNCTION__);
+virDispatchError(NULL);
+return -1;
+}
+
+/* Validate the MAC address */
+if (mac  virMacAddrParse(mac, addr)  0) {
+virReportInvalidArg(mac,
+_(Given MAC Address doesn't comply 
+  with the standard (IEEE 802) format in 
%s),
+__FUNCTION__);
  
   Don't pass __FUNCTION__ in this error message - that is already done 
   automatically
  
+goto error;
+}
  
   'mac' should be a mandatory parameter here.
  
   Attached diff should fix it.

 No, it makes it worse - you're now allowing a NULL mac parameter
 to be passed to virMacAddrParse which will cause a segv. You need
 to be checking for mac == NULL with virCheckNonNullArg


I think you missed this, I am already using virCheckNonNullArg :

+virConnectPtr conn;
+virMacAddr addr;
+
+VIR_DEBUG(network=%p, mac=%s, leases=%p, flags=%x,
+   network, mac, leases, flags);
+
+virResetLastError();
+
+virCheckNonNullArgGoto(network, error);
+virCheckNonNullArgGoto(mac, error);
+
+if (leases)
+*leases = NULL;



 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 :|




-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] build: ensure 'make check' sees up-to-date config.h

2013-09-23 Thread Nehal J Wani
On Thu, Sep 19, 2013 at 4:02 AM, Eric Blake ebl...@redhat.com wrote:

 Nehal J. Wani reported on IRC a rather interesting build failure:

 In file included from util/virnetdevbridge.c:53:0:
 /usr/include/linux/in6.h:30:8: error: redefinition of 'struct in6_addr'
  struct in6_addr {
 ^

 I traced it to the fact that he ran 'git pull; make check' across
 commit e62e0094.  What happened is that the configure changes
 result in a new variable that was set to be defined on his system,
 but config.h was not regenerated to contain the value of that
 variable.  Running 'make' instead of 'make check' cleaned up the
 problem.  A bit more investigation, and I see that in Makefile.am,
 automake sticks rules that rebuild config.h as part of 'make all',
 and that we also had a dependency 'check-local: all'; BUT the
 rule for check-local is run only at the point when the top-level
 directory is visited.  Automake documents that SUBDIRS should
 contain an explicit '.' at the point the top-level should be
 visited (defaulting to last, if it doesn't appear).  Sure enough,
 with this patch, 'make check' now does the top-level 'all' rules,
 which regenerates 'config.h' BEFORE compiling any code that might
 depend on changed content of that file.

 * Makefile.am (SUBDIRS): Put '.' first, not last.

 Signed-off-by: Eric Blake ebl...@redhat.com
 ---

 Tough to argue the build-breaker rule on this one, since a
 fresh checkout doesn't hit it (only a 'make check' without
 a 'make', across an incremental build that happened to need
 new configure substitutions).  So I'll wait for a review
 for my one-liner.

  Makefile.am |2 +-
  1 files changed, 1 insertions(+), 1 deletions(-)

 diff --git a/Makefile.am b/Makefile.am
 index 4e24ecf..66cb677 100644
 --- a/Makefile.am
 +++ b/Makefile.am
 @@ -19,7 +19,7 @@
  LCOV = lcov
  GENHTML = genhtml

 -SUBDIRS = gnulib/lib include src daemon tools docs gnulib/tests \
 +SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \
python tests po examples/domain-events/events-c examples/hellolibvirt \
examples/dominfo examples/domsuspend examples/python examples/apparmor \
examples/xml/nwfilter examples/openauth examples/systemtap
 --
 1.7.1

 --
 libvir-list mailing list
 libvir-list@redhat.com
 https://www.redhat.com/mailman/listinfo/libvir-list




Ping. If there is a specific reason why this was not pushed, I would
like to know.


Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH] build: ensure 'make check' sees up-to-date config.h

2013-09-23 Thread Nehal J Wani
On Mon, Sep 23, 2013 at 9:13 PM, Eric Blake ebl...@redhat.com wrote:
 On 09/23/2013 09:07 AM, Nehal J Wani wrote:
 On Thu, Sep 19, 2013 at 4:02 AM, Eric Blake ebl...@redhat.com wrote:

 Nehal J. Wani reported on IRC a rather interesting build failure:

 In file included from util/virnetdevbridge.c:53:0:
 /usr/include/linux/in6.h:30:8: error: redefinition of 'struct in6_addr'
  struct in6_addr {
 ^


 * Makefile.am (SUBDIRS): Put '.' first, not last.

 Signed-off-by: Eric Blake ebl...@redhat.com
 ---

 Tough to argue the build-breaker rule on this one, since a
 fresh checkout doesn't hit it (only a 'make check' without
 a 'make', across an incremental build that happened to need
 new configure substitutions).  So I'll wait for a review
 for my one-liner.



 Ping. If there is a specific reason why this was not pushed, I would
 like to know.

 Pong - no one has reviewed it.  Did it work for you?  If so, state that,
 and your review will serve as enough for me to push it :)

Running 'make' and then 'make check' worked for me. So, I guess there
is no problem in pushing this patch.

-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv4 0/4] Introduce APIs to extract DHCP leases info

2013-09-26 Thread Nehal J Wani
This API returns the leases information stored in the DHCP leases
file of dnsmasq for a given virtual network. It contacts the
bridge network driver, which parses the leases file.

It supports two methods:

1. Return info for all network interfaces connected to a given
   virtual network
2. Return information for a particular network interface in a
   given virtual network by providing its MAC Address

v4
* Added support for DHCPv6, updated lease file parsing method

v3
* Mostly small nits, change in MACRO names, use of virSocketAddrGetIpPrefix to
  retrieve IP prefix from @dom XML.
  Refer: 
https://www.redhat.com/archives/libvir-list/2013-September/msg00832.html

v2
* Since DHCPv6 is supposed to be suported in future, 
virNetworkGetDHCPLeasesForMAC
  changed, prefix and virIPAddrType added in virNetworkDHCPLeases struct.
  Refer: 
https://www.redhat.com/archives/libvir-list/2013-September/msg00732.html

v1
* Refer: 
https://www.redhat.com/archives/libvir-list/2013-September/msg00620.html

* The need for these APIs were result of a RFC was proposed on the list.
  Refer: http://www.redhat.com/archives/libvir-list/2013-July/msg01603.html

Nehal J Wani (4):
  net-dhcp-leases: Implement the remote protocol
  net-dhcp-leases: Implement the remote protocol
  net-dhcp-leases: Private implementation inside network driver
  net-dhcp-leases: Add virsh support

 daemon/remote.c  | 157 
 include/libvirt/libvirt.h.in |  36 +++
 python/generator.py  |   3 +
 src/driver.h |  13 +++
 src/libvirt.c| 177 +++
 src/libvirt_public.syms  |   3 +
 src/network/bridge_driver.c  | 240 +++
 src/remote/remote_driver.c   | 169 +-
 src/remote/remote_protocol.x |  59 ++-
 src/remote_protocol-structs  |  47 +
 src/rpc/gendispatch.pl   |   1 +
 tools/virsh-network.c| 150 +++
 tools/virsh.pod  |   6 ++
 13 files changed, 1057 insertions(+), 4 deletions(-)

-- 
1.7.11.7

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv4 2/4] net-dhcp-leases: Implement the remote protocol

2013-09-26 Thread Nehal J Wani
Implement RPC calls for virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC

daemon/remote.c
   * Define remoteSerializeNetworkDHCPLeases,
remoteDispatchNetworkGetDHCPLeases
   * Define remoteDispatchNetworkGetDHCPLeasesForMAC
   * Define helper function make_dhcp_lease

src/remote/remote_driver.c
   * Define remoteNetworkGetDHCPLeases
   * Define remoteNetworkGetDHCPLeasesForMAC
   * Define helper function make_dhcp_lease

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES
   * Define structs remote_network_dhcp_leases, 
remote_network_get_dhcp_leases_args,
remote_network_get_dhcp_leases_ret
   * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC
   * Define structs remote_network_dhcp_leases_for_mac, 
remote_network_get_dhcp_leases_for_mac_args,
remote_network_get_dhcp_leases_for_mac_ret

src/remote_protocol-structs
   * New structs added

src/rpc/gendispatch.pl
   * Add exception (s/Dhcp/DHCP) for auto-generating names of the remote 
functions
 in daemon/remote_dispatch.h

---
 daemon/remote.c  | 157 
 src/remote/remote_driver.c   | 169 ++-
 src/remote/remote_protocol.x |  59 ++-
 src/remote_protocol-structs  |  47 
 src/rpc/gendispatch.pl   |   1 +
 5 files changed, 429 insertions(+), 4 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 9497cc1..770f62a 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -88,6 +88,7 @@ static void 
make_nonnull_node_device(remote_nonnull_node_device *dev_dst, virNod
 static void make_nonnull_secret(remote_nonnull_secret *secret_dst, 
virSecretPtr secret_src);
 static void make_nonnull_nwfilter(remote_nonnull_nwfilter *net_dst, 
virNWFilterPtr nwfilter_src);
 static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot 
*snapshot_dst, virDomainSnapshotPtr snapshot_src);
+static void make_dhcp_lease(remote_network_dhcp_lease *lease_dst, 
virNetworkDHCPLeasesPtr lease_src);
 
 static virTypedParameterPtr
 remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
@@ -5209,6 +5210,136 @@ cleanup:
 }
 
 
+static int
+remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server ATTRIBUTE_UNUSED,
+   virNetServerClientPtr client,
+   virNetMessagePtr msg ATTRIBUTE_UNUSED,
+   virNetMessageErrorPtr rerr,
+   remote_network_get_dhcp_leases_args *args,
+   remote_network_get_dhcp_leases_ret *ret)
+{
+int rv = -1;
+size_t i;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virNetworkDHCPLeasesPtr *leases = NULL;
+virNetworkPtr net = NULL;
+int nleases = 0;
+
+if (!priv-conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open));
+goto cleanup;
+}
+
+if (!(net = get_nonnull_network(priv-conn, args-net)))
+goto cleanup;
+
+if ((nleases = virNetworkGetDHCPLeases(net,
+   args-need_results ? leases : NULL,
+   args-flags))  0)
+goto cleanup;
+
+if (nleases  REMOTE_NETWORK_DHCP_LEASES_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of leases is %d, which exceeds max limit: 
%d),
+   nleases, REMOTE_NETWORK_DHCP_LEASES_MAX);
+return -1;
+}
+
+if (leases  nleases) {
+if (VIR_ALLOC_N(ret-leases.leases_val, nleases)  0)
+goto cleanup;
+
+ret-leases.leases_len = nleases;
+for (i = 0; i  nleases; i++)
+make_dhcp_lease(ret-leases.leases_val + i, leases[i]);
+} else {
+ret-leases.leases_len = 0;
+ret-leases.leases_val = NULL;
+}
+
+ret-ret = nleases;
+
+rv = 0;
+
+cleanup:
+if (rv  0)
+virNetMessageSaveError(rerr);
+if (leases) {
+for (i = 0; i  nleases; i++)
+virNetworkDHCPLeaseFree(leases[i]);
+VIR_FREE(leases);
+}
+virNetworkFree(net);
+return rv;
+}
+
+
+static int
+remoteDispatchNetworkGetDHCPLeasesForMAC(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ 
remote_network_get_dhcp_leases_for_mac_args *args,
+ 
remote_network_get_dhcp_leases_for_mac_ret *ret)
+{
+int rv = -1;
+size_t i;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virNetworkDHCPLeasesPtr *leases = NULL;
+virNetworkPtr net = NULL;
+int nleases = 0;
+ 

[libvirt] [PATCHv4 3/4] net-dhcp-leases: Private implementation inside network driver

2013-09-26 Thread Nehal J Wani
By querying the driver for the path of the leases file for the given virtual
network and parsing it to retrieve info.

src/network/bridge_driver.c:
* Implement networkGetDHCPLeases
* Implement networkGetDHCPLeasesForMAC
* Implement networkGetDHCPLeasesHelper

---
 src/network/bridge_driver.c | 240 
 1 file changed, 240 insertions(+)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 8787bdb..e1c97c7 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -109,6 +109,29 @@ static int networkPlugBandwidth(virNetworkObjPtr net,
 virDomainNetDefPtr iface);
 static int networkUnplugBandwidth(virNetworkObjPtr net,
   virDomainNetDefPtr iface);
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX 2097152
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FIELDS:
+ *
+ * Macro providing the maximum number of fields in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FIELDS 5
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_SEPARATOR_FIELDS:
+ *
+ * Macro providing the maximum number of fields in the separator
+ * line in the DHCPv6 leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_SEPARATOR_FIELDS 2
+
 
 static virNetworkDriverStatePtr driverState = NULL;
 
@@ -2988,6 +3011,221 @@ cleanup:
 return ret;
 }
 
+/* This function parses the leases file of dnsmasq.
+ *
+ * An example of DHCPv4 leases file content:
+ *
+ * 1379024255 52:54:00:20:70:3d 192.168.105.240 * *
+ * 1379023351 52:54:00:b1:70:19 192.168.105.201 * *
+ *
+ * An example of DHCPv6 leases file content:
+ *
+ * 1380150262 52:54:00:2e:1d:22 192.168.122.80 * *
+ * 1380152517 52:54:00:72:0f:1e 192.168.122.119 * *
+ * duid 00:01:00:01:19:d3:ec:62:f0:4d:a2:8c:14:51
+ * 1380152445 3022114 2001:db8:ca2:2:1::92 * 
00:01:00:01:19:d6:0c:59:52:54:00:2e:1d:22
+ * 1380152453 7474974 2001:db8:ca2:2:1::4e * 
00:01:00:01:19:d5:e0:86:52:54:00:72:0f:1e
+ *
+ */
+static int
+networkGetDHCPLeasesHelper(virNetworkPtr network,
+   virNetworkObjPtr obj,
+   const char *mac,
+   virNetworkDHCPLeasesPtr **leases)
+{
+int rv = -1;
+size_t i = 0;
+size_t nleases = 0;
+char *lease_file = NULL;
+char **lease_fields = NULL;
+char *lease_entries = NULL;
+char *lease_entry = NULL;
+virNetworkDHCPLeasesPtr *leases_ret = NULL;
+virNetworkDHCPLeasesPtr lease = NULL;
+int lease_file_len = 0;
+bool ipv6 = false;
+bool need_results = !!leases;
+
+/* Retrieve leases file location */
+lease_file = networkDnsmasqLeaseFileNameDefault(network-name);
+
+if ((lease_file_len = virFileReadAll(lease_file,
+VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
+lease_entries))  0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Unable to read leases file: %s), lease_file);
+goto cleanup;
+}
+
+lease_entry = lease_entries[0] == '\0' ? NULL : lease_entries;
+
+while (lease_entry) {
+int nfields = 0;
+
+char *eol = strchr(lease_entry, '\n');
+*eol = '\0';
+
+/* Split the lease line */
+if (!(lease_fields = virStringSplit(lease_entry,  ,
+VIR_NETWORK_DHCP_LEASE_FIELDS)))
+goto error;
+
+nfields = virStringListLength(lease_fields);
+
+/* Forward lease_entry to the next lease */
+lease_entry = strchr(lease_entry, '\0');
+if (lease_entry - lease_entries + 1  lease_file_len)
+lease_entry++;
+else
+lease_entry = NULL;
+
+/* Ignore the separator line in case of DHCPv6 */
+if (nfields == VIR_NETWORK_DHCP_LEASE_SEPARATOR_FIELDS
+ STREQ(lease_fields[0], duid)) {
+ipv6 = true;
+virStringFreeList(lease_fields);
+continue;
+}
+
+if (nfields != VIR_NETWORK_DHCP_LEASE_FIELDS) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Number of lease params aren't equal to: %d),
+   VIR_NETWORK_DHCP_LEASE_FIELDS);
+goto error;
+}
+
+if (mac  virMacAddrCompare(mac, lease_fields[1])) {
+virStringFreeList(lease_fields);
+continue;
+}
+
+if (need_results) {
+if (VIR_ALLOC(lease)  0)
+goto error;
+
+/* Convert expirytime here */
+if (virStrToLong_ll(lease_fields[0], NULL, 10, 
(lease-expirytime))  0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _(Unable to convert lease expiry time to 
integer: %s),
+   lease_fields[0]);
+goto error;
+  

[libvirt] [PATCHv4 1/4] net-dhcp-leases: Implement the public APIs

2013-09-26 Thread Nehal J Wani
Introduce 3 new APIs, virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC
and virNetworkDHCPLeaseFree.

* virNetworkGetDHCPLeases: returns the dhcp leases information for a given
 virtual network.

 For DHCPv4, the information includes:
 - Expirytime
 - MAC Address
 - IPv4 address (with type and prefix)
 - Hostname (can be NULL)
 - Client ID (can be NULL)

 For DHCPv6, the information includes
 - Expirytime
 - IAID
 - IPv6 address (with type and prefix)
 - Hostname (can be NULL)
 - Client DUID

* virNetworkGetDHCPLeasesForMAC: returns the dhcp leases information for a
 given virtual network and specified MAC Address.

* virNetworkDHCPLeaseFree: allows the upper layer application to free the
 network interface object conveniently.

There is no support for flags, so user is expected to pass 0 for
both the APIs.

include/libvirt/libvirt.h.in:
  * Define virNetworkGetDHCPLeases
  * Define virNetworkGetDHCPLeasesForMAC
  * Define virNetworkDHCPLeaseFree

python/generator.py:
  * Skip the auto-generation for virNetworkGetDHCPLeases
  * Skip the auto-generation for virNetworkGetDHCPLeasesForMAC
  * Skip the auto-generation for virNetworkDHCPLeaseFree

src/driver.h:
  * Define networkGetDHCPLeases
  * Define networkGetDHCPLeasesForMAC

src/libvirt.c:
  * Implement virNetworkGetDHCPLeases
  * Implement virNetworkGetDHCPLeasesForMAC
  * Implement virNetworkDHCPLeaseFree

src/libvirt_public.syms:
  * Export the new symbols

---
 include/libvirt/libvirt.h.in |  36 +
 python/generator.py  |   3 +
 src/driver.h |  13 
 src/libvirt.c| 177 +++
 src/libvirt_public.syms  |   3 +
 5 files changed, 232 insertions(+)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 83c219e..557a4c1 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2800,6 +2800,42 @@ int virConnectNumOfDefinedInterfaces 
(virConnectPtr conn);
 int virConnectListDefinedInterfaces  (virConnectPtr conn,
   char **const names,
   int maxnames);
+
+typedef enum {
+VIR_IP_ADDR_TYPE_IPV4,
+VIR_IP_ADDR_TYPE_IPV6,
+
+#ifdef VIR_ENUM_SENTINELS
+VIR_IP_ADDR_TYPE_LAST
+#endif
+} virIPAddrType;
+
+typedef struct _virNetworkDHCPLeases virNetworkDHCPLeases;
+typedef virNetworkDHCPLeases *virNetworkDHCPLeasesPtr;
+struct _virNetworkDHCPLeases {
+long long expirytime;   /* Seconds since epoch */
+union {
+char *mac;  /* MAC address */
+unsigned long iaid; /* Identity association identifier (IAID) */
+} id;
+char *ipaddr;   /* IP address */
+char *hostname; /* Hostname */
+char *clientid; /* Client ID or DUID */
+int type;   /* virIPAddrType */
+unsigned int prefix;/* IP address prefix */
+};
+
+void virNetworkDHCPLeaseFree(virNetworkDHCPLeasesPtr lease);
+
+int virNetworkGetDHCPLeases(virNetworkPtr network,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
+int virNetworkGetDHCPLeasesForMAC(virNetworkPtr network,
+  const char *mac,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
 /*
  * virConnectListAllInterfaces:
  *
diff --git a/python/generator.py b/python/generator.py
index 12c14f1..1079d6c 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -461,6 +461,8 @@ skip_impl = (
 'virNodeGetCPUMap',
 'virDomainMigrate3',
 'virDomainMigrateToURI3',
+'virNetworkGetDHCPLeases',
+'virNetworkGetDHCPLeasesForMAC',
 )
 
 lxc_skip_impl = (
@@ -561,6 +563,7 @@ skip_function = (
 virTypedParamsGetString,
 virTypedParamsGetUInt,
 virTypedParamsGetULLong,
+'virNetworkDHCPLeaseFree',
 )
 
 lxc_skip_function = (
diff --git a/src/driver.h b/src/driver.h
index 8cd164a..e000b17 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1127,6 +1127,17 @@ typedef int
  int cookieinlen,
  unsigned int flags,
  int cancelled);
+typedef int
+(*virDrvNetworkGetDHCPLeases)(virNetworkPtr network,
+  virNetworkDHCPLeasesPtr **leases,
+  unsigned int flags);
+
+typedef int
+(*virDrvNetworkGetDHCPLeasesForMAC)(virNetworkPtr network,
+const char *mac,
+virNetworkDHCPLeasesPtr **leases,
+unsigned int flags);
+
 
 typedef struct _virDriver virDriver;
 typedef virDriver *virDriverPtr;
@@ -1458,6 +1469,8 @@ struct _virNetworkDriver 

[libvirt] [PATCHv4 4/4] net-dhcp-leases: Add virsh support

2013-09-26 Thread Nehal J Wani
Use virNetworkGetDHCPLeases and virNetworkGetDHCPLeasesForMAC in virsh.

The new feature supports the follwing methods:

1. Retrieve leases info for a given virtual network

2. Retrieve leases info for given network interface

tools/virsh-domain-monitor.c
   * Introduce new command : net-dhcp-leases
 Example Usage: net-dhcp-leases network [mac]

 virsh # net-dhcp-leases default6
 Expiry Time  MAC address / IAIDProtocol   IP address   
 Hostname Client ID / DUID
 
---
 2013-09-26 12:46:15  140483776435424   ipv6   
2001:db8:ca2:2:1::92/24   (null)   00:01:00:01:19:d6:0c:59:52:54:00:2e:1d:22
 2013-09-26 12:26:29  140483776438128   ipv6   
2001:db8:ca2:2:1::4e/24   (null)   00:01:00:01:19:d5:e0:86:52:54:00:72:0f:1e
 2013-09-26 12:34:31  52:54:00:2e:1d:22 ipv4   
192.168.122.80/24 (null)   (null)
 2013-09-26 12:13:24  52:54:00:72:0f:1e ipv4   
192.168.122.119/24(null)   (null)

tools/virsh.pod
   * Document new command

---
 tools/virsh-network.c | 150 ++
 tools/virsh.pod   |   6 ++
 2 files changed, 156 insertions(+)

diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 8ddd5ca..5786ca2 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -1129,6 +1129,150 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd)
 
 return ret;
 }
+/*
+ * net-dhcp-leases command
+ */
+static const vshCmdInfo info_network_dhcp_leases[] = {
+{.name = help,
+ .data = N_(print lease info for a given network)
+},
+{.name = desc,
+ .data = N_(Print lease info for a given network)
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_network_dhcp_leases[] = {
+{.name = network,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_(network name or uuid)
+},
+{.name = mac,
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_NONE,
+ .help = N_(MAC address)
+},
+{.name = NULL}
+};
+
+static int
+vshNetworkDHCPLeaseSorter(const void *a, const void *b)
+{
+char *id1 = NULL;
+char *id2 = NULL;
+int rv = -1;
+
+virNetworkDHCPLeasesPtr *lease1 = (virNetworkDHCPLeasesPtr *) a;
+virNetworkDHCPLeasesPtr *lease2 = (virNetworkDHCPLeasesPtr *) b;
+
+if (*lease1  !*lease2)
+return -1;
+
+if (!*lease1)
+return *lease2 != NULL;
+
+
+switch ((*lease1)-type) {
+case VIR_IP_ADDR_TYPE_IPV4:
+ignore_value(virAsprintf(id1, %s, (*lease1)-id.mac));
+break;
+case VIR_IP_ADDR_TYPE_IPV6:
+ignore_value(virAsprintf(id1, %lu, (*lease1)-id.iaid));
+break;
+}
+switch ((*lease2)-type) {
+case VIR_IP_ADDR_TYPE_IPV4:
+ignore_value(virAsprintf(id2, %s, (*lease2)-id.mac));
+break;
+case VIR_IP_ADDR_TYPE_IPV6:
+ignore_value(virAsprintf(id2, %lu, (*lease2)-id.iaid));
+break;
+}
+
+rv = vshStrcasecmp(id1, id2);
+VIR_FREE(id1);
+VIR_FREE(id2);
+return rv;
+}
+
+static bool
+cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd)
+{
+const char *name = NULL;
+const char *mac = NULL;
+virNetworkDHCPLeasesPtr *leases = NULL;
+int nleases = 0;
+bool ret = false;
+size_t i;
+unsigned int flags = 0;
+virNetworkPtr network = NULL;
+
+if (vshCommandOptString(cmd, mac, mac)  0)
+return false;
+
+if (!(network = vshCommandOptNetwork(ctl, cmd, name)))
+return false;
+
+nleases = mac ? virNetworkGetDHCPLeasesForMAC(network, mac, leases, flags)
+: virNetworkGetDHCPLeases(network, leases, flags);
+
+if (nleases  0) {
+vshError(ctl, _(Failed to get leases info for %s), name);
+goto cleanup;
+}
+
+/* Sort the list according to MAC Address/IAID */
+qsort(leases, nleases, sizeof(*leases), vshNetworkDHCPLeaseSorter);
+
+vshPrintExtra(ctl,  %-20s %-25s %-10s %-25s %-12s %s\n%s%s\n,
+  _(Expiry Time), _(MAC address / IAID), _(Protocol),
+  _(IP address), _(Hostname), _(Client ID / DUID),
+  --,
+  -);
+
+for (i = 0; i  nleases; i++) {
+const char *type = NULL;
+char *id = NULL;
+char *cidr_format = NULL;
+virNetworkDHCPLeasesPtr lease = leases[i];
+time_t expirytime_tmp = lease-expirytime;
+struct tm ts;
+char expirytime[32];
+ts = *localtime_r(expirytime_tmp, ts);
+strftime(expirytime, sizeof(expirytime), %Y-%m-%d %H:%M:%S, ts);
+
+switch (lease-type) {
+case VIR_IP_ADDR_TYPE_IPV4:
+type = ipv4;
+ignore_value(virAsprintf(id, %s, lease-id.mac));
+ 

Re: [libvirt] [PATCHv4 1/4] net-dhcp-leases: Implement the public APIs

2013-10-01 Thread Nehal J Wani
Since we have lost the train for 1.1.3, changes in
a/src/libvirt_public.syms attached.


-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


1.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 2/4] net-dhcp-leases: Implement the remote protocol

2013-10-01 Thread Nehal J Wani
In accordance with latest changes in rules for making building
src/remote_protocol-structs, diff attached.

-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


2.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 3/4] net-dhcp-leases: Private implementation inside network driver

2013-10-01 Thread Nehal J Wani
Removing redundant if, diff attached.

-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


3.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 4/4] net-dhcp-leases: Add virsh support

2013-10-01 Thread Nehal J Wani
In accordance with latest rule: use VIR_STRDUP instead of virAsprintf with %s
Diff attached.

-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


4.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 4/4] net-dhcp-leases: Add virsh support

2013-10-01 Thread Nehal J Wani
Rectified attachment.


-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


4.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 1/4] net-dhcp-leases: Implement the public APIs

2013-10-01 Thread Nehal J Wani
Rectified attachment.

-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


1.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 3/4] net-dhcp-leases: Private implementation inside network driver

2013-10-01 Thread Nehal J Wani
Rectified attachment.
-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


3.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 2/4] net-dhcp-leases: Implement the remote protocol

2013-10-01 Thread Nehal J Wani
Rectified attachment.

-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad


2.diff
Description: Binary data
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 1/4] net-dhcp-leases: Implement the public APIs

2013-10-01 Thread Nehal J Wani
 I sense some struggle in getting the interface right - for everyone's
 sake, let's FIRST get the interface nailed down, rather than churning on
 implementations of something that then has to be reworked because the
 interface wasn't correct.

Agreed. I hope we can have some discussion on whether we should be
supporting DHCPv6 or not, and how should IAID be exposed, if we do.

-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCHv4 1/4] net-dhcp-leases: Implement the public APIs

2013-10-01 Thread Nehal J Wani
According to commit 2d5cd1d724084d9975b2514fb31776627acbe997, libvirt
supports DHCPv6. The virNetworkGetDHCPLeases API doesn't mention
anywhere (in its name) that it is specific to DHCPv4. Hence I thought
of adding the support for DHCPv6.  Since the format for DHCPv6 leases
is a bit different, it might be difficult to add it in the future by
modifying the API. To understand the format for DHCPv6 better, one can
follow the conversation:
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2013q3/007538.html
and the RFC: https://tools.ietf.org/html/rfc3315


-- 
Nehal J Wani

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCHv4 1/4] net-dhcp-leases: Implement the public APIs

2013-10-02 Thread Nehal J Wani
On Wed, Oct 2, 2013 at 1:43 PM, Daniel P. Berrange berra...@redhat.com wrote:
 On Tue, Oct 01, 2013 at 05:39:02PM -0600, Eric Blake wrote:
 On 09/26/2013 02:08 AM, Nehal J Wani wrote:
  Introduce 3 new APIs, virNetworkGetDHCPLeases, 
  virNetworkGetDHCPLeasesForMAC
  and virNetworkDHCPLeaseFree.
 
  * virNetworkGetDHCPLeases: returns the dhcp leases information for a given
   virtual network.
 
   For DHCPv4, the information includes:
   - Expirytime
   - MAC Address
   - IPv4 address (with type and prefix)
   - Hostname (can be NULL)
   - Client ID (can be NULL)
 
   For DHCPv6, the information includes
   - Expirytime
   - IAID
   - IPv6 address (with type and prefix)
   - Hostname (can be NULL)
   - Client DUID
 
  * virNetworkGetDHCPLeasesForMAC: returns the dhcp leases information for a
   given virtual network and specified MAC Address.
 
  * virNetworkDHCPLeaseFree: allows the upper layer application to free the
   network interface object conveniently.
 
  There is no support for flags, so user is expected to pass 0 for
  both the APIs.


  +typedef struct _virNetworkDHCPLeases virNetworkDHCPLeases;
  +typedef virNetworkDHCPLeases *virNetworkDHCPLeasesPtr;
  +struct _virNetworkDHCPLeases {
  +long long expirytime;   /* Seconds since epoch */
  +union {
  +char *mac;  /* MAC address */
  +unsigned long iaid; /* Identity association identifier (IAID) 
  */
  +} id;

 I'm not sure I like iaid - the whole point of this interface was to
 return IP addresses associated with a MAC.  Either the iaid is important
 and deserves a separate field, or all we care about is the MAC address.
  Not to mention that you didn't document which leg of the id union is
 valid based on the type discriminator.

 Agreed, we want the MAC address to be unconditionally available
 here. IMHO the IAID is not something we care about exposing. That
 is a impl detail of the DHCP comms protocol that is not useful
 to people outside.


So in case DHCPv6 is used by the client, should we report the rest of
the lease fields and report MAC as NULL?



 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 :|



-- 
Nehal J Wani
UG3, BTech CS+MS(CL)
IIIT-Hyderabad
http://commandlinewani.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


  1   2   3   >