{"id":989,"date":"2025-11-09T14:12:42","date_gmt":"2025-11-09T14:12:42","guid":{"rendered":"https:\/\/blog.bar-solutions.com\/?p=989"},"modified":"2025-11-09T14:12:43","modified_gmt":"2025-11-09T14:12:43","slug":"keeping-the-cloud-alive-multiple-clouds","status":"publish","type":"post","link":"https:\/\/blog.bar-solutions.com\/?p=989","title":{"rendered":"Keeping the cloud alive &#8211; multiple clouds"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>I explained how I configured the Raspberry Pi and created a Python script to connect to the cloud. Now, I want to be able to keep multiple cloud databases alive using a single Raspberry Pi. In this blog, I will show you how I handled this problem.<\/strong><strong><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Connecting more than one cloud environment sounds impossible. After all, a new Wallet overwrites the existing one. So how can you work around this? Luckily, I already solved this issue on my laptop, using a solution that I found in&nbsp;<a href=\"https:\/\/smart4solutions.nl\/blog\/oci-connections-to-multiple-autonomous-transaction-databases-in-the-oracle-always-free-cloud\/\">this blogpost<\/a>. This is also what I did on the Raspberry Pi.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, I created a separate Wallet folder and moved all the files here:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[root@rpi ~]#&nbsp;&nbsp;cd \/usr\/lib\/oracle\/19.10\/client64\/lib\/network\/admin\/<br>[root@rpi admin]# mkdir Wallet_Sandbox<br>[root@rpi admin]# mv *.* Wallet_Sandbox\/<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then I created another folder that consists of different Wallet files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[root@rpi admin]# mkdir Wallet_orcldev<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using my FTP tool, I uploaded the files from the unzipped Wallet to this folder. To make sure that the Oracle Client can find the correct Wallet folder for the different connection strings (tnsnames entries), I created a new&nbsp;<em>tnsnames.ora<\/em>&nbsp;file in the admin folder.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I used&nbsp;<em>tnsnames.ora<\/em>&nbsp;files from the Wallets and combined them into one big file. However, for this to work, I had to add a minor change to each entry.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">sandbox_low =<br>&nbsp;&nbsp;(description =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(retry_count = 20)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(retry_delay = 3)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(address&nbsp;&nbsp;&nbsp;=<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(protocol = tcps)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(port&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 1522)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(host&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= adb.eu-amsterdam-1.oraclecloud.com)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(connect_data = (service_name = **********_sandbox_low.adb.oraclecloud.com))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(security =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(MY_WALLET_DIRECTORY =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;\/usr\/lib\/oracle\/19.10\/client64\/lib\/network\/admin\/Wallet_Sandbox&#8221;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ssl_server_cert_dn=&#8221;CN=adb.eu-amsterdam-1.oraclecloud.com<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,OU=Oracle ADB AMSTERDAM,O=Oracle Corporation<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,L=Redwood City,ST=California,C=US&#8221;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br>&nbsp;&nbsp;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the security section of the entry, I told the client where to find the Wallet files. I had to do this for every entry in the tnsnames.ora file, making sure I pointed to the correct folder for the correct entry.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now that this part of the administration was in place, I could copy the directory with the python files. In the new directory, all I had to do was update the config.py file. Since I am using scripts to create the user, table and trigger, the password was the same. So, it was a matter of simply changing the DSN entry.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[oracle@rpi ~]$ mkdir oradev<br>[oracle@rpi ~]$ cp patch72\/*.* oradev\/<br>[oracle@rpi ~]$ cd oradev\/<br>[oracle@rpi oradev]$ vi config.py<br>dsn = &#8216;orcldev_low&#8217;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, I copied the shell script and altered this to call the Python script from the new folder:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[oracle@rpi ~]$ cp keeppatchalive keeporadevalive<br>[oracle@rpi ~]$ vi keeporadevalive<br>python3 oradev\/keepalive.py<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Checked if it worked by calling the shell script:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[oracle@rpi ~]$ .\/keeporadevalive<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To make sure this script gets called by the cron scheduler, I needed to update the crontab (while I was at it, I changed the schedule from every 5 minutes to every hour, because we know it works now):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[oracle@rpi ~]$ crontab -e<br># This command keeps the connection to patch72 alive<br>0 * * * * \/home\/oracle\/keeppatchalive<br># This command keeps the connection to oradev alive<br>0 * * * * \/home\/oracle\/keeporadevalive<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a><\/a><strong>Minimizing the work<\/strong><strong><\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This was all pretty easy, but adding another database to the set was still a lot of work. More work than I would like to do. What if I just have to set up a user in the database that I want to keep alive, then add a couple of lines to a configuration file to point to this database? That would be a lot easier. So, with the internet as my helper, I came up with the following Python script. I decided to put procedure\/function in the same file, since I thought it was a bit of an overkill to put a single program into a single file. Maybe I am wrong. If so, please let me know in the comments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[KeepMeAlive.py]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">#!\/usr\/bin\/env python<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">#######################################################################<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Author : Patrick Barel &#8211;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Version : 0.1<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Date : 2021-09-14<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Filename : KeepMeAlive.py<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Description : A python script that connects to multiple oracle<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># always free tier to keep them alive\/awake<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Dependencies :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">#######################################################################<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import cx_Oracle<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import logging<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">import json<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">def connect(connection_in):<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">try:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">logging.info(&#8220;Connect to %s@%s&#8221;, connection_in[&#8220;username&#8221;], connection_in[&#8220;dsn&#8221;])<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">connection = cx_Oracle.connect(<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">connection_in[&#8216;username&#8217;],<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">connection_in[&#8216;password&#8217;],<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">connection_in[&#8216;dsn&#8217;],<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">encoding=connection_in[&#8216;encoding&#8217;])<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">except cx_Oracle.Error as error:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">logging.error(error)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">print(error)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">finally:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># return the connection<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">if connection:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">return connection<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">if __name__ == &#8216;__main__&#8217;:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">#######################################################################<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># start &#8211; setup logging #<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">#######################################################################<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">logging.basicConfig( filename=&#8217;KeepMeAlive.log&#8217;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, level=logging.DEBUG<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, format=&#8217;%(asctime)s %(message)s&#8217;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">logging.info(&#8220;Read the JSON file with the defined connections&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Opening JSON file<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">file = open(&#8216;\/home\/oracle\/KeepMeAlive\/connections.json&#8217;,)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># returns JSON object as<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># a dictionary<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">connections = json.load(file)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Iterating through the json list<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">logging.info(&#8220;Loop through all the defined connections&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">for conndata in connections[&#8216;connections&#8217;]:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">connection = connect(conndata)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">logging.info(&#8220;Close the connection (Just connecting should be enough)&#8221;)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">connection.close()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"># Closing file<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">file.close()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This program reads the connection information from a JSON file, then simply connects and disconnects to the database. However, I think just connecting should be enough to keep the databases up and running.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The JSON file looks like this:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[connections.json]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">{<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;connections&#8221;: [<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">{ &#8220;username&#8221; : &#8220;keepalive&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, &#8220;password&#8221; : &#8220;&lt;aVeRySeCReTPa$$W0RD&gt;&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, &#8220;dsn&#8221; : &#8220;orcldev_low&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, &#8220;port&#8221; : 1512<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, &#8220;encoding&#8221; : &#8220;UTF-8&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">{ &#8220;username&#8221; : &#8220;keepalive&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, &#8220;password&#8221; : &#8220;&lt;aVeRySeCReTPa$$W0RD&gt;&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, &#8220;dsn&#8221; : &#8220;sandbox_low&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, &#8220;port&#8221; : 1512<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">, \u201cencoding\u201d : \u201cUTF-8\u201d<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I created a shell script to call this Python program:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[oracle@rpi ~]$ cp keeporadevalive KeepDBAlive<br>[oracle@rpi ~]$ vi KeepDBAlive<br>#!\/bin\/sh<br>&nbsp;<br>python3 KeepMeAlive\/KeepMeAlive.py<br>exit 0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And added the following line to the crontab to add it to the cron schedule:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[oracle@rpi ~]$ crontab -e<br># This command keeps the cloud databases alive<br>0 * * * * \/home\/oracle\/KeepDBAlive<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If I provision a new database in the cloud, all I have to do now is create a user that can connect and adjust the&nbsp;<em>connections.json<\/em>&nbsp;file to add the new credentials. And this program will automagically keep the new database alive. I know this code needs more error handling and better logging, but for now it works. As far as I can tell, it gets the job done and saves me (and hopefully you) time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a><\/a><strong>More information?<\/strong><strong><\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Qualogy has a lot of expertise and experience with Oracle, cloud environments and cloud databases. We are happy to share this knowledge. For more information, please contact&nbsp;info@qualogy.com&nbsp;or&nbsp;+31 70 319 5000.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These articles were previously published on the <a href=\"https:\/\/www.qualogy.com\">Qualogy<\/a> website.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I explained how I configured the Raspberry Pi and created a Python script to connect to the cloud. Now, I want to be able to keep multiple cloud databases alive using a single Raspberry Pi. In this blog, I will show you how I handled this problem. Connecting more than one cloud environment sounds impossible. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28],"tags":[],"class_list":["post-989","post","type-post","status-publish","format-standard","hentry","category-keeping-the-cloud-alive"],"_links":{"self":[{"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=\/wp\/v2\/posts\/989","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=989"}],"version-history":[{"count":2,"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=\/wp\/v2\/posts\/989\/revisions"}],"predecessor-version":[{"id":993,"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=\/wp\/v2\/posts\/989\/revisions\/993"}],"wp:attachment":[{"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=989"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=989"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.bar-solutions.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=989"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}