Zero Downtime Live Migration Kernel Zones Openstack PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 67

HOL6739: Zero Downtime with

OpenStack Live Migration for Oracle


Solaris Kernel Zones

Yan Zhang
Software Engineer, Oracle

Xiao-song Zhu
Principal Software Engineer, Oracle

Yu Wang
Principal Software Engineer, Oracle
Table of Contents
Introduction ....................................................................................................................................................................................................... 2
Prerequisites....................................................................................................................................................................................................... 2
Hardware/Software Requirements ..................................................................................................................................................................... 2
Environment Configuration ............................................................................................................................................................................... 3
Notes for Users .................................................................................................................................................................................................. 3
Exercise 1: Playing with Oracle Solaris 11.3’s OpenStack Kilo (15 Minutes) .................................................................................................. 7
Exercise 2: Launching a VM Instance (20 Minutes) ....................................................................................................................................... 15
Exercise 3: Performing Live Migration with No Memory Data Loss (10 Minutes) ........................................................................................ 29
Exercise 4: Live Migration with Almost Zero Downtime (15 Minutes) .......................................................................................................... 36
Appendix A: Creating the Java Code for Exercise 3 ....................................................................................................................................... 43
Appendix B: Creating the Java Code for Exercise 4 ....................................................................................................................................... 59
Summary.......................................................................................................................................................................................................... 67
See Also ........................................................................................................................................................................................................... 67
About the Authors............................................................................................................................................................................................ 67

Introduction
OpenStack, the popular open source cloud computing platform, provides comprehensive self-service environments
for sharing and managing compute, network, and storage resources through a centralized web-based portal.
OpenStack has been integrated into all the core technology foundations of Oracle Solaris, allowing you to set up an
enterprise private cloud infrastructure in minutes. Oracle Solaris 11 includes the OpenStack Kilo release (Oracle
Solaris 11.3 SRU 9 and later versions).

Live migration refers to the process of moving a running virtual machine (VM) or application between different
physical machines without disconnecting the client or application. It can improve the cloud environment's
manageability and fault tolerance, as well as shorten the application downtime. In OpenStack Kilo, the Nova service
supports kernel zone live migration. In this hands-on lab (HOL) you will learn how to use the Nova service to
deploy a VM instance with a Java EE application. Oracle OpenStack live migration is used to migrate the VM
instance with minimum downtime, and you will observe the high availability of this application during the
migration.

Prerequisites
This HOL assumes you have some basic knowledge about the following technologies.

• Administration of Oracle Solaris or a similar UNIX or Linux OS


• Oracle WebLogic Server administration

Hardware/Software Requirements
• Client side:
o Memory requirement: 8 GB
o Disk space requirement: 20 GB
o Oracle VM VirtualBox 5.0.4 (host OS: Windows 7/8 or Oracle Linux)
o Operating System: Oracle Solaris 11.3

2
• Server side:
o Oracle’s SPARC T7-1 server
o Three logical domains (LDoms) on the server: hol6739-01, hol6739-02, and hol6739-03
 hol6739-01: 32 vCPU, 32 GB of memory, 50 GB of disk space
 hol6739-02 and hol6739-03: 64 VCP, 64 GB of memory, 100 GB disk space
o Operating system: Oracle Solaris 11.3 SRU 9
o Oracle WebLogic Server 12.2.1.1

Environment Configuration
• HOL6739 client:
o Oracle Solaris 11.3 for x86 installed in Oracle VM VirtualBox 5.0.4
o Host name: hol6739
o OS username/password:
 solaris/oow2016
 root/oow2016
• HOL6739 server:
o Oracle Solaris 11.3 for SPARC installed on a SPARC T7-1 server
o LDoms’ username/password:
 solaris/oow2016
 root/oow2016

Notes for Users


• Text highlighted in blue like the following indicates text you should enter in a terminal window:
#ls -l libdax*
• Text highlighted in yellow like the following indicates placeholder text you should replace with text that is
appropriate for your environment:
root@hol6739:~# dladm create-vnic -l vxlan20** vnic1

• Text highlighted in green like the following indicated text of importance:


root@hol6739-01:~# evsadm show-controlprop -o all
PROPERTY PERM VALUE DEFAULT FLAT VLAN_RANGE VXLAN_RANGE HOST
l2-type rw vxlan vlan -- -- -- --

• To log in to Oracle Solaris 11 running on Oracle VM VirtualBox, use the username/password


solaris/oow2016.
• GNOME on Oracle Solaris 11.3 (with desktop packages installed) is the preferred desktop environment.
• In order to open a terminal window in GNOME, right-click any point on the background of the desktop, and
select Open Terminal in the pop-up menu (as shown in Figure 0-1).

3
Figure 0-1. Opening a terminal window

Preparing the Environment


Client Side

1. Download and install Oracle Solaris 11.3 in Oracle VM VirtualBox.

• You can download an Oracle Solaris 11.3 template for Oracle VM VirtualBox at
oracle.com/technetwork/server-storage/solaris11/downloads/vm-templates-2245495.html.

• Import the Oracle VM VirtualBox client-side image and name it hol6739:

Name hol6739
CPUs 2
Memory 4
Network bridge
General->advanced>shared clipboard bidirectional

• Please initialize the OS and configure the environment as follows:

Host name hol6739


Memory 8 GB
IP address 192.168.99.3/24
Username/password solaris/oow2016
/etc/hosts Add hol6739-01, hol6739-02, and hol6739-03 to the /etc/hosts file as
follows:
192.168.99.101 hol6663-01
192.168.99.102 hol6739-02
192.168.99.103 hol6739-03
/export/home/solaris/.profile Add the following lines to the /export/home/solaris/.profile file:
export
JAVA_HOME=/export/home/solaris/application_sourcecode/jdk-
8u111
export PATH=$JAVA_HOME/bin:$PATH
export
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export
ANT_HOME=/export/home/solaris/application_sourcecode/apache-
ant-1.9.6
export PATH=${PATH}:${ANT_HOME}/bin

4
2. Compile the source code and export WAR files.

All the source code is listed in “Appendix A: Creating the Java Code for Exercise 3” and “Appendix B: Creating the
Java Code for Exercise 4.” Follow the instructions in these appendices to add the source code for this HOL.

Server Side

1. Configure the LDoms:

• Install LDoms hol6739-01, hol6739-02, and hol6739-03, and install Oracle Solaris following the guide “Oracle
VM Server for SPARC 2.2 Administration.”

• Please initialize the OS and configure the environment as follows:

Host name hol6739-01 hol6739-02 hol6739-03


VCPUs 32 64 64
Memory 32 GB 64 GB 64 GB
Disk space 50 GB 100 GB 100 GB
IP address 192.168.99.101/24 192.168.99.102/24 192.168.99.103/24
Username/password solaris/oow2016 solaris/oow2016 solaris/oow2016
/etc/hosts Add hol6739-01, hol6739- Modify the /etc/hosts file Modify the /etc/hosts
02, and hol6739-03 to the the same as you did for file the same as you did for
/etc/hosts file as follows: host hol6739-01 host hol6739-01
192.168.99.101 hol6663-01
192.168.99.102 hol6739-02
192.168.99.103 hol6739-03
Note: This is the controller node This is a compute node and This is a compute node and
a Cinder node a Cinder node

• Install and configure OpenStack (Kilo) following the guide “Installing and Configuring OpenStack(Kilo) in
Oracle Solaris.”

Note: Please configure the OpenStack network following this blog. A VLAN is not recommended when
configuring multinode OpenStack in LDoms; you must use a VXLAN in this HOL.

2. Create an image and upload the image to OpenStack Glance.

• Create Oracle Solaris Kernel Zones in hol6739-01 following the guide “How to Get Started Creating Oracle
Solaris Kernel Zones in Oracle Solaris 11.”

• Install JDK and Oracle WebLogic in the kernel zone.

You can download JDK 8 from the Java SE Development Kit 8 Downloads page. Configure the environment
parameters as follows:

JAVA_HOME /export/home/wls/jdk1.8.0.101
PATH $JAVA_HOME/bin:$PATH
CLASSPATH .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

5
You can install Oracle WebLogic in the kernel zone by following the guide “Oracle WebLogic Server 12c
(12.2.1): Installing WebLogic Server Using the Generic Installer,” and set the Oracle WebLogic
administrator username/password to weblogic/welcome1.

• Create an Oracle Solaris Unified Archive clone archive for the kernel zone following the guide “How to Create
a Clone Archive.”

• Upload the archive to OpenStack Glance.

The following commands will set global shell variables for Glance and upload the Oracle Solaris Unified
Archive you created to the Glance repository. Use raw as the format type. Be sure to specify
the architecture property. Change myfirstkz.uar to your archive name.

root@hol6739-01: export OS_AUTH_URL=http://hol6739-01:5000/v2.0/


root@hol6739-01: export OS_PASSWORD=glance
root@hol6739-01: export OS_USERNAME=glance
root@hol6739-01: export OS_TENANT_NAME=service
root@hol6739-01: glance image-create --container-format bare --disk-format raw --is-public true -
-name "Kernel Zone" --property architecture=sparc64 --property hypervisor_type=solariszones --
property vm_mode=solariszones < myfirstkz.uar

3. Create user user01 for this HOL for using OpenStack Horizon.

Please add user01 with the following properties by following the procedure in “How to Create a Project and
Assign Users”:

Username user01
Password user01
Project project01
Privilege Admin + member

6
Exercise 1: Playing with Oracle Solaris 11.3’s
OpenStack Kilo (15 Minutes)
In this exercise, a SPARC T7 server from Oracle is separated into five logical domains by Oracle VM Server for
SPARC. An OpenStack framework is deployed among these domains. One domain works as a controller node,
while the others work as compute nodes and Cinder nodes. In this exercise, we are going to learn the basic concepts
about OpenStack, and check how the OpenStack services are setup in the domains.

Background Information

Oracle VM Server for SPARC


Oracle VM Server for SPARC provides highly efficient, enterprise-class virtualization capabilities for Oracle’s
SPARC T-Series servers, SPARC M-Series servers, and so on. Using the Oracle VM Server for SPARC software,
you can create up to 128 virtual servers, called logical domains or LDoms, on a single system. This kind of
configuration enables you to take advantage of the massive thread scale offered by SPARC servers and Oracle
Solaris.

Oracle Solaris Zones and Oracle Solaris Kernel Zones


The Oracle Solaris Zones virtualization technology has been an integrated part of Oracle Solaris since Oracle
Solaris 10. Oracle Solaris Zones let you isolate one application from others on the same operating system (OS),
allowing you to create an isolated environment in which users can log in and do what they want from inside an
Oracle Solaris Zone without affecting anything outside that zone. Each Oracle Solaris Zone contains a complete
resource-controlled environment that allows you to allocate resources such as CPU, memory, networking, and
storage.

An Oracle Solaris Kernel Zone, also called a solaris-kz branded zone, uses the branded zones framework to run a
zone with a separate kernel and OS installation from the global zone. The separate kernel and OS installation
provide for greater independence and enhanced security of operating system instances and applications.

Oracle Solaris ZFS


ZFS is a combined 128-bit file system and logical volume manager in Oracle Solaris. The features of ZFS include
protection against data corruption, support for high storage capacities, efficient data compression, integration of the
concepts of file system and volume management, snapshots and copy-on-write clones, continuous integrity
checking and automatic repair, RAID-Z, and native NFSv4 access control lists (ACLs).

COMSTAR
Oracle Solaris 11 introduced a framework named Common Multiprotocol SCSI TARget (COMSTAR) that supports
the iSCSI protocol, making it possible to turn any Oracle Solaris 11 host into an iSCSI target, which offers storage
to other machines, or an iSCSI initiator, which uses software that functions like a host bus adapter (HBA) to access
the storage offered by an iSCSI target.

Oracle OpenStack
OpenStack is a cloud operating system that controls large pools of compute, storage, and networking resources
throughout a data center, all managed through a dashboard that gives administrators control while empowering their
users to provision resources through a web interface. Now OpenStack is completely integrated with the core
technologies of Oracle Solaris. The following figure shows Oracle Solaris features that are used to implement
OpenStack services.
7
Figure 1-1. Oracle Solaris and OpenStack integration

HOL Environment

In this HOL, we have set up a multi-node OpenStack framework across three logical domains on a SPARC T7-1
server. See detailed information shown in Figure 1-2 and Table 1-1.

Figure 1-2. OpenStack HOL environment architecture

8
Supplies API, scheduling, and most of the shared services, such as dashboard,
Controller node hol6739-01 image store, and identity service. Additionally, the Nova compute management
service and the Neutron server are also configured in this node.

hol6739-02 Nodes where VM instances, also known as Nova compute instances, are installed.
Compute node
hol6739-03 These nodes run the compute daemon that manages these VM instances.

hol6739-02 These hosts merely provide the LUN disks to the initiator host based on
Storage node
hol6739-03 COMSTAR.
Table 1-1. HOL configuration

In Oracle Solaris, the elastic virtual switch (EVS) forms the back end for OpenStack networking. The EVS
facilitates communication between VM instances that are either on VLANs or VXLANs. The VM instances can be
on the same compute node or across multiple compute nodes. In this lab, we use VXLAN to communicate between
instances. Please see the detailed network environment shown in Figure 1-3.

Figure 1-3. Network architecture

The Horizon dashboard and command line are the two most common methods for users to access OpenStack:
• Horizon serves as the web portal for OpenStack. It provides a web-based user interface to manage Nova,
Swift, Keystone, and so on.
• Each core OpenStack project has a command-line client that you can use to run simple commands to view,
create, and manage resources in a cloud and automate tasks by using scripts.

In addition to these ways of interacting with a cloud, you can access the OpenStack APIs directly or indirectly
through URL commands or open SDKs. In this exercise, we will use both the Horizon dashboard and the command
line to access the cloud.

9
Step 1: Access the Cloud Using the Horizon Dashboard

1. Click the Firefox button at the top of the desktop to bring up a Firefox web browser (as shown in Figure 1-4).

Figure 1-4. Firefox browser open in Oracle VM VirtualBox

2. Horizon was installed and configured on the server hol6739-01. Please explore the Horizon dashboard by
inputting following URL: http://hol6739-01/horizon. You will get a Log In dialog box.

Figure 1-5. Horizon log in dialog box

Provide the following information on the log in screen:


• User Name: userXX
• Password: userXX

Note: Each user has a dedicated username and password for OpenStack in this lab. The username is formatted as
userXX, where XX stands for a number. The password is same as the username. In this lab, we use user01 as an
example.

3. Click Project > Compute > Overview to get an overview of your project.

Each user belongs to a project that is also known as tenant. Projects provide a mechanism to group and isolate
ownership of virtual computing resources and users. As shown in Figure 1-6, user01 belongs to project01; the
project limitation and usage are shown in the right view. And you can find the instances installed in the project.

10
Figure 1-6. Project overview

4. Check the Nova compute node.

Click Admin > System > Hypervisors to get an overview of the Nova computers in the cloud.

Figure 1-7. Nova computer hosts

All the Nova compute nodes are listed here with the available resources.
OpenStack has two management roles by default, member and admin. Because admin privilege is necessary for live
migration, we gave admin privilege to user01 when we created that user in the section ”Preparing the Environment.”

5. Check the Cinder storage node.

11
Click “Admin > System > System information, and choose Block Storage Services to check the Cinder services
in the cloud.

Figure 1-8. Cinder services

hol6739-02 and hol6739-03 provide the LUN disks to the initiator host based on COMSTAR. After you launch an
instance, Cinder allocates a ZFS volume to contain the instance's image as the guest's root device.

6. Check the Glance image.

Click Admin > System > Images to see all the images in the cloud, as shown in Figure 1-9. Then you can click the
image name to get detailed information about the image, as shown in Figure 1-10.

12
Figure 1-9. Glance images Figure 1-10. Image detail

In Oracle Solaris, OpenStack images are Oracle Solaris Unified Archives. Using the archiveadm command, you
can create new Unified Archives from global, non-global, and kernel zones running Oracle Solaris 11. In the
“Preparing the Environment” section, we uploaded an archive to the Glance repository for this lab.

Step 2: Access the Cloud by Command Line

The cloud management capability is available both on the command line as well as through the Horizon dashboard.
In this step, you will use the command line to check the cloud status.

1. Open a new terminal window, connect to the hol6739-01 server, and then change the user to root.

solaris@hol6739:~$ ssh solaris@hol6739-01


The authenticity of host 'hol6739-01 (192.168.99.101)' can't be established.
RSA key fingerprint is bd:4e:66:f0:7c:d6:1a:e9:f5:08:f0:8f:e6:6b:55:3a.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'hol6739-01,192.168.99.101' (RSA) to the list of known hosts.
Password: oow2016
Last login: Thu Oct 1 00:07:20 2016 from 192.168.99.1
Oracle Corporation SunOS 5.11 11.3 August 2016
solaris@hol6739-01:~$ su -
Password: oow2016
Oracle Corporation SunOS 5.11 11.3 August 2016
root@hol6739-01:~#

2. Set the global shell variables for Nova:

root@hol6739-01:~# export OS_USERNAME=nova

root@hol6739-01:~# export OS_PASSWORD=nova

root@hol6739-01:~# export OS_TENANT_NAME=service

root@hol6739-01:~# export OS_AUTH_URL=http://hol6739-01:5000/v2.0

3. After correctly configuring environment for Nova, display each service state by listing the services.

13
root@hol6739-01:~# nova host-list
+------------+-------------+----------+
| host_name | service | zone |
+------------+-------------+----------+
| hol6739-01 | conductor | internal |
| hol6739-01 | cert | internal |
| hol6739-01 | scheduler | internal |
| hol6739-01 | consoleauth | internal |
| hol6739-02 | compute | nova |
| hol6739-03 | compute | nova |
+------------+-------------+----------+

4. List the Cinder services available in the cloud.

root@hol6739-01:~# cinder service-list


+------------------+------------+------+---------+-------+----------------------------+--------------
---+
| Binary | Host | Zone | Status | State | Updated_at | Disabled
Reason |
+------------------+------------+------+---------+-------+----------------------------+--------------
---+
| cinder-scheduler | hol6739-01 | nova | enabled | up | 2016-09-01T02:41:37.000000 | -
|
| cinder-volume | hol6739-02 | nova | enabled | up | 2016-09-01T02:41:31.000000 | -
|
| cinder-volume | hol6739-03 | nova | enabled | up | 2016-09-01T02:41:30.000000 | -
|

You will find the host hol6739-01 working as a Cinder scheduler and the hosts hol6739-02 and hol6739-03 working
as a Cinder volume.

6. Check the images available in the Glance repository

root@hol6739-01:~# glance image-list


+--------------------------------------+--------------------+-------------+------------------+-------
-----+--------+
| ID | Name | Disk Format | Container Format | Size
| Status |
+--------------------------------------+--------------------+-------------+------------------+-------
-----+--------+
| be2e58d6-a2bb-4103-9428-bd1fb3a1dfb4 | WeblogicKernelZone | raw | bare |
2176286720 | active |
+--------------------------------------+--------------------+-------------+------------------+-------
-----+--------+

Summary
In this exercise, you have learned the basic concepts about OpenStack (Kilo), the architecture and resource
configuration for this HOL. You also learned how to manage your cloud resources using both the command lines
and the Horizon dashboard.

14
Exercise 2: Launching a VM Instance (20 Minutes)
In this exercise, you will use the OpenStack dashboard to launch a new VM instance, and deploy two Java EE
applications to Oracle WebLogic Server.

Background Information

In Oracle Solaris, the elastic virtual switch (EVS) enables users to manage multiple virtual switches that are spread
across several physical machines, typically in a cloud environment. Building on the network virtualization and
software-defined networking (SDN) capabilities, the EVS helps simplify administration by managing these virtual
switches as a single virtual switch, including the management of network traffic between VMs, MAC and IP
addresses, and VLANs and VXLANs. The EVS also enforces service-level agreements across the network through
resource control management.

Step 1: Create an Internal Network

Before launching instances, we need to prepare the internal network first.

1. On the left panel, select the Project > Network > Networks tab. Shown as Figure 2-1, there is no available
network in the very beginning. Click +Create Network on the right. A new dialog box pops up.

Figure 2-1. Network view

2. Input your network name as netXX, shown as Figure 2-2, where XX is the same number as in your username,
and then click Next.

15
Figure 2-2. Create network-1

3. Input the subnet name and network address as follows, and then click Next.

 Subnet Name: netXX_sub


 Network Address: 192.168.XX.0/24

Note: Here XX is the number used in your username.

Figure 2-3. Create network-2

4. Deselect the Enable DHCP option, and set the IP allocation pool from 192.168.XX.2 to 192.168.XX.100 in the
Allocation Pools field by entering 192.168.XX.2,192.168.XX.100, where XX is your number used in your
username. Then click Create.

The following is an example for net01_sub for user01. Don’t forget to change the value according to your username.
16
Figure 2-4. Create network-3

Note: If you want an internal network to connect to the public network, add that subnet to the cloud's external
network. In this HOL, we don’t create a public network.

You will now see the network in the list, as shown in Figure 2-5. Now you have created an internal network.

Figure 2-5. Network overview

5. Click the network name to get the detail information. Please remember the VXLAN segmentation ID, which will
be used in the following steps. For example, the VXLAN segmentation ID of net01, shown in the following figure,
is 2000.

17
Figure 2-6. Network detail

Step 2: Launch a VM Instance

1. On the left panel, click the Project > Compute > Instances tab, and then click Launch Instance on the right.

Figure 2-7. Instances overview

2. In the Launch Instance dialog box, set the instance information as follows:

 Instance Name: weblogickz


 Flavor: hol6739 – Oracle Solaris kernel zone with weblogic
 Instance Boot Source: Boot from image
 Image Name: WeblogicKernelZone(2.0GB)

18
Note: Do not click the Launch button now. You need to set a password in the next step. If you don’t have this flavor,
you can create one that has a configuration as listed in Figure 2-8.

In Exercise 1, we checked that there’s an image WeblogicKernelZone ready in the Glance repository. We just used
it to create our instance. See the example shown in Figure 2-8.

Figure 2-8. Launch Instance – Details screen

3. Click the Access & Security tab, and input a password for the instance’s root user. Please don’t forget your root
password; you can use oow2016 as your password.

19
Figure 2-9. Launch Instance – Access & Security screen

4. Click the Networking tab, and ensure that the network which we created in Step 1 is selected. Then click
Launch.

Figure 2-10. Launch Instance – Networking screen

Now the new instance appears in the list, as shown in Figure 2-11. It might take more than 5 minutes to create the
new instance.

20
Figure 2-11. Newly launched instance

5. Please leave the web browser here; we will be back to check the instance status after Step 3.

Step 3: Create a VXLAN-Based VNIC in the Oracle VM VirtualBox Client

1. Connect to hol6739-01 or use the previous terminal window, and show the preset properties of the EVS controller,
which are based on VXLAN, and the range is from 2000 to 3000.

root@hol6739-01:~# evsadm show-controlprop -o all


PROPERTY PERM VALUE DEFAULT FLAT VLAN_RANGE VXLAN_RANGE HOST
l2-type rw vxlan vlan -- -- -- --
uplink-port rw net0 -- no -- 2000-3000 --
uplink-port rw net0 -- no -- 2000-3000 hol6739-02
uplink-port rw net0 -- no -- 2000-3000 hol6739-03
uri-template rw ssh:// ssh:// -- -- -- --
uuid r- 9d30ad18-72c6-11e6-815e-115884abdd65 -- -- -- -- --
vlan-range rw -- -- -- -- -- --
vlan-range-avail r- -- -- -- -- -- --
vxlan-addr rw 0.0.0.0 0.0.0.0 -- -- -- --
vxlan-ipvers rw v4 v4 -- -- -- --
vxlan-mgroup rw 0.0.0.0 0.0.0.0 -- -- -- --
vxlan-range rw 2000-3000 -- -- -- -- --
vxlan-range-avail r- 2001-3000 -- -- -- -- --
root@hol6739-01:~# exit
solaris@hol6739-01:~$ exit
solaris@hol6739:~$

2. Change the user to root for the Oracle VM VirtualBox client:

solaris@hol6739:~$ su -
Password: oow2016
Oracle Corporation SunOS 5.11 11.3 August 2016
root@hol6739:~#

Note: All the numbers marked as yellow in this step must be replaced according to your system environment.

21
3. Do you still remember the VXLAN segmentation ID shown in Figure 2-6? Now we will build a VXLAN with the
same ID. Don’t forget to replace all the 20** marked in yellow with your own VXLAN ID.

 The interface property is your Oracle VM VirtualBox client interface name.


 vni is your internal network’s segmentation ID.

root@hol6739:~# dladm create-vxlan -p interface=net0,vni=20** vxlan20**

root@hol6739:~# dladm show-vxlan


LINK ADDR VNI MGROUP
vxlan1 192.168.99.1 2000 224.0.0.1

4. Create VNICs over the VXLAN link. Don’t forget to replace the 20** marked in yellow with your own VXLAN
ID.

root@hol6739:~# dladm create-vnic -l vxlan20** vnic1

root@hol6739:~# dladm show-vnic


LINK OVER SPEED MACADDRESS MACADDRTYPE VIDS
vnic1 vxlan1 10000 2:8:20:d9:df:5f random 0

5. Configure the IP address for vnic1.

It should be in the same subnet as the instance. Check the subnet of your instance, as shown in Figure 2-3. And in
Figure 2-4, you reserved an IP pool for the instances, so you’d better not use an IP address in this pool for your
client.

For example for user01, the reserved IP pool is from 192.168.1.2 to 192.168.1.100. So we’d like to set the client IP
address as 192.168.1.101. Please don’t forget to replace the text marked in yellow.
root@hol6739:~# ipadm create-ip vnic1
root@hol6739:~# ipadm create-addr -T static -a local=192.168.X.101/24 vnic1/v4

6. Now let’s check the connection between your client and your instance.

root@hol6739:~# ping 192.168.X.2

You can ping your instance when it is successfully launched.

7. Add the instance host IP address to your /etc/hosts file, and save the file. Don’t forget to replace the text
marked in yellow.

root@hol6739:~# vi /etc/hosts
::1 hol6739 localhost
127.0.0.1 hol6739 localhost loghost
192.168.99.101 hol6739-01
192.168.99.102 hol6739-02
192.168.99.103 hol6739-03
192.168.X.2 weblogickz

Step 4: Check the Launched Instance

1. Go back to the Horizon dashboard, and click Project > Compute > Instances to check the instance’s status.
Make sure that your instance is shown as “Running” now; otherwise, please wait for a few more minutes.

22
Figure 2-12. Instance overview

2. If the instance is running, click the Actions drop-down menu of the instance, select Console.

Figure 2-13. Actions menu

3. Click the Click here to show only console link to get a bigger terminal window.

23
Figure 2-14. Instance console

4. Press Enter in the terminal window and log in the instance console using the root user. Then input the password
that was configured in the process of launching the instance.

Then run the commands shown in Figure 2-15 to verify the instance’s resource configuration.

Figure 2-15. Verify instance resources

You will find that the instance weblogickz has two virtual CPUs operating at 4133 MHz, and with 4096 MB of
memory.

24
Step 5: Deploy the Java EE Applications to Oracle WebLogic Server

1. Start up the Oracle WebLogic Administrator service.

To do this, go to the terminal, and connect to weblogickz using the password configured in the Step 2. Then change
the user to wls.

root@hol6739:~# ssh root@weblogickz


The authenticity of host 'weblogickz (192.168.1.2)' can't be established.
RSA key fingerprint is 07:c8:86:31:f3:e5:7a:0d:c3:e7:40:e6:b0:cb:81:e1.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'weblogickz' (RSA) to the list of known hosts.
Password: oow2016
Last login: Thu Sep 8 15:15:22 2016 from 192.168.1.101
Oracle Corporation SunOS 5.11 11.3 November 2015
root@weblogickz:~# su - wls
Oracle Corporation SunOS 5.11 11.3 November 2015

Navigate to the domain directory, and run the startup script, which will print some log information to the screen.

wls@weblogickz:~$ cd Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/

wls@weblogickz:~/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain$ ./startWebLogic.sh &


………………..
<Sep 6, 2016, 6:05:22,603 AM UTC> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to
RUNNING.>

When you see the line “Server state changed to RUNNING”, this indicates that the Oracle WebLogic Administrator
service has started. Minimize the terminal window, but make sure you do not close the terminal window.

2. Back in the Firefox browser, create a new tab, and input the following link
http://webloigickz:7001/console to log in to the Oracle WebLogic Server administration console.
Input the username/password as weblogic/welcome1, as shown in Figure 2-16.

25
Figure 2-16. Oracle WebLogic Server 12c administration console

3. In the Domain Structure section, click Deployments to open the Configuration view. On the right, under
Deployments, click the Install button.

Figure 2-17. Deploy an application

4. Click the Upload your file(s) link. There’s a book store application ready in the Oracle VM VirtualBox client;
you can find it in /export/home/solaris/application/.

26
Figure 2-18. Upload an application file

5. The upload page is displayed. Click Browse to upload the deployment archive. A dialog box pops up. Choose the
file to upload.

Figure 2-19. Upload a deployment archive

6. Select the file BookStore.war file in /export/home/solaris/application, and then click Open,
shown in Figure 2-20.

27
Figure 2-20. File upload window

7. Then following the screens, keep all the default values and click the Next button three times. Then click the
Finish button. The application will be deployed to Oracle WebLogic Server.

8. Repeat Steps 3 through 7 to deploy the other application Hol6739Sample.war file to Oracle WebLogic
Server.

Note: BookStore.war and Hol6739Sample.war were created in the previous section “Preparing the
Environment.”

Summary

In this exercise, you have learned how to create an internal network and launch an instance using Horizon.

28
Exercise 3: Performing Live Migration with No
Memory Data Loss (10 Minutes)
In this exercise, we will use OpenStack commands to conduct a live migration and to verify that the live migration
process does not lose any memory data.

Background Information

Migration enables an administrator to move a VM instance from one compute host to another. This feature is useful
when a compute host requires maintenance. Migration can also be useful to redistribute the load when many VM
instances are running on a specific physical machine.

The following are the migration types:

• Non-live migration (sometimes referred to simply as “migration”). The instance is shut down for a period of
time so it can be moved to another hypervisor. In this case, the instance recognizes that it was rebooted.
• Live migration (or “true live migration”). There is almost no instance downtime, which is useful when the
instances must be kept running during the migration. The different types of live migration are
o Shared storage-based live migration. Both hypervisors have access to shared storage.
o Block live migration. No shared storage is required.
o Volume-backed live migration. Instances are backed by volumes rather than by ephemeral disk, no
shared storage is required, and migration is supported.

In Oracle OpenStack for Oracle Solaris, VM instances are Oracle Solaris Kernel Zones or non-global zones, which
are scalable high-density virtual environments of Oracle Solaris. Support for kernel zone live migration is extended
to Nova VM instances.

Figure 3-1. Oracle OpenStack for Oracle Solaris live migration

29
Step 1: Run the Application and Add Books to the Shopping Cart

The BookStore application is a simple shopping cart application. When a user logs in, a new session is created for
the user. When a user adds some books to the shopping cart, the data is stored in the session. We will do a live
migration and check whether the data is still in memory.

1. Create a new tab in Firefox and connect to the BookStore application by visiting the URL
http://weblogickz:7001/BookStore/bookstore/login.htm.

Log in to the application using the username/password user/user.

Figure 3-2. BookStore login

2. After logging in, choose a book and click Add to Shopping Cart. The book is in the shopping cart now. Click
Return to BookStore to choose more books.

Figure 3-3. Book list

30
Figure 3-4. Shopping cart with two books

Now you have some books in the shopping cart, and the session data is cached in the Oracle WebLogic memory.
Please leave the browser but don’t close it.

Step 2: Conduct an Instance Live Migration from the OpenStack Command Line

1. Verify that the Nova service has been configured correctly.

For node migration to succeed, you must ensure that the SSH key of each compute node is added to the authorized
keys file of each node. Thus, the nodes share identical files of authorized keys, as illustrated in the following figure:

Figure 3-5. Nova SSH key configuration

Open a new terminal window, and connect to the hol6739-02 server. Change to the nova user, and test the
hol6739-02 server's SSH connections to the other compute nodes.

solaris@hol6739:~$ ssh root@hol6739-02


The authenticity of host 'hol6739-02 (192.168.99.102)' can't be established.
RSA key fingerprint is ad:9c:dc:9f:56:45:93:96:79:4c:19:9b:13:d2:eb:9c.
Are you sure you want to continue connecting (yes/no)? yes
Password:oow2016

31
Last login: Fri Sep 9 01:50:25 2016 from 192.168.99.110
Oracle Corporation SunOS 5.11 11.3 June 2016
root@hol6739-02:~# su - nova

nova@hol6739-02:~$ ssh nova@hol6739-03 true

nova@hol6739-02:~$ exit

2. Verify that live migration–related services have started.

root@hol6739-02:~# svcs rad:local nova-compute kz-migr:stream

STATE STIME FMRI


online Sep_05 svc:/system/rad:local
online Sep_05 svc:/network/kz-migr:stream
online Sep_05 svc:/application/OpenStack/nova/nova-compute:default

root@hol6739-02:~# exit
solaris@hol6739:~$

3. Connect to hol6739-03, repeat the previous two steps for it, and ensure the compute node's SSH connections to
the other compute nodes work.

4. Connect to hol6739-01:

solaris@hol6739:~$ ssh root@hol6739-01


Password:oow2016
Last login: Fri Sep 9 01:55:25 2016 from 192.168.99.110
Oracle Corporation SunOS 5.11 11.3 June 2016

5. Set environmental variables for your OpenStack user. Please don’t forget to replace the XX with your number.

root@hol6739-01:~# export OS_USERNAME=userXX

root@hol6739-01:~# export OS_PASSWORD=userXX

root@hol6739-01:~# export OS_TENANT_NAME=projectXX

root@hol6739-01:~# export OS_AUTH_URL=http://hol6739-01:5000/v2.0

root@hol6739-01:~# nova list


+--------------------------------------+--------+--------+---------------+-------------+--------+
| ID | Name | Status |Task State | Power State|Networks |
+--------------------------------------+--------+--------+---------------+-------------+--------+
| d0386ae4-89a7-43de-967f-c83da513f7f3 | weblogickz| ACTIVE | - | Running |net01=192.168.1.2 |
+--------------------------------------+--------+--------+---------------+-------------+--------+

6. Show the VM details and determine which host the instance is running on and which flavor it is using.

root@hol6739-01:~# nova show weblogickz


+--------------------------------------+----------------------------------------------------------|
Property | Value
|+--------------------------------------+----------------------------------------------------------|
OS-DCF:diskConfig | MANUAL
|| OS-EXT-AZ:availability_zone | nova
|| OS-EXT-SRV-ATTR:host | hol6739-02
|| OS-EXT-SRV-ATTR:hypervisor_hostname | hol6739-02
|| OS-EXT-SRV-ATTR:instance_name | instance-0000008a
|| OS-EXT-STS:power_state | 1
|| OS-EXT-STS:task_state | -
|| OS-EXT-STS:vm_state | active
…………………………………………………………….

32
| created | 2016-09-08T08:50:59Z
|
| flavor | Hol6739 - Oracle Solaris kernel zone with weblogic (c3011d81-
cd7a-4621-b39a-8b9ecf4dc421) |
| hostId | 214709b36fa36460b76819680fdea1f64398e925acac8459bc3d1fc2
……………………………………….

7. Get the instance’s resource usage using its flavor ID. Below, the flavor ID is the ID shown in the previous step.

root@hol6739-01:~# nova flavor-show c3011d81-cd7a-4621-b39a-8b9ecf4dc421


+----------------------------+----------------------------------------------------+
| Property | Value |
+----------------------------+----------------------------------------------------+
| OS-FLV-DISABLED:disabled | False |
| OS-FLV-EXT-DATA:ephemeral | 0 |
| disk | 10 |
| extra_specs | {"zonecfg:brand": "solaris-kz"} |
| id | c3011d81-cd7a-4621-b39a-8b9ecf4dc421 |
| name | Hol6739 - Oracle Solaris kernel zone with weblogic |
| os-flavor-access:is_public | True |
| ram | 4096 |
| rxtx_factor | 1.0 |
| swap | |
| vcpus | 2 |
+----------------------------+----------------------------------------------------+

8. List the available compute hosts and choose the host you want to migrate the instance to.

root@hol6739-01:~# nova service-list --binary nova-compute


+----+--------------+----------------+------+---------+-------+----------------------------+-----
| Id | Binary | Host | Zone | Status | State | Updated_at |Disabled
Reason |
| 4 | nova-compute | hol6739-03 | nova | enabled | up | 2016-09-09T02:39:55.000000 | -
|
| 5 | nova-compute | hol6739-02 | nova | enabled | up | 2016-09-09T02:39:59.000000 | -
|

9. Check whether the hypervisor host has enough free capacity for the VM you want to migrate. Don’t forget to
replace the hol6739-0* by the target host server you want to migrate.

root@hol6739-01:~#nova host-describe hol6739-0*


+------------+----------------------------------+-----+-----------+---------+
| HOST | PROJECT | cpu | memory_mb | disk_gb |
+------------+----------------------------------+-----+-----------+---------+
| hol6739-03 | (total) | 64 | 65536 | 248 |
| hol6739-03 | (used_now) | 2 | 4608 | 10 |
| hol6739-03 | (used_max) | 2 | 4096 | 10 |
| hol6739-03 | 7687c94c9c4d4d4e8a6d94dd36e92664 | 2 | 4096 | 10 |
+------------+----------------------------------+-----+-----------+---------+

 The cpu column shows the sum of the virtual CPUs for instances running on the host.
The memory_mb column shows the sum of the memory (in MB) allocated to the instances that run on the hosts.
 The disk_gb column shows the sum of the root and ephemeral disk sizes (in GB) of the instances that run on
the hosts.
 The used_now row shows the sum of the resources allocated to the instances that run on the host plus the
resources allocated to the virtual machine of the host itself.
 The used_max row shows the sum of the resources allocated to the instances that run on the host.

You could use total value minus the used_now value to get number of available resources.
33
If the VM flavor fits on this hypervisor, continue on with the manual migration. If not, free up some resources or
choose another compute server. If the hypervisor node lacks enough capacity, the migration will fail.

10. Migrate the instance to another host using instance name weblogickz and the target host’s name.
Don’t forget to replace the hol6739-0* with the target host server you want to migrate to.

root@hol6739-01:~#nova live-migration weblogickz hol6739-0*

The migration time depends on the instance. For this HOL, the command might take 1 to 2 minutes. If it is
successful, the nova live-migration command produces no output.

Note: Sometimes, the migration might fail because the maximum number of live migrations to run concurrently is
one by default. If there is more than one request raised concurrently, only one live migration process will succeed.
So don’t worry about it; just try again, please.

11. Open a new terminal window, and connect to hol6739-01.

Show the VM details and check if it has been migrated successfully. Sometimes you might find the instance still has
the status of “MIGRATION.” If so, check again until it is shown as “ACTIVE.”

solaris@hol6739:~$ ssh root@hol6739-01


The authenticity of host 'hol6739-01 (192.168.99.101)' can't be established.
RSA key fingerprint is ad:9c:dc:9f:56:45:93:96:79:4c:19:9b:13:d2:eb:9c.
Are you sure you want to continue connecting (yes/no)? yes
Password:oow2016

root@hol6739-01:~# nova show weblogickz
+--------------------------------------+--------------------------------------------------------+
| Property | Value |
+--------------------------------------+--------------------------------------------------------+
| OS-DCF:diskConfig | MANUAL |
| OS-EXT-AZ:availability_zone | nova |
| OS-EXT-SRV-ATTR:host | hol6739-02 |
| OS-EXT-SRV-ATTR:hypervisor_hostname | hol6739-02 |
| OS-EXT-SRV-ATTR:instance_name | instance-0000008a |
| OS-EXT-STS:power_state | 1 |
| OS-EXT-STS:task_state | migrating |
| OS-EXT-STS:vm_state | active |
| …
| name | weblogickz |
| net01 network | 192.168.1.2 |

| security_groups | default |
| status | MIGRATING |
| tenant_id | 7687c94c9c4d4d4e8a6d94dd36e92664 |
| updated | 2016-09-12T07:06:46Z |
| user_id | bb62ec0cc7fb4271820fa5d92b250ca6 |

root@hol6739-01:~# nova show weblogickz


+--------------------------------------+--------------------------------------------------------+
| Property | Value |
+--------------------------------------+--------------------------------------------------------+
| OS-DCF:diskConfig | MANUAL |
| OS-EXT-AZ:availability_zone | nova |
| OS-EXT-SRV-ATTR:host | hol6739-03 |
| OS-EXT-SRV-ATTR:hypervisor_hostname | hol6739-03 |
| OS-EXT-SRV-ATTR:instance_name | instance-0000008a |
| OS-EXT-STS:power_state | 1 |
| OS-EXT-STS:task_state | - |
| OS-EXT-STS:vm_state | active |
| …

34
| name | weblogickz |
| net01 network | 192.168.1.2 |

| security_groups | default |
| status | ACTIVE |
| tenant_id | 7687c94c9c4d4d4e8a6d94dd36e92664 |
| updated | 2016-09-12T07:07:17Z |
| user_id | bb62ec0cc7fb4271820fa5d92b250ca6 |

Congratulations, you’ve just migrated your VM from hol6739-02 to hol6739-03.

Step 3: Check Whether Any Data Was Lost After Live Migration

Go Back to the Firefox window, and click the “refresh” button on the top bar.

Figure 3-6. Check shopping cart information

You will find the selected books are still in the shopping cart. The Oracle WebLogic session doesn’t suffer any loss
during the live migration.

Summary

In this exercise, you have migrated running instances from one OpenStack compute server to another using the
OpenStack command line. Also, you learned how to check cloud resources and instance status using commands.
The memory state is transferred from one machine to another without any data loss, which is important in a
production environment.

35
Exercise 4: Live Migration with Almost Zero
Downtime (15 Minutes)
In this exercise, we will conduct live migration using Horizon to verify that there is no service interruption during
the migration.

Note: Make sure the Oracle WebLogic service is running first.

Step 1: Start the Application

Start up the image download process.

To do this, create a new tab in Firefox and connect to the application by visiting the URL
http://weblogickz:7001/Hol6739Sample/. You will see that the image is beginning to download.

Figure 4-1. Hol6739Sample

Step 2: Conduct a Live Migration Using OpenStack Horizon

1. Open a new tab in Firefox, and open the Horizon dashboard by visiting the URL http://hol6739-01/horizon.
Click Admin > System > Instances to check your running instance.

36
Figure 4-2. Instances

In the admin view, you can find the host server of the running instance. For example, the weblogickz instance is
running on the hol6739-03 server now.

2. Check the resources the instance needs.

Click the link Hol6739-Oracle Solaris kernel zone with weblogic in the Size column. The Flavor Details window
shows two VCPUs, 4 GB of RAM, and 10 GB of disk space are required for the target host server.

Figure 4-3. Flavor details

3. Click Admin > System > Hypervisors, and then click the Compute Host tab to list the available compute hosts.

37
Figure 4-4. All Hypervisors screen showing all compute hosts

4. Change to the Hypervisor tab to see the available resources on hosts.

Figure 4-5. All Hypervisors screen showing available resources

5. Refresh the image if necessary.

Before performing a live migration, please go back to the Hol6739Sample tab and ensure the image has download
less than 50 percent. Otherwise, please refresh the page to download the image again.

38
6. Conduct a live migration using Horizon.

On the left panel, click the Admin > System > Instances to go back to the Instances view, and then click the
dropdown button and select Live Migrate Instance in the right view.

Figure 4-6. Instances screen – Live Migrate Instance menu item

7. In the Live Migration dialog box, select the target host server, and then click Live Migrate Instance.

Figure 4-7. Live Migrate

The migration process might take a few seconds. Sometimes, you will get a message in the top right corner saying
migration failed. The maximum number of live migrations to run concurrently is one by default. So just try again
please.

Don’t wait here. Please go to the next step to check whether the live migration will affect the image download.
39
Figure 4-8. Migrating

Step 4: Check Whether There Was Service Interruption During the Migration

1. Go back to the Hol6739Sample page, and observe it for a few minutes. Run next step at the same time.

The live migration didn’t stop the image download. The image continues to be shown line by line, and the download
percentage, number of downloaded bytes, and time consumed are shown in real time. There’s no visible interruption
in the instance live migration.

40
Figure 4-9. Check the download status

2. At the same time, open a small terminal window, and connect to the target host (for example, hol6739-02) to
check the TCP throughput for one minute. Please replace hol6739-0* with your target hostname.

solaris@hol6739:~$ ssh root@hol6739-0*


Password:oow2016
Last login: Fri Sep 9 02:25:25 2016 from 192.168.99.110
Oracle Corporation SunOS 5.11 11.3 June 2016
root@hol6739-02:~# ipstat -l 2 -c 1 60
Please wait...
SOURCE DEST PROTO INT BYTES

SOURCE DEST PROTO INT BYTES
hol6739-05 hol6739-02 TCP net0 522.3M
hol6739-02 hol6739-05 TCP net0 770.8K
Total: bytes in: 522.3M bytes out: 771.4K
SOURCE DEST PROTO INT BYTES
hol6739-05 hol6739-02 TCP net0 710.0M
hol6739-02 hol6739-05 TCP net0 1.0M
Total: bytes in: 710.0M bytes out: 1.0M
SOURCE DEST PROTO INT BYTES
hol6739-05 hol6739-02 TCP net0 709.7M
hol6739-02 hol6739-05 TCP net0 1.0M
Total: bytes in: 709.7M bytes out: 1.0M
SOURCE DEST PROTO INT BYTES
hol6739-05 hol6739-02 TCP net0 592.8M
hol6739-02 hol6739-05 TCP net0 877.5K
Total: bytes in: 592.8M bytes out: 878.0K
SOURCE DEST PROTO INT BYTES
hol6739-05 hol6739-02 TCP net0 414.1M
hol6739-02 hol6739-05 TCP net0 613.0K
Total: bytes in: 414.1M bytes out: 613.6K
41
SOURCE DEST PROTO INT BYTES
hol6739-05 hol6739-02 TCP net0 77.0M
hol6739-02 hol6739-03 TCP net0 223.3K
Total: bytes in: 77.2M bytes out: 342.1K
SOURCE DEST PROTO INT BYTES
hol6739-01 hol6739-02 TCP net0 2.6K
hol6739-02 hol6739-01 TCP net0 1.7K
Total: bytes in: 2.7K bytes out: 2.6K

You can find high TCP traffic for several seconds, but there’s no effect on the image download; the browser running
under the terminal continues to show the image line by line.

3. Go back to the OpenStack dashboard. You will find the instance is running on hol6739-02 now.

Figure 4-10. Instances screen

Summary

In this exercise, you have learned about how to migrate an Oracle Solaris kernel zone and check cloud resources
using Horizon, and you verified the ability of OpenStack to move running virtual machines from one host to another
with minimum downtime.

42
Appendix A: Creating the Java Code for Exercise 3
Use the procedures in this appendix to create the .java files and build files for Exercise 3.

Create the Directory Structure

1. The source code of the BookStore web application will be located in the
/export/home/solaris/application_sourcecode/BookStore directory. Create the directory if it
does not exist.

2. The building tools are put in /export/home/solaris/application_sourcecode/apache-ant-


1.9.6, which includes Apache Ant. Download these tools using the following link:
http://ant.apache.org/bindownload.cgi.

3. The common libraries are located in /export/home/solaris/application_sourcecode/lib.


Download the libraries using the following links:

json-lib-0.8.jar: http://www.java2s.com/Code/Jar/j/Downloadjsonlib08jar.htm
servlet.jar: http://www.java2s.com/Code/Jar/s/Downloadservletjar.htm

4. As shown in the directory structure for BookStore in the following figure, the build file is put in
/export/home/solaris/application_sourcecode/BookStore and the main source code is created in
/export/home/solaris/application_sourcecode/BookStore/src, while the JavaServer Pages
(JSP) and configuration files are created in
/export/home/solaris/application_sourcecode/BookStore/WebRoot. Please create these
directories.

Figure A-1 BookStore source code architecture


43
Create the Build Script File

Create the Ant build file build.xml for BookStore as follows:

<?xml version="1.0" encoding="UTF-8"?>


<project name="BookStore" default="deploy" basedir="./">
<property environment="env" />
<property name="webapp.name" value="BookStore" />
<property name="dist.dir" value="${basedir}/dist" />
<property name="ant.dir" value="../apache-ant-1.9.6" />
<property name="webRoot.dir" value="${basedir}/WebRoot" />
<property name="src.dir" value="${basedir}/src" />
<property name="lib.dir" value="../lib" />
<property name="build.dir" value="${basedir}/build" />
<property name="application.home" value="../../application" />

<!-- init classpath -->


<path id="project.classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
<!-- ant lib -->
<fileset dir="${ant.dir}">
<include name="**/*.jar" />
</fileset>
</path>

<!-- get the source compile classpath in a printable form -->


<pathconvert pathsep="${line.separator}| |-- "
property="echo.path.compile"
refid="project.classpath">
</pathconvert>

<!-- show classpath jars -->


<target name="print_classpath">
<echo message="|-- compile classpath"/>
<echo message="| |"/>
<echo message="| |-- ${echo.path.compile}"/>
</target>

<!-- remove previous dir -->


<target name="clear" description="remove old files">
<delete dir="${build.dir}" />
<delete dir="${dist.dir}" />
<delete file="${application.home}/${webapp.name}.war" />
<delete dir="${application.home}/${webapp.name}" />
</target>

<!-- create new dir -->


<target name="init" depends="clear" description="create new dir">
<mkdir dir="${build.dir}/classes" />
<mkdir dir="${dist.dir}" />
</target>

<!-- compile java -->


<target name="compile" depends="init" description="compile java">
<echo message="begin compile..." />
<javac srcdir="${src.dir}" destdir="${build.dir}/classes"
includeantruntime="false" nowarn="on"
deprecation="true" debug="true"
encoding="UTF-8" classpathref="project.classpath"
>
<compilerarg line="-Xlint:unchecked" />
<!-- <classpath refid="project.classpath" /> -->
</javac>

44
<echo message="end compile..." />
</target>
<!-- war package -->
<target name="war" depends="compile" description="project to war">
<echo message="begin war..." />
<war destfile="${dist.dir}/${webapp.name}.war" basedir="${webRoot.dir}"
webxml="${webRoot.dir}/WEB-INF/web.xml">
<lib dir="${lib.dir}" />
<classes dir="${build.dir}/classes" />
<fileset dir="${webRoot.dir}">
<include name="***.*" />
</fileset>
</war>
<echo message="end war..." />
</target>

<!-- copy war to deploy dir -->


<target name="deploy" depends="war" description="deploy project">
<echo message="begin deploy..." />
<copy file="${dist.dir}/${webapp.name}.war" todir="${application.home}" />
<echo message="end deploy..." />
</target>

</project>

Create the Java Files

1. To create the Java files for the login servlet in


/export/home/solaris/application_sourcecode/BookStore/wangyu/Servlets, copy the
code shown below and save it in a plain-text ASCII file named login.java.

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package wangyu.Servlets;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class login extends HttpServlet {


/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

valideUser(request, response);
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the
left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.

45
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>

private void valideUser(HttpServletRequest request, HttpServletResponse response) throws


IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String s = request.getScheme() + "://" + request.getServerName() + ":" +
request.getServerPort() + ((HttpServletRequest)request).getContextPath();
String gotoURL = request.getParameter("goto");
if (gotoURL == null) gotoURL = s+ "/bookstore/BookList.jsp";
String failURL = s+"/bookstore/login.htm";
if (!isUserValid(username, password)) {
response.sendRedirect(failURL);
} else {
HttpSession session = request.getSession();
session.removeAttribute("ShoppingCart");
session.setAttribute("username", username);
response.sendRedirect(gotoURL);
}
}
private boolean isUserValid(String username,String password)
{
if(username.equals("user") && password.equals("user"))
return true;
else
return false;
}
}

2. Copy the code shown below and save it in a plain-text ASCII file named AddToShoppingCartServlet.java,
and then put the file in directory
/export/home/solaris/application_sourcecode/BookStore/wangyu/Servlets.

package wangyu.Servlets;

46
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import wangyu.Domains.*;
public class AddToShoppingCartServlet extends HttpServlet {
public void service(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
String productCode = request.getParameter("productCode");
String description = request.getParameter("description");
int quantity = Integer.parseInt(
request.getParameter("quantity"));
double price = Double.parseDouble(
request.getParameter("price"));
Item item = new Item(productCode, description, price, quantity);
HttpSession session = request.getSession();
ShoppingCart cart = (ShoppingCart) session.
getAttribute("ShoppingCart");
if (cart == null) {
cart = new ShoppingCart();
session.setAttribute("ShoppingCart", cart);
}
cart.addItem(item);
response.sendRedirect(response.encodeRedirectURL(
"/BookStore/bookstore/DisplayShoppingCart.jsp"));
}
}

3. Copy the code shown below and save it in a plain-text ASCII file named RemoveItemServlet.java, and then
put the file in directory
/export/home/solaris/application_sourcecode/BookStore/wangyu/Servlets.

package wangyu.Servlets;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import wangyu.Domains.*;
public class RemoveItemServlet extends HttpServlet {
public void service(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
int itemIndex = Integer.parseInt(request.getParameter("item"));
HttpSession session = request.getSession();
ShoppingCart cart= (ShoppingCart) session.getAttribute("ShoppingCart");
if (cart == null) {
cart = new ShoppingCart();
session.setAttribute("ShoppingCart", cart);
}
cart.removeItem(itemIndex);

response.sendRedirect(response.encodeRedirectURL("/BookStore/bookstore/DisplayShoppingCart.jsp"));
}
}

4. Copy the code shown below and save it in a plain-text ASCII file named Item.java, and then put the file in
directory /export/home/solaris/application_sourcecode/BookStore/wangyu/ Domains.

package wangyu.Domains;
public class Item implements java.io.Serializable
{
public String productCode;
public String description;
public double price;
public int quantity;
public int orderQuantity;
47
public Item()
{
}
public Item(String aProductCode, String aDescription,
double aPrice, int aQuantity)
{
this(aProductCode, aDescription, aPrice, aQuantity, aQuantity);
}

public Item(String aProductCode, String aDescription,


double aPrice, int aQuantity, int anOrderQuantity)
{
productCode = aProductCode;
description = aDescription;
price = aPrice;
quantity = aQuantity;
orderQuantity = anOrderQuantity;
}
public String getProductCode() { return productCode; }
public void setProductCode(String aProductCode) {
productCode = aProductCode; }

public String getDescription() { return description; }


public void setDescription(String aDescription) {
description = aDescription; }

public double getPrice() { return price; }


public void setPrice(double aPrice) { price = aPrice; }

public int getQuantity() { return quantity; }


public void setQuantity(int aQuantity) { quantity = aQuantity; }

public int getOrderQuantity() { return orderQuantity; }


public void setOrderQuantity(int anOrderQuantity)
{
orderQuantity = anOrderQuantity;
}

public boolean equals(Object ob)


{
if (ob == this) return true;
if (!(ob instanceof Item)) return false;
if (((Item)ob).getProductCode().equals(getProductCode()))
{
return true;
}
return false;
}
}

5. Copy the code shown below and save it in a plain-text ASCII file named ProductCatalog.java, and then put
the file in directory
/export/home/solaris/application_sourcecode/BookStore/wangyu/Domains.

package wangyu.Domains;
import java.util.Vector;
public class ProductCatalog
{
protected Item[] items;
public ProductCatalog()
{
items = new Item[] {
new Item("PBJG-1", "Tier One (Tier One Series)", 9.86, 10),
new Item("PBJZ-1", "The Hope That Kills", 11.91, 10),
new Item("PBJS-1", "The Things We Wish Were True", 9.41, 70),
new Item("GCX", "Black Rain", 8.44, 15),

48
new Item("XC", "The Shelf Life of Happiness", 10.85, 34),
new Item("BH", "Love Warrior : A Memoir", 15.59, 16),
new Item("K9", "Publication Manual of the American...", 19.98, 12),
new Item("ATL", "Born to Run", 19.50, 15),
new Item("TEG", "Killing the Rising Sun: How America...", 18.00, 19),
new Item("UPC", "Empire of Storms (Throne of Glass)", 10.67, 1),
new Item("ALL", "Michael Vey 6: Fall of Hades", 12.91, 17),
new Item("ZYZZYVAS", "Harry Potter and the Cursed Child",17.98, 23),
new Item("SAM", "The Girl with the Lower Back Tattoo", 16.8, 19),
new Item("KATY", "Celebrity Picks", 16.00, 1),
new Item("FR44", "Llama Llama Red Pajama",11.95, 19),
new Item("PF44", "MyMathLab: Student Access Kit",22.00, 13),
new Item("LF44", "StrengthsFinder 2.0",13.94, 15)
};
}
public Item[] getItems()
{
return getItems(0, items.length);
}

public Item[] getItems(int startingLocation, int numItems)


{
if (numItems > items.length)
{
numItems = items.length;
}
if (startingLocation+numItems >= items.length)
{
startingLocation = items.length - numItems;
}
Item[] returnItems = new Item[numItems];

System.arraycopy(items, startingLocation,
returnItems, 0, numItems);

return returnItems;
}
public boolean itemsAvailable(int startingLocation)
{
if (startingLocation >= items.length) return false;
return true;
}
public Item findItemByProductCode(String productCode)
{
for (int i=0; i < items.length; i++)
{
if (items[i].getProductCode().equals(
productCode))
{
return items[i];
}
}
return null;
}
}

6. Copy the code shown below and save it in a plain-text ASCII file named ShoppingCart.java, and then put the
file in directory
/export/home/solaris/application_sourcecode/BookStore/wangyu/Domains.

package wangyu.Domains;

import java.util.*;
import java.io.*;

public class ShoppingCart implements java.io.Serializable {

49
protected Vector items;

public ShoppingCart() {
items = new Vector();
}

public Vector getItems() {


return (Vector) items.clone();
}

@SuppressWarnings("unchecked")
public synchronized void addItem(Item newItem) {
Enumeration e = items.elements();

while (e.hasMoreElements()) {
Item currItem = (Item) e.nextElement();

if (newItem.equals(currItem)) {
currItem.orderQuantity = currItem.orderQuantity
+ newItem.orderQuantity;
return;
}
}
items.addElement(newItem);
}

public synchronized void removeItem(int itemIndex) {


Item item = (Item) items.elementAt(itemIndex);
item.orderQuantity = item.orderQuantity - item.quantity;

if (item.orderQuantity <= 0) {
items.removeElementAt(itemIndex);
}
}

protected static int nextOrderNumber = 1;


}

Create the Web Page JSP File

1.Copy the code shown below and save it in a plain-text ASCII file named login.htm, and then put the file in
directory
/export/home/solaris/application_sourcecode/BookStore/WebRoot/bookstore/.

<!doctype html>
<html lang="zh">
<head>
<title>login</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="<%=basePath%>">
<style>
@import url('css/bootstrap.css');
@charset "utf-8";

body {
width: 100%;
text-align: center;
}

#loginForm {
margin: 200px auto 0;
50
display: inline-block;
padding: 10px;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.3),
0 3px 7px rgba(0, 0, 0, 0.3),
inset 0 1px rgba(255,255,255,1),
inset 0 -3px 2px rgba(0,0,0,0.25);
border-radius: 5px;
height: 100px;
position: relative;
}

.input-group {
width: 280px;
font-family:'Microsoft YaHei',SimHei;
}

.input-group:first-child {
margin-bottom: 10px;
}

.input-group input {
box-shadow: inset 0 0 5px rgba(0,0,0,0.1), inset 0 3px 2px rgba(0,0,0,0.1);
background-color: #f9f9f9;
}

.input-group-addon {
color: #777;
background-color: #f9f9f9;
box-shadow: inset 0 0 5px rgba(0,0,0,0.1), inset 0 3px 2px rgba(0,0,0,0.1);
}

.submit {
display: inline-block;
width: 65px;
height: 65px;
border-radius: 50%;
border: none;
box-shadow: 0 0 2px rgba(0,0,0,0.1), 0 3px 2px rgba(0,0,0,0.1), inset 0 -3px 2px rgba(0,0,0,0.2);
background-color: white;
position: relative;
top: -73px;
z-index: 2;
right: -142px;
padding: 10px;
}

.submit:after {
content: "";
width: 10px;
height: 10px;
position: absolute;
top: -2px;
left: 30px;
background: #ffffff;
box-shadow: 0 62px white, -32px 31px white;
}

#submit,
#submit:focus {
border: none;
height: 45px;
width: 45px;
border-radius: 50%;
background: #52cfeb;
background: -moz-linear-gradient(#52cfeb, #42A2BC);
background: -ms-linear-gradient(#52cfeb, #42A2BC);
background: -o-linear-gradient(#52cfeb, #42A2BC);
background: -webkit-gradient(linear, 0 0, 0 100%, from(#52cfeb), to(#42A2BC));
51
background: -webkit-linear-gradient(#52cfeb, #42A2BC);
background: linear-gradient(#52cfeb, #42A2BC);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.3),
0 1px 2px rgba(0,0,0,0.35),
inset 0 3px 2px rgba(255,255,255,0.2),
inset 0 -3px 2px rgba(0,0,0,0.1);
outline: none;
}

#submit:active {
background: #42A2BC;
box-shadow: inset 0 0 5px rgba(0,0,0,0.3), inset 0 3px 4px rgba(0,0,0,0.3);
}

#submit:hover {
background: #42A2BC;
}

#submit:hover {

#submit span {
color: white;
font-size: 22px;
}

#register {
position: absolute;
top: 86px;
left: 13px;
font-size: 22px;
background: transparent;
border: none;
color: #52cfeb;
height: 105px;
width: 105px;
border-radius: 50%;
font-weight: bold;
outline: none;
}

#register:hover {
color: yellow;
}

#registerModal .input-group {
margin: 0 auto;
margin-bottom: 15px;
}

#registerButton {
width: 280px;
margin-bottom: 30px;
font-weight: bold;
font-size: 16px;
}

.tooltip {
width: 150px;
}

.tooltip-inner {
background: rgba(0,0,0,0.7);
}
</style>
</head>
52
<body>

<div id="container">
<form id="loginForm" action="/BookStore/login" method="POST">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-user"></i>
</div>
<input id="username" name="username" type="text" placeholder="User Name" class="form-control">
</div>
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-lock"></i>
</div>
<input id="password" name="password" type="password" placeholder="Password" class="form-
control">
</div>
<div class="submit">
<button id="submit" name="submit" type="submit">
<span class="glyphicon glyphicon-arrow-right"></span>
</button>
</div>

</form>
</div>

<script type="text/javascript" src="js/jquery-1.12.2.min.js"></script>


<script src="js/bootstrap.min.js"></script>

<script>
(function(){
var $loginForm = $("#loginForm");

function showTip(selector, content){


$(selector).tooltip('destroy')
$(selector).tooltip({
animation: true,
placement: 'top auto',
title: content,
trigger: "manual"
});
$(selector).tooltip('show');

setTimeout(function(){
$(selector).tooltip('hide');
}, 2000);
}

$loginForm.submit(function(e){
if($("#username").val() == "") {
showTip("#username", "Please input your name:");
e.preventDefault();
} else if($("#password").val() == "") {
showTip("#password", "password please!");
e.preventDefault();
}
});
})(jQuery);
</script>
</body>
</html>

2. Copy the code shown below and save it in a plain-text ASCII file named DisplayShoppingCart.jsp, and then
put the file in directory
/export/home/solaris/application_sourcecode/BookStore/WebRoot/bookstore/.

53
<%--
Document : DisplayShoppingCart
Created on : 2016-9-8, 11:42:47
--%>
<%@ page language="java" import="wangyu.Domains.*,java.util.*,java.text.*" %>

<%-- Show the header with the shopping cart image --%>
<table border="0">
<tr><td><img src="img/cart.png"><td><h1>Shopping Cart</h1>
</table>

<%
ShoppingCart cart = (ShoppingCart) session.getAttribute("ShoppingCart");
if (cart == null)
{
cart = new ShoppingCart();
session.setAttribute("ShoppingCart", cart);
}
java.util.Vector items = cart.getItems();

// If there are no items, tell the user that the cart is empty.
if (items.size() == 0)
{
out.println("<h3>Your shopping cart is empty.</h3>");
}
else
{
%>
<%-- Display the header for the shopping cart table --%>
<br>
<table border=4>
<tr><th>Description</th><th>Quantity</th><th>Price</th></tr>
<%
int numItems = items.size();
// Get a formatter to write out currency values.
NumberFormat currency = NumberFormat.getCurrencyInstance();
for (int i=0; i < numItems; i++)
{
Item item = (Item) items.elementAt(i);
// Print the table row for the item.
out.print("<tr><td>");
out.print(item.description);
out.print("</td><td>");
out.print(item.orderQuantity);
out.print("</td><td>");
out.print("$"+item.price);
// Print out a link that allows the user to delete an item from the cart.
out.println("</td><td>"+
"<a href=\"/BookStore/RemoveItemServlet?item="+
i+"\">Remove</a></td></tr>");
}
}
%>
</table>
<a href="/BookStore/bookstore/BookList.jsp">Return to BookStore</a>

3. Copy the code shown below and save it in a plain-text ASCII file named BookList.jsp, and put then the file in
directory
/export/home/solaris/application_sourcecode/BookStore/WebRoot/bookstore/.

<%@ page language="java"


import="wangyu.Domains.ProductCatalog,wangyu.Domains.*,java.net.*,java.text.*" %>

<%!
// Declare a constant for the number of items to show on a page.
public static final int ITEMS_PER_PAGE = 5;

54
%>
<html>
<body bgcolor="#ffffff">
<table border="0">
<tr><td><img src="img/bookstore.png"><td><h1>My Book Store--<%=session.getAttribute("username")%></h1>
</table>
<hr/>
<a href="/BookStore/bookstore/DisplayShoppingCart.jsp">View Shopping Cart</a>
<p>
<h1>Available Books</h1>
<table border="1">
<tr><th>Description<th>Quantity<th>Price
<%
// Get the shared product catalog.
ProductCatalog catalog = (ProductCatalog) application.getAttribute(
"ProductCatalog");
// If the shared product catalog hasn't been created yet, create it.
if (catalog == null)
{
synchronized (application)
{
catalog = new ProductCatalog();
application.setAttribute("ProductCatalog", catalog);
}
}
// Get the next starting position for displaying catalog items.
String startingPositionStr = (String) request.
getParameter("StartingPosition");
int startingPosition = 0;
// If there is a starting position parameter, parse it as an integer.
if (startingPositionStr != null)
{
try
{
// If there's an error parsing the number, the starting position will
// just remain 0.
startingPosition = Integer.parseInt(startingPositionStr);
}
catch (Exception ignore)
{
}
}
// Get ITEMS_PER_PAGE items at a time.
Item[] items = catalog.getItems(startingPosition, ITEMS_PER_PAGE);

// Get a currency formatter for showing the price.


NumberFormat currency = NumberFormat.getCurrencyInstance();
for (int i=0; i < items.length; i++)
{
Item item = items[i];
// Create the URL for adding the item to the shopping cart.
String addItemURL =
"/BookStore/AddToShoppingCartServlet?"+
"productCode="+URLEncoder.encode(item.getProductCode())+
"&description="+URLEncoder.encode(item.getDescription())+
"&quantity="+URLEncoder.encode(""+item.getQuantity())+
"&price="+URLEncoder.encode(""+item.getPrice());
%>
<tr><td><%=item.getDescription()%></td><td><%=item.getQuantity()%>
</td><td>$<%=item.getPrice()%></td>
<td><a href="<%=addItemURL%>">Add to Shopping Cart</a></td></tr>
<%
}
%>
</table>
<table border="0">
<tr>
<%
55
if (startingPosition > 0)
{
int prevPosition = startingPosition-ITEMS_PER_PAGE;
// Don't let the starting position go negative.
if (prevPosition < 0) prevPosition = 0;
// Write out a link to display the previous catalog page.
out.println("<td><a
href=\"/BookStore/bookstore/BookList.jsp?StartingPosition="+prevPosition+"\">&lt;&lt;Prev</a></td>");
}
// Compute the next starting position in the catalog.
int nextPosition = startingPosition+ITEMS_PER_PAGE;
// Make sure that there are still items to display at that starting
// position (that is, make sure nextPosition isn't greater than the total
// catalog size).
if (catalog.itemsAvailable(nextPosition))
{
// Write out a link to display the next catalog page.
out.println("<td><a
href=\"/BookStore/bookstore/BookList.jsp?StartingPosition="+nextPosition+"\">Next&gt;&gt;</a></td>");
}
%>
</tr>
</table>
</body>
</html>

Create the Web Configuration File

Create the web deployment descriptor web.xml file in


/export/home/solaris/application_sourcecode/BookStore/WebRoot/WEB-INF.

<?xml version="1.0" encoding="UTF-8"?>


<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-
app_3_1.xsd">
<servlet>
<servlet-name>AddToShoppingCartServlet</servlet-name>
<servlet-class>wangyu.Servlets.AddToShoppingCartServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>wangyu.Servlets.login</servlet-class>
</servlet>
<servlet>
<servlet-name>RemoveItemServlet</servlet-name>
<servlet-class>wangyu.Servlets.RemoveItemServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AddToShoppingCartServlet</servlet-name>
<url-pattern>/AddToShoppingCartServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RemoveItemServlet</servlet-name>
<url-pattern>/RemoveItemServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/bookstore/login.htm</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>
56
30
</session-timeout>
</session-config>
</web-app>

Create the js, fonts, css, and img Folders

1. Create folders using the following commands in the directory


/export/home/solaris/application_sourcecode/BookStore/WebRoot.

solaris@hol6739:~/application_sourcecode/BookStore/WebRoot$ cd bookstore/
solaris@hol6739:~/application_sourcecode/BookStore/WebRoot/bookstore$ mkdir fonts css img js

2. Download files from web using the following link, and put bootstrap.css in the folder css; put
glyphicons-halflings-regular.eot, glyphicons-halflings-regular.svg, glyphicons-
halflings-regular.ttf, and glyphicons-halflings-regular.woff in folder fonts; and put
bootstrap.min.js in folder js.

http://blog.getbootstrap.com/2013/12/05/bootstrap-3-0-3-released/

3. Please copy the following images and put them in the folder img. Name the files bookstore.png and
cart.png.

Figure A-2. Bookstore image Figure A-3. Cart image

Compile the Source Code and Export a WAR File

Use the Ant tool to compile the source code. It will export a WAR file to directory
/export/home/solaris/application.

solaris@hol6739:~/application_sourcecode/BookStore$ ant
Buildfile: /export/home/solaris/application_sourcecode/BookStore/build.xml
clear:
[delete] Deleting directory /export/home/solaris/application_sourcecode/BookStore/build
[delete] Deleting directory /export/home/solaris/application_sourcecode/BookStore/dist
[delete] Deleting: /export/home/solaris/application/BookStore.war
init:
[mkdir] Created dir: /export/home/solaris/application_sourcecode/BookStore/build/classes
[mkdir] Created dir: /export/home/solaris/application_sourcecode/BookStore/dist
compile:
[echo] begin compile...
[javac] Compiling 6 source files to
/export/home/solaris/application_sourcecode/BookStore/build/classes
[echo] end compile...
war:
[echo] begin war...
[war] Building war: /export/home/solaris/application_sourcecode/BookStore/dist/BookStore.war
[echo] end war...

57
deploy:
[echo] begin deploy...
[copy] Copying 1 file to /export/home/solaris/application
[echo] end deploy...
BUILD SUCCESSFUL
Total time: 4 seconds

58
Appendix B: Creating the Java Code for Exercise 4
Use the procedures in this appendix to create the .java files and build files for Exercise 4.

Create the Directory Structure

1. The source code of the Hol6739Sample web application will be located in the
/export/home/solaris/application_sourcecode/Hol6739Sample.Create the directory if it does
not exist.

2. The building tools are put in /export/home/solaris/application_sourcecode/apache-ant-


1.9.6, which includes Apache Ant. You can download these tools using the following link:
http://ant.apache.org/bindownload.cgi.

3. The common libraries are located in /export/home/solaris/application_sourcecode/lib.


Download the libraries using the following links:

json-lib-0.8.jar: http://www.java2s.com/Code/Jar/j/Downloadjsonlib08jar.htm
servlet.jar: http://www.java2s.com/Code/Jar/s/Downloadservletjar.htm

4. As shown in the directory structure for Hol6739Sample in the following figure, the build file is put in
/export/home/solaris/application_sourcecode/Hol6739Sample and the main source code is
created in /export/home/solaris/application_sourcecode/Hol6739Sample/src, while the JSP
and configuration files are created in
/export/home/solaris/application_sourcecode/Hol6739Sample/WebRoot. Please create these
directories.

59
Figure B-1. Hol6739Sample source code architecture

Create the Build Script File

Create the Ant build file


/export/home/solaris/application_sourcecode/Hol6739Sample/build.xml for
Hol6739Sample as follows:

<?xml version="1.0" encoding="UTF-8"?>


<project name="Hol6739Sample" default="deploy" basedir="./">
<property environment="env" />
<property name="webapp.name" value="Hol6739Sample" />
<property name="dist.dir" value="${basedir}/dist" />
<property name="ant.dir" value="../apache-ant-1.9.6" />
<property name="webRoot.dir" value="${basedir}/WebRoot" />
<property name="src.dir" value="${basedir}/src" />
<property name="lib.dir" value="../lib" />
<property name="build.dir" value="${basedir}/build" />
<property name="application.home" value="../../application" />

<!-- init classpath -->


<path id="project.classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
<!-- ant lib -->
<fileset dir="${ant.dir}">
<include name="**/*.jar" />
</fileset>
</path>

<!-- get the source compile classpath in a printable form -->


<pathconvert pathsep="${line.separator}| |-- "
property="echo.path.compile"
refid="project.classpath">
</pathconvert>

60
<!-- show classpath jars -->
<target name="print_classpath">
<echo message="|-- compile classpath"/>
<echo message="| |"/>
<echo message="| |-- ${echo.path.compile}"/>
</target>

<!-- remove previous dir -->


<target name="clear" description="remove old files">
<delete dir="${build.dir}" />
<delete dir="${dist.dir}" />
<delete file="${application.home}/${webapp.name}.war" />
<delete dir="${application.home}/${webapp.name}" />
</target>

<!-- create new dir -->


<target name="init" depends="clear" description="create new dir">
<mkdir dir="${build.dir}/classes" />
<mkdir dir="${dist.dir}" />
</target>

<!-- compile java -->


<target name="compile" depends="init" description="compile java">
<echo message="begin compile..." />
<javac srcdir="${src.dir}" destdir="${build.dir}/classes"
includeantruntime="false" nowarn="on"
deprecation="true" debug="true"
encoding="UTF-8" classpathref="project.classpath"
>
<compilerarg line="-Xlint:unchecked" />
<!-- <classpath refid="project.classpath" /> -->
</javac>
<echo message="end compile..." />
</target>
<!-- war package -->
<target name="war" depends="compile" description="project to war">
<echo message="begin war..." />
<war destfile="${dist.dir}/${webapp.name}.war" basedir="${webRoot.dir}"
webxml="${webRoot.dir}/WEB-INF/web.xml">
<lib dir="${lib.dir}" />
<classes dir="${build.dir}/classes" />
<fileset dir="${webRoot.dir}">
<include name="***.*" />
</fileset>
</war>
<echo message="end war..." />
</target>

<!-- copy war to deploy dir -->


<target name="deploy" depends="war" description="deploy project">
<echo message="begin deploy..." />
<copy file="${dist.dir}/${webapp.name}.war" todir="${application.home}" />
<echo message="end deploy..." />
</target>

</project>

Create the Java Files

To create the Java files for the servlet in


/export/home/solaris/application_sourcecode/Hol6739Sample/, copy the code shown below
and save it in a plain-text ASCII file named Hol6739Servlet.java.

import java.io.File;

61
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
/**
* Servlet implementation class ServletDownload
*/
public class Hol6739Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private int progressNum = 0;
private long fileSize = 0;
public static String appPath;
private long maxInterval = 0;
private long maxInterval2 = 0;
private long minInterval = 0;
private float avgInterval = 0;
String maxIntervalDate = null;
String maxIntervalDate2 = null;
private float timeConsumed=0;
/**
* @see HttpServlet#HttpServlet()
*/
public Hol6739Servlet() {
super();
// TODO Auto-generated constructor stub
}
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
super.init();
String path = this.getClass().getClassLoader().getResource("")
.getPath();
appPath = path.replace("WEB-INF/classes/", "");
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

if (request.getParameter("flag") != null
&& request.getParameter("flag").equals("progressBar")) {
JSONObject json = new JSONObject();
json.put("progressBar",
String.format("%.1f", (((float)progressNum ) / fileSize) * 100));
json.put("progressNum", progressNum + "Byte");
json.put("fileSize", fileSize + "Byte");
json.put("maxInterval", maxInterval);
json.put("maxIntervalDate", maxIntervalDate);
json.put("maxInterval2", maxInterval2);
json.put("maxIntervalDate2", maxIntervalDate2);
json.put("timeConsumed", timeConsumed);
PrintWriter pw = response.getWriter();
pw.print(json.toString());
pw.close();
} else {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
progressNum = 0;
62
long start=(new Date()).getTime();
String filename = request.getParameter("filename");
response.setContentType(getServletContext().getMimeType(filename));
response.setHeader("Content-Disposition", "attachment;filename="+ filename);
String fullFileName = appPath + "download/" + filename;
fileSize = (new File(fullFileName)).length();
InputStream in = new FileInputStream(fullFileName);
OutputStream out = response.getOutputStream();
long previous = (new Date()).getTime();
long after = (new Date()).getTime();
long timeSum = 0;
maxInterval = 0;
maxInterval2 = 0;
minInterval = 0;
avgInterval = 0;
int tmp = 0;
int b;
byte[] swap = new byte[20];
while ((b = in.read(swap)) != -1) {
tmp++;
//previous = (new Date()).getTime();
progressNum += b;
out.write(swap, 0, swap.length);
out.flush();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
previous=after;
after = (new Date()).getTime();
long timeInterval = after - previous;
if (minInterval == 0)
minInterval = timeInterval;
if (timeInterval > maxInterval) {
maxInterval2=maxInterval;
maxIntervalDate2=(maxIntervalDate==null?df.format(previous):maxIntervalDate);
maxInterval = timeInterval;
maxIntervalDate = df.format(previous);
}
if (timeInterval < maxInterval && timeInterval > maxInterval2)
{maxInterval2 = timeInterval;
maxIntervalDate2 = df.format(previous);
}
if (timeInterval < minInterval)
minInterval = timeInterval;
timeSum += timeInterval;
long now=(new Date()).getTime();
timeConsumed=(now-start)/1000;
}
avgInterval = (float) ((timeSum * 1.0) / tmp);
in.close();
out.close();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}

63
Create the Web Page JSP File

Copy the code shown below and save it in a plain-text ASCII file named index.jsp in directory
/export/home/solaris/application_sourcecode/Hol6739Sample/WebRoot.

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>


<%
String path = request.getContextPath();
String basePath =
request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">


<html>
<head>
<base href="<%=basePath%>">

<title>Hol6739</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" src="js/jquery-3.1.0.js"></script>
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<script type="text/javascript">
$(function(){
var id=window.setInterval(downloadProcess,100);
function downloadProcess()
{
$.ajax({
url:'Hol6739Servlet',
data:{flag:'progressBar'},
dataType:'json',
error:function(){
alert("error occured!!!");
},
success:function(data){
$.each(data.jsonArray,function(index){
$.each(data.jsonArray[index],function(key,value){
alert(key+":"+value);
});
});

if(data.progressBar>=110)
window.clearInterval(id);
$('#progressStatus').html("[Download Percentage: "+data.progressBar+"%]
"+"[Download: "+data.progressNum+"] [Time Consumed: "+data.timeConsumed+"s]");
// $('#intervalStatus').html("[Max Interval: "+data.maxInterval+"ms Time:
"+data.maxIntervalDate+"] [Max Interval2: "+data.maxInterval2+"ms Time:
"+data.maxIntervalDate2+"]").css("");
}
});
}
});
</script>
</head>

<body style="text-align:center;">
<div align="center" style="width:100%;height:5%;font-size: 23px;font-weight:bold">Zero Downtime
with OpenStack Live Migration</div>
<div id="progressStatus" style="height:20px;color:#F00"></div>
<img height="85%" width="80%" src="Hol6739Servlet?filename=sample.bmp" alt=" Downloading...."
border="1" />
64
</body>
</html>

Create the Web Configuration File

Create the web deployment descriptor web.xml file in


/export/home/solaris/application_sourcecode/Hol6739Sample/WebRoot/WEB-INF.

<?xml version="1.0" encoding="UTF-8"?>


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-
app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>Hol6739Servlet</servlet-name>
<servlet-class>Hol6739Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hol6739Servlet</servlet-name>
<url-pattern>/Hol6739Servlet</url-pattern>
</servlet-mapping>
</web-app>

Create the js and download Folders

1. Create folders using the following commands in the directory


/export/home/solaris/application_sourcecode/Hol6739Sample/WebRoot.

solaris@hol6739:~/application_sourcecode/Hol6739Sample/WebRoot$ mkdir js download


solaris@hol6739:~/application_sourcecode/Hol6739Sample/WebRoot$ ls
download js

2. Download files from the web using the following link, and put jquery-3.1.0.js in the folder js:
https://code.jquery.com/jquery-3.1.0.js.

3. Please copy the following .bmp image and put it in the folder download and name it sample.bmp.

Note: Ensure the image type is .bmp and the size is between 2 MB and 3 MB.

65
Figure B-2. Oracle buildings

Compile the Source Code and Export a WAR File

Use the Ant tool to compile the source code. It will export a WAR file to directory
/export/home/solaris/application.

solaris@hol6739:~/application_sourcecode/Hol6739Sample$ ant
Buildfile: /export/home/solaris/application_sourcecode/Hol6739Sample/build.xml
clear:
[delete] Deleting directory /export/home/solaris/application_sourcecode/Hol6739Sample/build
[delete] Deleting directory /export/home/solaris/application_sourcecode/Hol6739Sample/dist
[delete] Deleting: /export/home/solaris/application/Hol6739Sample.war
init:
[mkdir] Created dir: /export/home/solaris/application_sourcecode/Hol6739Sample/build/classes
[mkdir] Created dir: /export/home/solaris/application_sourcecode/Hol6739Sample/dist
compile:
[echo] begin compile...
[javac] Compiling 1 source file to
/export/home/solaris/application_sourcecode/Hol6739Sample/build/classes
[echo] end compile...
war:
[echo] begin war...
[war] Building war:
/export/home/solaris/application_sourcecode/Hol6739Sample/dist/Hol6739Sample.war
[echo] end war...
deploy:
[echo] begin deploy...
[copy] Copying 1 file to /export/home/solaris/application
[echo] end deploy...

BUILD SUCCESSFUL
Total time: 4 seconds
66
Summary
You have successfully completed the "Zero Downtime with OpenStack Live Migration for Oracle Solaris Kernel
Zones" hands-on lab! You have studied how to manage OpenStack resources using both the Horizon dashboard and
the command line. You have also learned about how OpenStack is integrated with Oracle Solaris.

See Also
 “Migrating an Oracle Solaris Kernel Zone”
 “Installing and Configuring OpenStack (Kilo) in Oracle Solaris”
 “Multi-node Solaris 11.2 OpenStack on SPARC Servers”
 Oracle WebLogic Server 12.2.1.1 documentation
 OpenStack technology community

About the Authors


Yan Zhang is a software engineer in Oracle’s ISV Engineering group. She is focused on Oracle Solaris and Java.
Her duties include supporting local ISVs to run Java applications best on Oracle Solaris and SPARC servers.

Xiaosong (Chris) Zhu is a senior software engineer in Oracle’s ISV Engineering group. She is focused on Oracle
Solaris and C/C++. Her duties include evangelizing Oracle Solaris and supporting local ISVs to run C/C++
applications best on Oracle Solaris and SPARC servers.

Yu Wang presently works in Oracle’s ISV Engineering group as a principal software engineer. His duties include
supporting local ISVs and evangelizing about Oracle Solaris and Java technologies.

67

You might also like