Vagrant AWS Template

This took me a bit to gather all the details together so I wanted to document this and maybe provide some usefulness to others. There are a number of plugins, features, configurations tricks that I’ve found extremely useful over the last several years for working with Vagrant and Chef. Below is a sample Vagrantfile that can be used as a template and is hopefully commented enough to be self explanatory. You’ll need the following plugins installed:

vagrant plugin install vagrant-berskhelf
vagrant plugin install vagrant-omnibus
vagrant plugin install vagrant-cachier
vagrant plugin install vagrant-vbguest
vagrant plugin install vagrant-hostmanager

Vagrant File:

#-----------------------------------------------------#
#- Project: vagrant-based
#- Author.: john.lawson@scriobha.im
#- Date...: 2015-03-16
#- Notes..: Base template should be usable with a dual scenario
#-----------------------------------------------------#

#- Defaults
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |c|

    #- Caching section to speed local dev/usage don't remove! -#
    if Vagrant.has_plugin?("vagrant-cachier")
        #- Configure scope
        c.cache.scope = :box

        # Enable Apt cache
        c.cache.enable :apt

        # Disable this for actual development use as this will cause issues in file refresh
        #c.cache.enable_nfs = true
    end
    #- END Caching ------------------------------------------ -#

    #- Configure vagrant-hostmanager plugin ----------------- -#
    #- Use this for managing multiple instances, mimics
    #- AWS OpsWorks DNS by hostname functionality
    if Vagrant.has_plugin?("vagrant-hostmanager")
        c.hostmanager.enabled = true
        c.hostmanager.manage_host = true
        c.hostmanager.ignore_private_ip = false
        c.hostmanager.include_offline = true
    end

    #- Define our primary instance as app1
    c.vm.define "app1", primary: true do |app1|

        #- Instance Details
        app1.vm.box = "[name of instance here - this will be the name listed in Virtual Box GUI]"

        #- Pull down an Ubuntu 14.04 base box from Amazon
        app1.vm.box_url = "https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box"

        #- Set the hostname and alias (used in conjunction with the host manager plugin
        app1.vm.hostname = "dev-app1.local.vm"
        app1.hostmanager.aliases = %w(dev-app1.localdomain dev-app1)

        #- Network & Network Shares
        app1.vm.network(:forwarded_port, {:guest=>80, :host=>8001})
        app1.vm.network(:forwarded_port, {:guest=>443, :host=>8443})
        app1.vm.network(:private_network, {:ip=>"199.10.0.2"})
        app1.vm.synced_folder ".", "/vagrant", disabled: true

        #- Setup a mount point for Apache docroot (not in /var/www/) and we'll mount it later with Chef recipe
        app1.vm.synced_folder "~/vm-mounts/project-folder", "/mnt/app-www/", create: true, :nfs=> { :mount_options=> ['rw', 'vers=3', 'tcp', 'fsc'] }

        #- Instance Customizations
        app1.vm.provider :virtualbox do |p|
            p.name = app1.vm.box
            p.customize ["modifyvm", :id, "--memory", "1024"]
            p.customize ["modifyvm", :id, "--cpus", "1"]
        end

        #- Chef Solo Configurations & Details
        app1.berkshelf.enabled = true
        app1.omnibus.chef_version = '11.14.2'
        
        app1.vm.provision :chef_solo do |chef|
            chef.cookbooks_path = ['.']
            chef.add_recipe 'recipe[opsworks::_local_init]'
            chef.add_recipe 'recipe[opsworks::apache2]'
            chef.json = {
                #- used locally to mimic auto DNS resolution by hostname done by AWS OpsWorks
                opsworks: {
                    local_dev: true
                },
                # Mimic Hash provided by OpsWorks
                deploy: {
                    webapp: {
                        environment: {
                            #- 10.0.2.2 is most likely your host (this allows you to keep a central DB)
                            main_dbhost: "10.0.2.2",
                            main_dbname: "dbname",
                            totara_dbuser: "dbuser",
                            totara_dbpwd: "dbpwd"
                        }
                    }
                }
            }
        end
    end

    #- Define a secondary instance, could be used as NFS server, jobs server, other? Will not start unless you specifically call it
    c.vm.define "file1", autostart: false do |file1|
        #- Instance Details
        file1.vm.box = "[name of instance here - this will be the name listed in Virtual Box GUI]"

        #- Pull down an Ubuntu 14.04 base box from Amazon
        file1.vm.box_url = "https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box"

        #- Set the hostname and alias (used in conjunction with the host manager plugin
        file1.vm.hostname = "dev-file1.local.vm"

        #- Network & Network Shares
        file1.vm.network(:private_network, {:ip=>"199.10.0.4"})
        file1.vm.synced_folder ".", "/vagrant", disabled: true

        #- Instance Customizations
        file1.vm.provider :virtualbox do |p|
            p.customize ["modifyvm", :id, "--memory", "512"]
            p.customize ["modifyvm", :id, "--cpus", "1"]
        end
        file1.vm.provision :chef_solo do |chef|
            chef.cookbooks_path = ['.']
            chef.add_recipe 'recipe[opsworks::_local_init]'
            chef.add_recipe 'recipe[opsworks::nfs-config]'
            chef.json = {
                #- used locally to mimic auto DNS resolution by hostname done by AWS OpsWorks
                opsworks: {
                    local_dev: true
                }
            }
        end
    end
end

CI/Build/Deploy

A friend of mine recently asked a very general question of what tools, tips, process, other had I used at a former employer for our Continuous Integration, Build, Deploy process. After digging through my memory for some of the names of products and then dusting off the processes that we developed I realized that the entire process was a lot of fun. I’m very interested to see how much further the concept becomes a standard practice among development teams and companies in general.

Google Drive Synced for Ubuntu

OK, so I’ve been finding myself using GDrive more and more but missing the sync capabilities as with DropBox and of course there is no Linux client/integration because why would anyone want to do that. Don’t you know Linux is used to bypass DRM and hack people and stuff!? OMG! I mean really the next thing will be cats and dogs living together, mass hysteria!

So, after poking around grive seemed to be the most flexible, allow for actual sync and not be tied to a beta (see InSync beta program) and only free for that beta. That’s not really free in my mind and yes I’m arguing semantics; it’s my site, I can do that.

Steps:

  1. $ sudo add-apt-repository ppa:nilarimogard/webupd8
  2. $ sudo apt-get update
  3. $ sudo apt-get install grive
  4. $ mkdir /home/[your home directory here]/gDrive
  5. $ cd $home/gDrive
  6. $ grive -a
  7. follow the prompt from Google to allow Grive to access and then copy the key and paste it as instructed

I personally don’t like having to execute manual things so I also added a Cron entry to sync every 15 minutes

  1. $ crontab -e
  2. */15 * * * * cd /home/[your home directory here]/gDrive && grive
  3. save/exit
  4. Done!

Interesting article on Liferay and Alfresco integration

Liferay and Alfresco integration with JSR-168 and JSR-286.

I’ve been tracking the efforts of Liferay and working with Alfresco for a couple of years now and this article at Rivet Logic Blogs by Alaaeldin El-Nattar caught my eye. Discussed are the integration capabilities of the two products and the JSR-168/286 specification. Check it out!

Froyo 2.2 for Motorola Droid Update.

Update for MotoDroid phone to Froyo 2.2 works

I’ve been watching all the hype about Verizon updating it’s line of MotoDroid phones and getting annoyed about having to wait. Officially now, it’s been rolling out but they are projecting Aug. 18th for completing the roll-out. It’s an open phone, why can’t I update it myself? Well, I didn’t like the prospect of “bricking” it and having to shell out money for a new one. That said, I stumbled on this post from Phandroid and couldn’t help myself. I am now a Froyo user in just over 10 minutes. Easy, easy, easy!

Oracle Portal JSP based pages

Re-posted from my old site. This may be slightly outdated but of use to someone….

NOTE: I am working with the Portal 10g product version 10.1.2.* and it’s various componenets. In my recent trolling through Google search results I found the following information on Mark Rittman’s blog. The below is a direct copy from his blog and all credit should be hereby granted to him for the following content. This “re-post” is simply for the purpose of further distributing this info and also creating a version for myself in the unwelcome event that Mark’s site goes defunct or is unavailable.

The following example uses Application Server 10g to integrate Portal portlets into a JSP page, and delivers it through the AS10g mid-tier webserver [Thanks to Gareth for putting together the examples]

1.    First, rename your existing HTML files to use the extension .jsp instead of .htm or .html
2.    Create a new blank file at $ORACLE_HOME\j2ee\OC4J_Portal\applications\portal\portal\WEB-INF\wwjps.xml where $ORACLE_HOME is your Portal mid-tier instance

Within the file, create this XML

<jps version="1.0">
<portal name="mtier" default="true">
<database data-source="jdbc/MyPortal"/>
<url host="site.name.com" port="1111" path="/pls/portal"/>
<cookie name="portal" maxAge="-1" path="/" />
<pagegroups>
<pagegroup name="DWHome" key="welcome1" default="false"/>
<pagegroup name="TOPLEVELSITE" key="welcome1" default="true"/>
<pagegroup name="GH_DEV" key="welcome1" default="false"/>
<pagegroup name="PG_PAYMON" key="welcome1" default="false"/>
</pagegroups>
</portal>
</jps>

Note: The <portal name="mtier" default="true"> is the name of the mid-tier instance that contains the Portal application we wish to use portlets from. The <pagegroup name="DWHome" key="welcome1" default="false"/> entries define which pagegroups will contain the portlets we wish to use. The MyPortal reference I’ll explain in a second.

3.    Locate the file $ORACLE_HOME\j2ee\OC4J_Portal\applications\portal\portal\WEB-INF\web.xml where $ORACLE_HOME is your Portal mid-tier instance

This file should contain the following code within the <web-app> tag.

<context -param>
<param -name>oracle.webdb.service.ConfigLoader</param>
<param -value>/WEB-INF/wwjps.xml</param>
<description>This parameter specifies the location of the JPS configuration file</description>
</context>

Note: In the OC4J_Portal application this code is already present in the web.xml file

4.    In the wwjps.xml file (mentioned in step 1) there is a tag to provide database connection information about a given portal instance.
<database data-source="jdbc/MyPortal"/>
Data-source attribute value is the name of the datasource, which must be specified in the data-sources.xml file located in the $J2EE_HOME/config directory. This file is located in the $ORACLE_HOME\j2ee\OC4J_Portal\config\data-sources.xml

The following code was inserted into this file for a connection to the Infrastructure database:


<data -source
class="com.evermind.sql.DriverManagerDataSource"
name="MyPortal"
location="jdbc/MyPortal"
xa-location="jdbc/xa/MyPortal"
ejb-location="jdbc/MyPortal"
connection-driver="oracle.jdbc.driver.OracleDriver"
username="portal"
password="passwd-here"
url="jdbc:oracle:thin:@site.name.com:port-#:SID"
inactivity-timeout="30"
/>

The text in bold must be the same as the text in bold in the wwjps.xml file.

5.    If you want a Portal page group to be accessible externally then you need to allow external access.  To do so go the the Page Group Properties   Configure   JSP Access.  Check the “Allow External Access” tickbox and enter the access key.   The access key should be the key=”welcome1″ value you used when creating the wwjps.xml file in step 1.

6.    To add a portlet that can be accessed from our JSP page, use Navigator to select the page group you wish to work with, click on the ‘Externally Published Portlets’ entry at the bottom of the navigator page, then click on the ‘Create Externally Published Portlet’ link. Select a portlet you wish to publish and give it a name.

Externally Published Portlets

1.    To include a reference to this portlet in your .jsp page, open up the page in your HTML editor and add the following JSP tag codes.


< %@ taglib prefix="portal" uri="/WEB-INF/lib/wwjpstag.jar" %>
<portal :usePortal id="mtier" pagegroup="PG_PAYMON" login="false"/>
<portal :showPortlet name="test_paymon" portal="mtier" header="True"/>

2.    Lastly, copy your .JSP pages into the $ORACLE_HOME\j2ee\OC4J_Portal\applications\portal\portal\ directory, which the ‘htdocs’ equivalent for your now 9ias-delivered website.
3.    Assuming your converted HTML page is now called index.jsp, you can now access your page using the URL http://<host .domain:port/portal/index.jsp

Portlets on JSP Page

What we’ve done here is convert our HTML pages to JSP pages, include references to Portal portlets, and delivered the page through Application Server 10g. Oracle refer to these as ‘external JSPs’, and because the pages aren’t hosted in Portal you’ll have to maintain them outside of Portal. However, you can also choose to take your JSP page and import it into Portal, making it what Oracle terms an Internal JSP. To do this:

1.    Create your Portal page group as normal, but when you go to create a new page, select ‘JSP’ as your page type.

Create JSP Page

2.    Then, after naming the page, select the jsp page (from your filesystem, not from a URL) to import, and it’ll then be brought in as an internal JSP.

Like external JSPs, internal JSPs can reference Portal content as well as regular HTML and JSP tags. So what are the differences between external and internal JSPs?

  • Both internal and external JSPs are created outside of Portal using a text editor or HTML editor like Dreamweaver or Frontpage
  • Internal JSPs are automatically stored in the Portal database, and are managed and secured by Portal
  • External JSPs are stored outside of Portal (usually in the 9iAS mid-tier file system, under the OC4J_PORTAL directory home) and Portal does not provide any file management or file security
  • Both internal external JSPs can make use of SSO, internal JSPs automatically and external JSPs by using login=”true” in the Portal JSP tags.
  • Generally, Internal JSPs are easier to manage and store, whilst external JSPs are more flexible and run faster (as they’re not being delivered through Portal).

For more details on delivering Oracle Portal content through your JSP pages, check out the Oracle document “Oracle HTTP Server : Integrating Java Server Pages With Oracle 9iAS Portal” available on OTN.

Create a perfect ISO

Creating an ISO with long file names and odd folder structures

There are a million posts out there that cover how to make an ISO image of a CD/DVD. For some reason I was having a particularly hard time with a specific disk. It had long file names, funny folder structures and I kept getting all uppercase file names. I tried the stock dd if=/dev/cdrom of=~/[file-name].iso first and found that it was just not cutting it. The below seemed to work the best on multiple CDs and formats.

mkisofs -r -J -l -d -allow-multidot -allow-leading-dots -joliet-long -no-bak -o ~/[name-of-file-or-disk].iso /media/[source-folder]