G’day All,

So Cameron Lackpour suckered engaged another extremely talented EPM specialist – Chris Rothermel – to write a guest post.

It walks through a simple yet elegant code set to perform Automated Daily Timestamped Backups on PBCS. Given the consolidation Oracle Cloud products this process could be easily extended to any Oracle Cloud application that utilises LCM.

Absolutely brilliant, worth the read. It might just be me, but reading any cleanly documented, clearly written, optimised code is always an soothing experience. Errr.

Reaching out

Anyways, because we are all tragic and in dire need of better hobbies technical enthusiasts – I got in touch with Chris to discuss it further.

Quickly to go through his process:

  1. Login to PBCS using EPMAutomate
  2. Download the latest Artifact Snapshot
  3. Rename the snapshot on the local machine with a datestamp
  4. Upload the renamed snapshot to PBCS

My only problem with the process is the literally the bandwidth cost. Even with a single environment and wanting to backup a Prod and Test environment you could be downloading and uploading gigabytes \ day. If I’m at my day job and want to extend this functionality to our large (and growing quickly!) PBCS client base, we could be looking at 50gb+ of movements a day – which is problematic.

What to do…

So the first and easiest option – instead of downloading the Artifact Snapshot to rename it, why don’t we just rename the snapshot on the PBCS server?

Well, unfortunately it’s not that simple.

EPMAutomate doesn’t have that feature.

Even looking through the REST API documentation it doesn’t seem possible :

Available options are limited to:
Possible values: self, import, export, upload, download, or delete depending on the operation permitted on an application snapshot

So what to do?

Okay, so we can’t rename an LCM Export. And downloading and uploading them costs too much time/bandwidth. But maybe we can trick it.

Let’s examine some of the other EPMAutomate functions – specifically exportsnapshot.

Repeats a previously performed export operation to create a snapshot of Migration content. You can download the exported snapshot from the default location.
Usage: epmautomate exportsnapshot SNAPSHOT_NAME where SNAPSHOT_NAME is the name of an existing snapshot in Migration. This snapshot is replaced by the new snapshot.
Example: epmautomate exportsnapshot October16FullApp

Maybe we could use this function to create a ‘new’ snapshot with our datestamp – all with have to do is convince PBCS that the snapshot has already occurred.

Easiest way to do that? Upload something that looks like an LCM export.

First crack 2 eggs…

Interestingly PBCS fundamentally uses the same filesystem and file structure as on-premises Hyperion. Specifically, this the PBCS ‘get everything’ export.xml format – I’ve highlighted the few fields that are specific to an application\environment.

This is available from the Artifact Snapshot in the top level of the zip file.

Having done a bit of work with LCM backups in the past, I figured it would be a similar process within PBCS. The Export.xml file defines the export process – so all we should need to do is zip up a default Export.xml, upload it to the server, and Robert is your mother’s brother.

Classic Remix

So, let’s look at some basic code:

for /f %%g in ('powershell get-date -format yyyymmdd') do set datestamp=%%g
Set Snapshotname=%datestamp%_Backup
7za.exe a %SnapshotName%.zip C:\Test\Backup\Export.xml 
Call %workingdir%\epmautomate login %user% %pass% %url% %domain% >> %Log%
Call %workingdir%\epmautomate uploadfile C:\Test\Backup\%SnapshotName%.zip >> %Log%
Call %workingdir%\epmautomate exportsnapshot %SnapshotName% >> %Log%
Call %workingdir%\epmautomate downloadfile %SnapshotName% >> %Log%
Call %workingdir%\epmautomate logout >> %Log% 

Breaking it Down

 for /f %%g in ('powershell get-date -format yyyymmdd') do set datestamp=%%g

Firstly, a quick way to build a fully formatted datestamp in dos batch\powershell that deals with international locales.

Set Snapshotname=%datestamp%_Backup
7za.exe a %SnapshotName%.zip C:\Test\Backup\Export.xml

Setting the snapshot name, and creating a zip file with just the export.xml in it. The eagle eyed amongst you will note that there is no username and password in the export.xml file.


Call %workingdir%\epmautomate login %user% %pass% %url% %domain% >> %Log%
Call %workingdir%\epmautomate uploadfile C:\Test\Backup\%SnapshotName%.zip >> %Log%

Login to EPMAutomate (the variables have been set earlier) and then upload the new zip file.

Call %workingdir%\epmautomate exportsnapshot %SnapshotName% >> %Log%

Trigger the LCM export of the uploaded snapshot.

And after a few minutes:


Call %workingdir%\epmautomate downloadfile %SnapshotName% >> %Log%

The last (and completely optional!) step of downloading the snapshot to the local machine.

Updated file size:

And the contents?

Wrapping Up

So, let’s talk about the new process

  1. Create a datestamp(ed? – sic) zip file containing only a generic Export.xml
  2. Login to PBCS using EPMAutomate
  3. Upload your empty Snapshot
  4. Trigger the uploaded artifact snapshot, adding to the empty snapshot file
  5. (Optional) Download the updated snapshot to the local machine

Key advantage? Because you’re only uploading a shell file, your bandwidth costs drop to 2kb per backup!

What’s next?

So the only item really left to cover off is how to remove the old files from the server. One of the key notes that Chris made in his post was that the EPMAutomate Listfiles does not show the LCM files.

In my trials and tribulations seamless process of writing this all out, I realised that the LCM files are accessible through the REST API – so it should be easy (cough) to write a process to parse and delete them.

And with that segue to a Part 2 – Peter tries to work out Groovy, Scripting and the REST APIs, I’ll leave it here.


Warning: Undefined array key "share_counts" in /var/www/wp-content/plugins/simple-social-buttons/simple-social-buttons.php on line 477

Fatal error: Uncaught TypeError: Cannot access offset of type string on string in /var/www/wp-content/plugins/simple-social-buttons/simple-social-buttons.php:477 Stack trace: #0 /var/www/wp-includes/class-wp-hook.php(324): SimpleSocialButtonsPR->ssb_footer_functions('') #1 /var/www/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #2 /var/www/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #3 /var/www/wp-includes/general-template.php(3066): do_action('wp_footer') #4 /var/www/wp-content/themes/wordstar/footer.php(59): wp_footer() #5 /var/www/wp-includes/template.php(810): require_once('/var/www/wp-con...') #6 /var/www/wp-includes/template.php(745): load_template('/var/www/wp-con...', true, Array) #7 /var/www/wp-includes/general-template.php(92): locate_template(Array, true, true, Array) #8 /var/www/wp-content/themes/wordstar/single.php(86): get_footer() #9 /var/www/wp-includes/template-loader.php(106): include('/var/www/wp-con...') #10 /var/www/wp-blog-header.php(19): require_once('/var/www/wp-inc...') #11 /var/www/index.php(17): require('/var/www/wp-blo...') #12 {main} thrown in /var/www/wp-content/plugins/simple-social-buttons/simple-social-buttons.php on line 477