<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.0">Jekyll</generator><link href="http://www.petrospetrou.co.uk/feed.xml" rel="self" type="application/atom+xml" /><link href="http://www.petrospetrou.co.uk/" rel="alternate" type="text/html" /><updated>2026-02-20T10:24:52-06:00</updated><id>http://www.petrospetrou.co.uk/feed.xml</id><title type="html">Cloud Infra Opensource…</title><subtitle>Personal and Technical Blog about me, Cloud Technologies and Open Source...</subtitle><entry><title type="html">Network outage simulation in libvirt using netfilter</title><link href="http://www.petrospetrou.co.uk/virtualization/2024/09/23/libvirt-net-filter.html" rel="alternate" type="text/html" title="Network outage simulation in libvirt using netfilter" /><published>2024-09-23T16:00:00-05:00</published><updated>2024-09-23T16:00:00-05:00</updated><id>http://www.petrospetrou.co.uk/virtualization/2024/09/23/libvirt-net-filter</id><content type="html" xml:base="http://www.petrospetrou.co.uk/virtualization/2024/09/23/libvirt-net-filter.html">&lt;p&gt;As I tend to work in cluster configuration and administration one of the most tricky tasks is how to
test network outage in a virtualized environment.&lt;/p&gt;

&lt;p&gt;One solution is to disable the network interface or set firewall rules but this is more of a hack
as we are configuring this in the OS. A better approach is to use the 
libvirt &lt;a href=&quot;https://libvirt.org/formatnwfilter.html&quot; target=&quot;_blank&quot;&gt;netfilter&lt;/a&gt; which is configured at the
hypervisor.&lt;/p&gt;

&lt;p&gt;As an example I will block unicast traffic between two KVMs using the sender MAC address.&lt;/p&gt;

&lt;p&gt;I will define my filter in an XML file and name it block_unicast_traffic.xml&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;filter name='block-unicast-traffic' chain='ipv4'&amp;gt;
  &amp;lt;rule action='drop' direction='inout'&amp;gt;
      &amp;lt;ip protocol='udp' srcmacaddr='$SENDER_MAC' /&amp;gt;
  &amp;lt;/rule&amp;gt;
&amp;lt;/filter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The filter will use the ipv4 protocol-specific filtering chain and we will use a simple
rule to drop packages that originate from a specific MAC address. We are defining the MAC address
by using the custom $SENDER_MAC parameter.&lt;/p&gt;

&lt;p&gt;The next step is to create the netfilter in libvirt using virsh and nwfilter-define.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;virsh # nwfilter-define --file /home/ppetrou/Dev/libvirt_netfilter_samples/block_unicast_traffic.xml
Network filter block-unicast-traffic defined from /home/ppetrou/Dev/libvirt_netfilter_samples/block_unicast_traffic.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next step is to create a netfilter binding as we need to bind the filter with a network interface of a KVM.
We could do this just by adding a filterref element in the domain XML in the interface element but this would make
things complex if we wanted to add/remove the filter on the fly without having to reboot the KVM.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;devices&amp;gt;
  &amp;lt;interface type='bridge'&amp;gt;
    &amp;lt;mac address='00:16:3e:5d:c7:9e'/&amp;gt;
    &amp;lt;filterref filter='clean-traffic'/&amp;gt;
  &amp;lt;/interface&amp;gt;
&amp;lt;/devices&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The filter binding can be added and removed from a KVM when the KVM is powered on so this can ease our testing
on when connectivity is lost or resumed.&lt;/p&gt;

&lt;p&gt;In the owner element we MUST define the KVM name and its UUID. You can get this from the domain XML of the KVM.
The portdev element is mandatory and defines the virtual network port name of the interface we want to bind the filter.
The mac element is the mac address of the interface we want to bind the filter.&lt;/p&gt;

&lt;p&gt;The most important part is the filterref element were we define the filter and also initialize any parameters.
In this case we need to initialize the $SENDER_MAC parameter with the MAC address of the sender.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;filterbinding&amp;gt;
  &amp;lt;owner&amp;gt;
    &amp;lt;name&amp;gt;vm1&amp;lt;/name&amp;gt;
    &amp;lt;uuid&amp;gt;80d59483-aec0-4d9f-b5f0-55f39ad1871e&amp;lt;/uuid&amp;gt;
  &amp;lt;/owner&amp;gt;
  &amp;lt;portdev name='vnet1'/&amp;gt;
  &amp;lt;mac address='52:54:00:83:73:8a'/&amp;gt;
  &amp;lt;filterref filter='block-unicast-traffic'&amp;gt;
    &amp;lt;parameter name='SENDER_MAC' value='52:54:00:fc:ee:d4'/&amp;gt;
  &amp;lt;/filterref&amp;gt;
&amp;lt;/filterbinding&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to test this we will use two KVMs.
The network interface which we will use is the enp7s0 and has the portdev name vnet1.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@node1 ~]# 
[root@node1 ~]# nmcli con show
NAME                UUID                                  TYPE      DEVICE 
enp1s0              8660f145-f5c6-46c1-995f-33460a027c47  ethernet  enp1s0 
Wired connection 1  51fdfc6c-df5e-35f3-a7bb-c11bf2c18676  ethernet  enp7s0 
Wired connection 2  abf63925-a804-391c-859a-498f6d1bb4fe  ethernet  enp8s0 
[root@node1 ~]# 
[root@node1 ~]# ip a show enp7s0
3: enp7s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:83:73:8a brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.182/24 brd 192.168.100.255 scope global dynamic noprefixroute enp7s0
       valid_lft 2560sec preferred_lft 2560sec
    inet6 fe80::88ca:707f:1bc3:d496/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@node1 ~]# 
[root@node1 ~]# 

[root@node2 ~]# nmcli con show
NAME                UUID                                  TYPE      DEVICE 
enp1s0              8660f145-f5c6-46c1-995f-33460a027c47  ethernet  enp1s0 
Wired connection 1  9500b4e5-f052-32b0-8cd4-0557250f55b0  ethernet  enp7s0 
Wired connection 2  50ed8da0-0cf7-34f1-a5d4-46b17d3f593c  ethernet  enp8s0 
[root@node2 ~]# 
[root@node2 ~]# ip a show enp7s0
3: enp7s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:fc:ee:d4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.201/24 brd 192.168.100.255 scope global dynamic noprefixroute enp7s0
       valid_lft 2479sec preferred_lft 2479sec
    inet6 fe80::daae:eb36:f3c3:d2e8/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[root@node2 ~]# 
[root@node2 ~]# 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First we wil test that connectivity is OK.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@node2 ~]# nc -vu 192.168.100.182 2233
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.100.182:2233.
test


[root@node1 ~]# nc -lvu 192.168.100.182 2233
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on 192.168.100.182:2233
Ncat: Connection from 192.168.100.201.
test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and then we will apply the netfilter binding and re-test to check that connectivity is lost&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;virsh # nwfilter-binding-create --file /home/ppetrou/Dev/libvirt_netfilter_samples/block_unicast_binding_vm1.xml 
Network filter binding on vnet1 created from /home/ppetrou/Dev/libvirt_netfilter_samples/block_unicast_binding_vm1.xml

[root@node2 ~]# nc -vu 192.168.100.182 2233
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.100.182:2233.
test
test2 &amp;lt;-- this message never arrives to node1
test3 &amp;lt;-- same this one
test4 &amp;lt;-- same this one

[root@node1 ~]# nc -lvu 192.168.100.182 2233
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on 192.168.100.182:2233
Ncat: Connection from 192.168.100.201.
test
     &amp;lt;-- no new messages
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we will remove the netfilter binding&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;virsh # nwfilter-binding-list 
 Port Dev   Filter
-----------------------------------
 vnet1      block-unicast-traffic

virsh # 
virsh # nwfilter-binding-delete --binding vnet1 
Network filter binding on vnet1 deleted

[root@node2 ~]# nc -vu 192.168.100.182 2233
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.100.182:2233.
test
test2
test3
test4
test5 &amp;lt;-- newer message is received in node1

[root@node1 ~]# nc -lvu 192.168.100.182 2233
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on 192.168.100.182:2233
Ncat: Connection from 192.168.100.201.
test
test5 &amp;lt;-- newer message
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can find the XML artefacts in my &lt;a href=&quot;https://github.com/ppetrou/libvirt_netfilter_samples&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That’s it. I hope you found this blog useful.&lt;/p&gt;

&lt;p&gt;Thank you,&lt;/p&gt;

&lt;p&gt;Petros&lt;/p&gt;</content><author><name></name></author><category term="virtualization" /><category term="libvirtd," /><category term="network," /><category term="netfilter" /><summary type="html">As I tend to work in cluster configuration and administration one of the most tricky tasks is how to test network outage in a virtualized environment.</summary></entry><entry><title type="html">Who does the DNS Lookup? The browser or the operating system?</title><link href="http://www.petrospetrou.co.uk/os/2022/10/10/dns-browser-vs-os-lookup.html" rel="alternate" type="text/html" title="Who does the DNS Lookup? The browser or the operating system?" /><published>2022-10-10T14:00:00-05:00</published><updated>2022-10-10T14:00:00-05:00</updated><id>http://www.petrospetrou.co.uk/os/2022/10/10/dns-browser-vs-os-lookup</id><content type="html" xml:base="http://www.petrospetrou.co.uk/os/2022/10/10/dns-browser-vs-os-lookup.html">&lt;p&gt;A common interview question for infrastructure roles is “Who does the DNS Lookup? The browser or the Operating System”. A few years ago when I had this question from a UK FS Consultancy, my mind started spinning and was doing endless loops on what could be the correct answer. As a passionate programmer I tend to overthink and my mind generates lots of possible solutions so I was not sure. I ended up replying “The Browser” and since this day I always wanted to research this further and see if this was correct or not :)&lt;/p&gt;

&lt;p&gt;In this blog I will present my analysis on this and walk you through the DNS lookup process.&lt;/p&gt;

&lt;p&gt;First we need to analyse each term in the question:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Who does? -&amp;gt; Do we mean initiate the call or do the actual lookup on the nameserver?&lt;/li&gt;
  &lt;li&gt;DNS Lookup -&amp;gt; An API call that takes as an argument a URL (e.g. petrospetrou.co.uk) and returns its IP address (e.g. 173.236.127.52).&lt;/li&gt;
  &lt;li&gt;Browser -&amp;gt; An application which provides access to the World Wide Web&lt;/li&gt;
  &lt;li&gt;Operating System -&amp;gt; This can be a bit complex to define. Do we mean just the kernel? Do we include standard libraries? More on this towards the end.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now lets see how a DNS Lookup works…&lt;/p&gt;

&lt;p&gt;When an application such as a web browser needs to resolve a hostname to an IP address it requires a DNS Lookup. This will query a name server and return the IP address of the hostname. A typical example is the dig utility.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ppetrou@fedora root]$
[ppetrou@fedora root]$ dig www.petrospetrou.co.uk

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.16.33-RH &amp;lt;&amp;lt;&amp;gt;&amp;gt; www.petrospetrou.co.uk
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 58067
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.petrospetrou.co.uk.		IN	A

;; ANSWER SECTION:
www.petrospetrou.co.uk.	672	IN	CNAME	petrospetrou.co.uk.
petrospetrou.co.uk.	146	IN	A	173.236.127.52

;; Query time: 0 msec
;; SERVER: 192.168.2.1#53(192.168.2.1)
;; WHEN: Sat Oct 08 21:00:56 BST 2022
;; MSG SIZE  rcvd: 99
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But how is the DNS Lookup implemented?&lt;/p&gt;

&lt;p&gt;In order to explain this we will see Linux as the OS and C as the language that the application is implemented. Something similar exists in other languages and Operating Systems but we have no access to their source code so we cannot elaborate further.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.gnu.org/software/libc/libc.html&quot; target=&quot;_blank&quot;&gt;Standard C Library&lt;/a&gt; has a header file &lt;a href=&quot;https://github.com/bminor/glibc/blob/master/resolv/netdb.h&quot; target=&quot;_blank&quot;&gt;netdb.h&lt;/a&gt; with definitions for network database operations. This is part of the &lt;a href=&quot;https://tldp.org/LDP/nag2/x-087-2-resolv.library.html&quot; target=&quot;_blank&quot;&gt;resolver library&lt;/a&gt; which includes the following two methods.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;gethostbyname()&lt;/li&gt;
  &lt;li&gt;gethostbyaddr()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When an application requires a DNS Lookup it can use the gethostbyname() function in order to resolve the hostname. You can find a simple C program that does this &lt;a href=&quot;https://paulschreiber.com/blog/2005/10/28/simple-gethostbyname-example/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to see this in a known application we can search the &lt;a href=&quot;http://invisible-island.net/datafiles/release/lynx-cur.zip&quot; target=&quot;_blank&quot;&gt;source code&lt;/a&gt; of the text based &lt;a href=&quot;https://lynx.invisible-island.net/lynx.html&quot; target=&quot;_blank&quot;&gt;Lynx&lt;/a&gt; browser. I have no time to analyse the code properly but we can see that there are multiple references to the gethostbyname() function.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ppetrou@fedora lynx2.9.0dev.10]$ grep -R gethostbyname *
.
.
WWW/Library/Implementation/HTTCP.c:	gbl_phost = gethostbyname(host);
WWW/Library/Implementation/HTTCP.c:    gbl_phost = gethostbyname(host);
WWW/Library/Implementation/HTTCP.c:     * fork-based gethostbyname() with checks for interrupts.
WWW/Library/Implementation/HTTCP.c:			HTInetStatus(&quot;CHILD gethostbyname&quot;);
WWW/Library/Implementation/HTTCP.c:	    CTRACE((tfp, &quot;%s: INTERRUPTED gethostbyname.\n&quot;, this_func));
WWW/Library/Implementation/HTTCP.c:static void really_gethostbyname(const char *host,
WWW/Library/Implementation/HTTCP.c:    phost = gethostbyname(host);
WWW/Library/Implementation/HTTCP.c:    CTRACE((tfp, &quot;really_gethostbyname() returned %d\n&quot;, phost));
WWW/Library/Implementation/HTTCP.c:    dump_hostent(&quot;CHILD gethostbyname&quot;, phost);
WWW/Library/Implementation/HTTCP.c:/*	Resolve an internet hostname, like gethostbyname
WWW/Library/Implementation/HTTCP.c: *  gethostbyname(), except for the following:
WWW/Library/Implementation/HTTCP.c: *  If NSL_FORK is not used, the result of gethostbyname is returned
WWW/Library/Implementation/HTTCP.c:#ifdef MVS			/* Outstanding problem with crash in MVS gethostbyname */
WWW/Library/Implementation/HTTCP.c:    CTRACE((tfp, &quot;%s: Calling gethostbyname(%s)\n&quot;, this_func, host));
WWW/Library/Implementation/HTTCP.c:    if (!setup_nsl_fork(really_gethostbyname,
WWW/Library/Implementation/HTTCP.c:		gbl_phost = gethostbyname(host);
WWW/Library/Implementation/HTTCP.c:	phost = gethostbyname(host);	/* See netdb.h */
WWW/Library/Implementation/HTTCP.c:	CTRACE((tfp, &quot;%s: gethostbyname() returned %d\n&quot;, this_func, phost));
WWW/Library/Implementation/HTTCP.c:#ifdef MVS			/* Outstanding problem with crash in MVS gethostbyname */
WWW/Library/Implementation/HTTCP.c:    phost = gethostbyname(name);	/* See netdb.h */
WWW/Library/Implementation/HTTCP.h:/*	Resolve an internet hostname, like gethostbyname
WWW/Library/Implementation/HTTCP.h: *  The interface is intended to be the same as for gethostbyname(),
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Taking things a bit further we can also search for the same in the linux kernel &lt;a href=&quot;https://github.com/torvalds/linux&quot; target=&quot;_blank&quot;&gt;source code&lt;/a&gt; and see if there are any references there.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ppetrou@fedora linux]$ ls
arch   certs    CREDITS  Documentation  fs       init      ipc     Kconfig  lib       MAINTAINERS  mm   README   scripts   sound  usr
block  COPYING  crypto   drivers        include  io_uring  Kbuild  kernel   LICENSES  Makefile     net  samples  security  tools  virt
[ppetrou@fedora linux]$
[ppetrou@fedora linux]$ grep -R gethostbyname *
[ppetrou@fedora linux]$
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As expected no references exist so the browser does the DNS Lookup… or NOT?? :)&lt;/p&gt;

&lt;p&gt;If we go back to the beginning of the blog where we analysed the terms of the question we see that we raised of few ambiguities…&lt;/p&gt;

&lt;p&gt;If we consider that “does” means initiates then yes the browser does the DNS Lookup as the gethostbyname() function is called within the browser code.
On the contrary if “does” means the lookup of the host in the nameserver then this gets executed by the &lt;a href=&quot;https://tldp.org/LDP/nag2/x-087-2-resolv.library.html&quot; target=&quot;_blank&quot;&gt;resolver&lt;/a&gt; which is part of the &lt;a href=&quot;https://www.gnu.org/software/libc/libc.html&quot; target=&quot;_blank&quot;&gt;Standard C Library&lt;/a&gt; and is considered part of the operating system. It also cannot be removed as it includes lots of libraries such as the resolver or sudo, which could make the OS unusable. See below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@lab1 ~]# sudo dnf remove glibc
Error:
 Problem: The operation would result in removing the following protected packages: sudo
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)
[root@lab1 ~]#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So the call sequence from the browser to the name server is the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Web browser -&amp;gt; glibc -&amp;gt; resolver -&amp;gt; gethostbyname() -&amp;gt; nameserver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also what we have proved from this analysis is that the kernel DOES NOT do the DNS Lookup in any case!&lt;/p&gt;

&lt;p&gt;I hope you enjoyed reading this blog as much I did when I was researching the topic. If you have any comments please leave them below.&lt;/p&gt;

&lt;p&gt;Thank you,&lt;/p&gt;

&lt;p&gt;Petros&lt;/p&gt;</content><author><name></name></author><category term="os" /><category term="dns," /><category term="linux," /><category term="resolver" /><summary type="html">A common interview question for infrastructure roles is “Who does the DNS Lookup? The browser or the Operating System”. A few years ago when I had this question from a UK FS Consultancy, my mind started spinning and was doing endless loops on what could be the correct answer. As a passionate programmer I tend to overthink and my mind generates lots of possible solutions so I was not sure. I ended up replying “The Browser” and since this day I always wanted to research this further and see if this was correct or not :)</summary></entry><entry><title type="html">How to write vmware pyvmomi mocked unit tests</title><link href="http://www.petrospetrou.co.uk/vmware/2021/06/13/mock-esxi.html" rel="alternate" type="text/html" title="How to write vmware pyvmomi mocked unit tests" /><published>2021-06-13T13:00:00-05:00</published><updated>2021-06-13T13:00:00-05:00</updated><id>http://www.petrospetrou.co.uk/vmware/2021/06/13/mock-esxi</id><content type="html" xml:base="http://www.petrospetrou.co.uk/vmware/2021/06/13/mock-esxi.html">&lt;p&gt;I have recently been doing some vmware api development work using pyvmomi and one of the issues I had is how we can unit test without a vSphere Installation. The solution is to mock the pyvmomi api but it turned out that it was a much more complex task than I initially thought, so here are my findings.&lt;/p&gt;

&lt;p&gt;I will not go into depth of the &lt;a href=&quot;https://pypi.org/project/pyvmomi/&quot; target=&quot;_blank&quot;&gt;pyvmomi api&lt;/a&gt; or the &lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html&quot; target=&quot;_blank&quot;&gt;python mock object library&lt;/a&gt; as I assume anyone who will need to mock it would have the sufficient knowledge of both.&lt;/p&gt;

&lt;p&gt;The pyvmomi wrapper class I have developed is VmwareUtil and I am using the context manager VmwareOpen to manage the lifecycle of the pyVim.connect.SmartConnectNoSSL which provides a &lt;a href=&quot;https://vdc-download.vmware.com/vmwb-repository/dcr-public/b50dcbbf-051d-4204-a3e7-e1b618c1e384/538cf2ec-b34f-4bae-a332-3820ef9e7773/vim.ServiceInstance.html&quot; target=&quot;_blank&quot;&gt;vim.ServiceInstance&lt;/a&gt;. This is the root object of the vCenter/ESXi inventory.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyVim.connect&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SmartConnectNoSSL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Disconnect&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyVmomi&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmodl&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VmwareOpen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_host&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__enter__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_service_instance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SmartConnectNoSSL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_service_instance&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;IOError&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__exit__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;traceback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Disconnect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_service_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VmwareUtil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmwarehost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmwareport&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_host&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmwarehost&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmwareport&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_get_vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RetrieveContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;vmlist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;child&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rootFolder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;childEntity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hasattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'vmFolder'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;datacenter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;vmfolder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datacenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vmFolder&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;vmlist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmfolder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;childEntity&lt;/span&gt;
                
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identity&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uuid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;identity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; not found.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_uuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VmwareOpen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_get_vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service_instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uuid&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tryme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vmware_util&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VmwareUtil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;192.168.122.168&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;443&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vmuuid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmware_util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_uuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test_vm_00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UUID : &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmuuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tryme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As the simplest example I will just implement a method which will return the UUID of a Virtual Machine by passing its name.&lt;/p&gt;

&lt;p&gt;In order to do this we first need to access the Service Instance Content &lt;a href=&quot;https://vdc-download.vmware.com/vmwb-repository/dcr-public/b50dcbbf-051d-4204-a3e7-e1b618c1e384/538cf2ec-b34f-4bae-a332-3820ef9e7773/vim.ServiceInstanceContent.html&quot; target=&quot;_blank&quot;&gt;vim.ServiceInstanceContent&lt;/a&gt; using the RetrieveContent method of the &lt;a href=&quot;https://vdc-download.vmware.com/vmwb-repository/dcr-public/b50dcbbf-051d-4204-a3e7-e1b618c1e384/538cf2ec-b34f-4bae-a332-3820ef9e7773/vim.ServiceInstance.html&quot; target=&quot;_blank&quot;&gt;vim.ServiceInstance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This will give us access to a set of Managed Objects in the inventory. The rootFolder is the root of the inventory and we need to look for the datacenter object &lt;a href=&quot;https://vdc-download.vmware.com/vmwb-repository/dcr-public/b50dcbbf-051d-4204-a3e7-e1b618c1e384/538cf2ec-b34f-4bae-a332-3820ef9e7773/vim.Datacenter.html&quot; target=&quot;_blank&quot;&gt;vim.Datacenter&lt;/a&gt;. This would be the child which has the attribute vmFolder. There should be a more efficient way of doing this such as using the instanceof function but I kept the lookup code as it was in the &lt;a href=&quot;https://github.com/vmware/pyvmomi-community-samples&quot; target=&quot;_blank&quot;&gt;pyvmomi community samples&lt;/a&gt;. The last step is to loop the children of the vmFolder and find the vm we look for based on name or uuid.&lt;/p&gt;

&lt;p&gt;Now the hard stuff and the mocking bit.&lt;/p&gt;

&lt;p&gt;The main issue I had is that all the pyvmomi objects are server managed so we cannot just instantiate and populate them at client side. This is why we need to mock the whole lot.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unittest&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unittest&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unittest.mock&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patch&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;vmware_util&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VmwareUtil&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyVim.connect&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SmartConnectNoSSL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Disconnect&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyVmomi&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmodl&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestVMwareUtil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;patch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'vmware_util.VmwareOpen'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_uuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmware_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Initialize the Config Summary
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;test_vm_00_config_summary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ConfigSummary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;test_vm_00_config_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test_vm_00&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;test_vm_00_config_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uuid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c7a5fdbd-cdaf-9455-926a-d65c16db1809&quot;&lt;/span&gt;
         
        &lt;span class=&quot;c1&quot;&gt;# Initialize VM Summary 
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;test_vm_00_summary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;test_vm_00_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_vm_00_config_summary&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Initialize the Mock VM
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;test_vm_00&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VirtualMachine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vm-41&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;test_vm_00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_vm_00_summary&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Initialize the Data Center and add the Mock VM
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Create the vmFolder       
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;vm_folder_mock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vm-folder&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vm_folder_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;childType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vim.Folder&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vim.Virtualmachine&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vim.VirtualApp&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;       
        &lt;span class=&quot;c1&quot;&gt;# Add it to the Data Center and add the VM in the children
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;ds_mock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Datacenter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ds-00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ds_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vmFolder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_folder_mock&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ds_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vmFolder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;childEntity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_vm_00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Initialize the Service Instance Mock and add the Data Center
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Create the rootFolder
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;root_folder_mock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;root-folder&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;root_folder_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;childEntity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ds_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Create the Service Instance and add the rootFolder
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;si_mock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;si-00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;si_content_mock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceInstanceContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;si_content_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rootFolder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root_folder_mock&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Mock the RetrieveContent Methos in the service instance
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;si_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RetrieveContent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;si_content_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;#si_mock.RetrieveContent.side_effect = Exception('Boom!')
&lt;/span&gt;        
        &lt;span class=&quot;c1&quot;&gt;# Get the VmwareOpen reference
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;vm_mock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmware_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return_value&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Mock the enter and exit methods
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;vm_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__enter__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;si_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vm_mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__exit__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MagicMock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Call the VMWare Util as normal. Any vmware_util.VmwareOpen reference within the function call will be replaced by the mocked object.
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;vmware_util&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VmwareUtil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;returned_uuid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmware_util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_uuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test_vm_00&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         
        &lt;span class=&quot;c1&quot;&gt;# Assert
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'c7a5fdbd-cdaf-9455-926a-d65c16db1809'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returned_uuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'__main__'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The hierarchy inside the ServiceInstanceContent is the following so we need to mock in reverve order.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
+-- ServiceInstanceContent
    +-- rootFolder
        +-- dataCenter
            +-- vmFolder
                +-- childEntity
                    +-- VirtualMachine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The next step is to mock the RetrieveContent method and assign the mocked ServiceInstanceContent as its returned object and the last step is to mock the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__enter__&lt;/code&gt; method of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmware_util.VmwareOpen&lt;/code&gt; class which is the context manager for the ServiceInstance. We use the mock.patch function decorator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@mock.patch('vmware_util.VmwareOpen')&lt;/code&gt; in the test_uuid() function so every time we ran the unit test, any reference to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmware_util.VmwareOpen&lt;/code&gt; will be replaced with the patched object so there will be no real call to the VMWare Hypervisor but the mocked object will be returned instead. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmware_util.VmwareOpen&lt;/code&gt; reference is at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with VmwareOpen(self._host, self._port, self._username, self._password) as service_instance:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can find the code listings in my &lt;a href=&quot;https://github.com/ppetrou/vmware_pyvmomi_mock&quot; target=&quot;_blank&quot;&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it, I hope you find this useful and if you have a better way of doing it please leave a comment below.&lt;/p&gt;

&lt;p&gt;Thank you,&lt;/p&gt;

&lt;p&gt;Petros&lt;/p&gt;</content><author><name></name></author><category term="vmware" /><category term="mock," /><category term="unittest," /><category term="pyvmomi" /><summary type="html">I have recently been doing some vmware api development work using pyvmomi and one of the issues I had is how we can unit test without a vSphere Installation. The solution is to mock the pyvmomi api but it turned out that it was a much more complex task than I initially thought, so here are my findings.</summary></entry><entry><title type="html">Hello World!</title><link href="http://www.petrospetrou.co.uk/hello/2020/10/22/hello-world.html" rel="alternate" type="text/html" title="Hello World!" /><published>2020-10-22T17:16:34-05:00</published><updated>2020-10-22T17:16:34-05:00</updated><id>http://www.petrospetrou.co.uk/hello/2020/10/22/hello-world</id><content type="html" xml:base="http://www.petrospetrou.co.uk/hello/2020/10/22/hello-world.html">&lt;p&gt;Hi, my name is Petros Petrou and this is my first blog post. If you want to know more about me have a look in &lt;a href=&quot;/about/&quot;&gt;About&lt;/a&gt;.
I will try and keep this space active with stories and technical articles from my workplace and also my home lab.&lt;/p&gt;</content><author><name></name></author><category term="hello" /><category term="helloworld" /><summary type="html">Hi, my name is Petros Petrou and this is my first blog post. If you want to know more about me have a look in About. I will try and keep this space active with stories and technical articles from my workplace and also my home lab.</summary></entry></feed>