Cisco UCS (Unified Computing System, codenamed Project California during development) was introduced in 2009. It was originally developed as a data center server technology optimized for VMware virtualization workloads, but nowadays is used in many mid-size and large enterprises.
One of the key advantages of UCS from a system administration perspective is the radical reduction in system management points to a single management point called the UCS Manager (UCSM) which is implemented as an NX-OS kernel module in a Cisco Nexus 6000 series Fabric Interconnect (FI) switch. A FI is essentially a Top-Of-Rack switch as far as UCS is concerned.
The core of UCSM is the Data Management Engine (DME) which is persisted in an XML database. A DME uses a number of Application Gateways (AG) to talk to the managed physical aspects of the system–server baseboard (CIMC – Cisco Integrated Management Controller), supported LAN and SAN devices (CNAs and HBAs), fabric subsystems (IOM/FEX), and the FI itself.
The UCS Platform Emulator (UCSPE) was developed by Cisco to enable the use of Cisco UCS Manager and the UCS XML API without requiring actual physical hardware. Amongst other uses, it enables users to become familiar with the UCSM GUI, troubleshoot UCS configuration problems, and provides a convenient way to demonstrate UCS operations for training purposes.
This post looks under the hood at the internals of the UCSPE and documents a number of interesting things. It is assumed that you are familiar with UCS if you are reading this post and therefore no attempt is made to explain, UCS, UCSM, service profiles, the underlying UCS architecture or UCS managed objects.
First of all, here are my VMware Workstation virtual machine settings. The only changes I have made to the downloaded OVA is to change the network settings for the three interfaces shown from NAT to host-only and remove the floppy drive.
After starting the VM, you can see UCSPE is running on some sort of a Red Hat or downstream derivative:
What is displayed above is the classic Red Hat SysVinit scripts output.
When we get root access (how is explained later in this post), from /proc/version and the install log, we determine the OS is a cut-down version of CentOS 4.4.3 (see tiny-centos.sh below) running on Linux kernel v2.6.9 with SELinux disabled. The default runlevel is 3 and no GUI is available except via documents and Perl-based CGI applications served by an Apache web sever.
# cat /root/tiny-centos.sh #!/bin/sh # # Copyright (c) 2007 Owl River Company # info@owlriver.com # 614 - 488 6954 # IAM=`id -u` [ "x$IAM" != "x0" ] && { echo "Error: only the root user may run me with effect" 1>&2 exit 1 } VERBOSE="" # VERBOSE="y" [ "x$1" = "x-v" ] && { export VERBOSE="-v" shift 1 } # DIRTY="1" while [ "x$DIRTY" = "x1" ] ; do export DIRTY="0" echo "restarting ... " | logger -p local1.info # # anaconda wants bc for i in `rpm -qa --qf '%{name}\n' | grep -v joe | grep -v ssh | \ grep -v rsync | grep -v dhclient | grep -v mouse | \ grep -v sudo | grep -v gpg-pubkey | grep -v lftp | \ grep -v sel | grep -v policy | grep -v nscd | \ grep -v kernel | grep -v dos | grep -v ^bc | \ grep -v grub | grep -v yum |grep -v vim |grep -v iptable`; do [ "x$VERBOSE" = "x-v" ] && echo "testing $i" 1>&2 echo "testing $i" | logger -p local1.info [ "x$i" != "x" ] && rpm -e $i 2> /dev/null && { [ "x$VERBOSE" = "x-v" ] && echo " removed $i" 1>&2 echo " removed $i" | logger -p local1.info export DIRTY="1" } done done [ "x$VERBOSE" = "x-v" ] && echo "done ..." 1>&2 echo "done ... " | logger -p local1.info
Here is what the initial console CLI looks like:
Use the config login to enter the initial setup mode. This invokes the /bin/config-startup binary which displays a simple menu.
Here I configure the three UCM IPv4 management interface addresses (eth0, eth1, and eth2):
The first IPv4 address is for Fabric Interconnect A (primary by default), the second IPv4 address is for Fabric Interconnect B (subordinate by default) and the third IPv4 address is for the virtual UCM address as the default setup assumes UCSM is configured in high availability (HA) mode.
This is what you will see if you have Java Runtime Environment 1.6 or later installed (and correctly configured) and point your browser to 192.168.100.12.
This webpage is rendered by a Perl-based MVC (Model View Controller) web framework called Catalyst which uses APE (Ajax Push Engine). The “Launch KVM Manager” button works but a working KVM is crippled in the emulator. All the code for a working KVM is actually present (see kvm.zip) but is not used. The Java-based KVM technology appears to come from Avocent, which is now a division of Emerson Network Power.
This is what you will see initially when you click on the “Launch UCS Manager” button and successfully login to the downloaded Java applet:
Note that any combination of username and password seems to work – admin/admin, cisco/cisco, murphy/murphy – even though admin is the only predefined locally authenticated user.
UCSM is a Java application which is started from a web browser. A JNPL (Java Network Launching Protocol) configuration file (ucsm.jnpl) is first downloaded and executed. Here is the JNPL file for my UCSMPE.
<?xml version="1.0" encoding="UTF-8"?> <jnlp spec="1.0+" codebase="http://192.168.100.10/ucsm" > <information> <title>Cisco Systems UCS Manager (UCSPE-192-168-100-12)</title> <vendor>Cisco Systems, Inc.</vendor> <description>Cisco Systems UCS Manager</description> <homepage href="../index.html" /> <icon kind="default" href="Nuova.32.png" width="32" height="32"/> <icon kind="shortcut" href="Nuova.16.png" width="16" height="16"/> <icon kind="shortcut" href="Nuova.24.png" width="24" height="24"/> <icon kind="shortcut" href="Nuova.128.png" width="128" height="128"/> <icon kind="shortcut" href="Nuova.64.png" width="64" height="64"/> <icon kind="splash" href="splash-centrale.png"/> <shortcut> <menu submenu="Cisco Systems UCS Manager"/> </shortcut> </information> <security> <all-permissions/> </security> <update check="always" policy="always"/> <resources> <j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se" java-vm-args="-Dsun.java2d.d3d=false -XX:+HeapDumpOnOutOfMemoryError -XX:MaxPermSize=256m" initial-heap-size="128M" max-heap-size="768M"/> <!--<jar href="signed/@centrale-core@" main="true"/>--> <jar href="signed/centrale-min.jar" main="true"/> <jar href="signed/cres.jar" /> <!--<jar href="signed/@centrale-gen@" />--> <jar href="signed/foxtrot-core-3.0.jar"/> <jar href="signed/swingx-1.0.jar"/> <jar href="signed/swing-worker.jar"/> <jar href="signed/TimingFramework-1.0.jar"/> <jar href="signed/OfficeLnFs_2.7.jar"/> <jar href="signed/prefuse.2007.10.21.jar"/> <jar href="signed/log4j-1.2.15.jar"/> <jar href="signed/Stub.jar"/> <jar href="signed/jgraph.jar"/> <jar href="signed/jna.jar"/> <jar href="signed/examples.jar"/> <jar href="signed/jfreechart-1.0.9.jar"/> <jar href="signed/jcommon-1.0.12.jar"/> <jar href="signed/miglayout-3.6-swing.jar"/> <jar href="signed/jxlayer.jar"/> <jar href="signed/JBusyComponent.jar"/> <jar href="signed/jautocomp.jar"/> <jar href="signed/lablib-checkboxtree-3.2.jar"/> <property name="jnlp.packEnabled" value="true"/> <property name="jnlp.ucsm.server.ip" value="192.168.100.10"/> <property name="jnlp.ucsm.server.port" value="80"/> <property name="jnlp.ucsm.server.port.secure" value="80"/> <property name="jnlp.ucsm.log4j.configuration" value="http://192.168.100.10/ucsm/log4j.xml"/> <property name="jnlp.ucsm.secure.mode" value="false"/> <property name="jnlp.ucsm.sun.awt.exception.handler" value="com.nuova.centrale.core.log4j.NuUnhandledExceptionHandler"/> <property name="jnlp.ucsm.centrale.security.enforced" value="true"/> <property name="jnlp.ucsm.centrale.login.enforced" value="true"/> <!-- property name="jnlp.ucsm.skip.version.check" value="true"/ --> <property name="jnlp.ucsm.use.login" value="true"/> <property name="jnlp.ucsm.centrale.systemName" value="UCSPE-192-168-100-12"/> <property name="jnlp.ucsm.centrale.systemFabric" value=""/> <property name="jnlp.ucsm.centrale.systemID" value="35073892-5923-11e4-b901-000c29974df8"/> <property name="jnlp.ucsm.centrale.oobIpAddr" value="192.168.100.10"/> <property name="jnlp.ucsm.centrale.domains" value=""/> <property name="jnlp.ucsm.centrale.clibanner" value=""/> <!-- property name="jnlp.ucsm.edge.black" value="false"/ --> <!-- property name="jnlp.ucsm.edge.thick" value="false"/ --> <property name="jnlp.ucsm.centrale.mainframe" value="app:centrale.3"/> <property name="jnlp.ucsm.token" value=""/> <property name="jnlp.ucsm.multi.token" value=""/> <property name="jnlp.ucsm.initial.naf" value=""/> <property name="jnlp.ucsm.fault.severity" value=""/> <property name="jnlp.ucsm.fault.type" value=""/> <!-- property name="jnlp.ucsm.skip.splash.screen" value="false"/ --> <!-- property name="jnlp.ucsm.native.splash" value="false"/ --> <!-- Required for w32 window transparency --> <!-- property name="jnlp.ucsm.sun.java2d.noddraw" value="true"/ --> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> </resources> <resources os="Mac OS X"> <jar href="signed/osx.jar"/> <jar href="signed/osx2.jar"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> <property name="log.show.encrypted" value="true"/> </resources> <application-desc main-class="com.nuova.centrale.core.NuApp" /> </jnlp>
Technically ucsm.jnlp is generated on the fly by ucsm.cgi from a template named applet.template based on configuration options from ../opt/db/sam.config using a Perl CGI script.
The JNLP protocol, defined with an XML schema, specifies how to launch Java Web Start applications. JNLP consists of a set of rules defining how exactly to implement the launching mechanism. JNLP files include information such as the location of the jar (Java Archive) package file(s) and the name of the main class for the application, in addition to any other parameters. A properly configured browser passes JNLP files to a Java Runtime Environment (JRE) which in turn downloads the application onto the user’s platform and executes it.
By the way, you can launch UCSM and KVM from the command line should you choose to do so. For example, to launch UCSM:
c:\Program Files\Java\jre7\bin>javaws -silent c:\ucs\ucsm.jnlp
assuming a local copy of ucsm.jnlp is in c:\ucs.
You can access the UCSMPE database browser by pointing your browser at <management ip>/visore.html:
Visore is a utility built into UCSMPE that allows a user to easily browse Managed Objects (MOs) using an HTML browser. Nothing can be changed from Visore; it’s usefulness lies in configuration verification.
To really explore the internals of UCSMPE, we need root access to the underlying OS. There are many techniques to do this. The particular technique I used was to boot the UCSMPE VM using Partition Magic, mount /dev/sda1 and modify the GRUB configuration file to add another stanza which, when selected, boots into single-user mode as show here:
Here is what the new GRUB menu looks like when invoked:
When the new menu option is selected, we end use as root in a bash shell:
Here is contents of /etc/passwd:
# cat /etc/passwd root:x:0:0:root:/root:/bin/apechallenge bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin news:x:9:13:news:/etc/news: uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin haldaemon:x:68:68:HAL daemon:/:/sbin/nologin apeuser:x:500:100::/home/apeuser:/bin/bash cliuser:x:504:501::/home/cliuser:/apedisk/ape/install/os/clishell.sh #stamp:x:502:502::/home/stamp:/apedisk/ape/install/os/stampshell.sh config:x:503:503::/home/config:/bin/config-startup ntp:x:38:38::/etc/ntp:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
Note what is invoked when a user successfully logs in as root. Not what you would normally expect to see.
From here, you can use the passwd command to change the password for apeuser and root. To speed up UCSPE startup, you can also turn off the nfs, nfslock and ntpd services using the chkconfig utility. I also usually add an extra user account called toor with a UID an GID of 0 and modify /etc/ssh/sshd_config to permit root and toor access via ssh. Also I suggest you delete the useless root crontab entry relating to ntp which is invoked every minute.
When you have made the above changes, reboot UCSPE and you will have easy access to UCSPE internals from the console or via ssh.
You will see various references to Nuovo when exploring UCSPE internals. In August 2006, Cisco paid $50 million to acquire an 80% stake in Nuova Systems, a Cisco “spin-in”, which was founded by a number of former Cisco senior employees including former senior vice president and chief development officer Mario Mazzola, and Ed Bugnion, a co-founder of VMware. In late 2008, Cisco purchased the remaining 20%. The Nexus 5000 series switch, for example, was a collaborative development between Cisco and Nuova Systems.
LVM is used to provide the /ape filesystem. This is where the majority of interesting stuff lives.
# df Filesystem 1K-blocks Used Available Use% Mounted on /dev/hda2 901252 589720 265740 69% / /dev/hda1 124427 9125 108878 8% /boot none 1037948 0 1037948 0% /dev/shm /dev/hdd1 1027768 361308 614252 38% /home /dev/ram0 247919 84011 163908 34% /mnt /dev/mapper/ape 10320108 3014080 6781796 31% /ape
It looks like /ape is configured from files in /home/apeuser.
# ls -l /home/apeuser total 343544 -rw-r--r-- 1 apeuser users 331319924 Sep 15 17:24 apedisk.tar.gz lrwxrwxrwx 1 apeuser users 16 Feb 15 2012 opt -> /apedisk/ape/opt -rw-r--r-- 1 root root 20109611 Sep 15 17:24 perl.tar.gz -rw-r--r-- 1 root root 1594 Sep 15 17:24 run_once_inside_vm_distro.sh lrwxrwxrwx 1 apeuser users 20 Feb 15 2012 tmp -> /apedisk/ape/var/tmp # cat /home/apeuser/run_once_inside_vm_distro.sh #!/bin/sh # as in the name: download this script along with apedisk.tar.gz into /home/apeuser inside the VM # run it once as root. After this, VM is ready to ship, so shut it down with 'shutdown -h now' # and once vmplayer exits, run vmzip.sh against the VM directory. umount /mnt mkfs.ext2 -m 0 /dev/ram0 mount /dev/ram0 /mnt cd /mnt chown apeuser.users /home/apeuser/apedisk.tar.gz tar xzvf /home/apeuser/apedisk.tar.gz \ ape/install/os/init.d/cisco_ucspe \ ape/install/os/init.d/init_ip \ ape/install/apevmsec \ ape/install/config-startup \ ape/install/os/config-sudo cp -f ape/install/os/init.d/cisco_ucspe /etc/init.d chmod 744 /etc/init.d/cisco_ucspe cp -f ape/install/apevmsec /etc/init.d chmod 744 /etc/init.d/apevmsec cp -f ape/install/os/init.d/init_ip /etc/init.d chmod 744 /etc/init.d/init_ip mv -f ape/install/config-startup /bin chown root.root /bin/config-startup chmod 755 /bin/config-startup mv -f ape/install/os/config-sudo /bin chown root.root /bin/config-sudo chmod 700 /bin/config-sudo cd / umount /mnt # /opt is not used, but if exists, it causes a "disk usage exceeded 70%" fault in UCSM rmdir /opt cd /etc/rc3.d/ ln -sf ../init.d/cisco_ucspe S96cisco_ucspe cd ../rc0.d/ ln -sf ../init.d/cisco_ucspe K05cisco_ucspe cd ../rc6.d/ ln -sf ../init.d/cisco_ucspe K05cisco_ucspe # deny ssh to anyone but root echo "AllowUsers root cliuser" >> /etc/ssh/sshd_config # doesn't work yet #cd /etc/rc3.d/ #ln -sf ../init.d/init_ip S07init_ip echo "Cisco UCS Platform Emulator 2.2(3aPE1)(391886)" > /etc/redhat-release
Spot the obvious error in the above script?
The last command reveals that this particular version of UCSPE was probably constructed in August 2010.
reboot system boot 2.6.9-89.0.23.EL Thu Nov 25 09:54 (00:05) root pts/0 nmtg-hq-salt1-37 Thu Nov 25 08:57 - down (00:01) root pts/0 nmtg-hq-salt1-37 Thu Nov 25 08:57 - 08:57 (00:00) reboot system boot 2.6.9-89.0.23.EL Thu Nov 25 08:55 (00:03) root pts/0 nmtg-hq-salt1-37 Thu Nov 25 07:58 - down (00:01) reboot system boot 2.6.9-89.0.23.EL Thu Nov 25 07:57 (00:02) root pts/0 nmtg-hq-salt1-37 Thu Nov 25 07:40 - down (00:16) reboot system boot 2.6.9-89.0.23.EL Thu Nov 25 07:39 (00:17) root pts/0 nmtg-hq-salt1-37 Wed Nov 24 15:10 - down (16:07) reboot system boot 2.6.9-89.0.23.EL Wed Nov 24 15:09 (16:08) root pts/1 nmtg-hq-salt1-37 Wed Nov 24 14:40 - down (00:27) config tty1 Wed Nov 24 14:38 - 14:38 (00:00) root pts/0 nmtg-hq-salt1-37 Wed Nov 24 14:00 - 15:07 (01:07) reboot system boot 2.6.9-89.0.23.EL Wed Nov 24 13:58 (01:09) root pts/0 savbu-mgmt09.cis Sat Nov 13 22:01 - down (00:02) reboot system boot 2.6.9-89.0.23.EL Sat Nov 13 22:00 (00:02) root pts/0 savbu-mgmt09.cis Wed Nov 10 00:29 - down (00:00) root pts/0 savbu-mgmt09.cis Wed Nov 10 00:28 - 00:29 (00:00) reboot system boot 2.6.9-89.0.23.EL Wed Nov 10 00:27 (00:02) root pts/0 savbu-mgmt09.cis Mon Nov 8 23:06 - down (00:02) reboot system boot 2.6.9-89.0.23.EL Mon Nov 8 23:06 (00:02) root pts/0 savbu-mgmt09.cis Mon Nov 8 05:32 - down (00:01) root pts/0 savbu-mgmt09.cis Mon Nov 8 05:22 - 05:28 (00:06) reboot system boot 2.6.9-89.0.23.EL Mon Nov 8 05:22 (00:11) root pts/0 savbu-mgmt09.cis Tue Oct 19 22:03 - down (00:03) reboot system boot 2.6.9-89.0.23.EL Tue Oct 19 22:00 (00:06) root pts/0 savbu-mgmt09.cis Sat Aug 7 01:33 - down (00:05) reboot system boot 2.6.9-89.0.23.EL Sat Aug 7 01:33 (00:05) wtmp begins Fri Aug 6 22:51:56 2010
However the date of /root/install.log appears to indicate August 2007 as the initial installation date.
The document root for the webpages served by UCSPE is /ape/ape/opt/apache/htdocs
# cd /ape/ape/opt/apache/htdocs # ls -l total 14308 -rwxr-xr-x 1 apeuser users 3946 Sep 15 14:39 ape.cgi drwxr-xr-x 6 apeuser users 4096 Sep 15 14:39 bootstrap -rw-r--r-- 1 apeuser users 94 Sep 15 14:26 crossdomain.xml drwxr-xr-x 2 apeuser users 4096 Sep 15 14:26 css drwxr-xr-x 6 apeuser users 524288 Sep 15 14:39 docs -rw-r--r-- 1 apeuser users 3638 Sep 15 14:26 favicon.ico drwxr-xr-x 3 apeuser users 4096 Sep 15 14:39 help drwxr-xr-x 4 apeuser users 4096 Nov 23 19:23 images -rw-rw-rw- 1 apeuser users 10160 Nov 23 19:02 index.html drwxr-xr-x 2 apeuser users 4096 Nov 23 20:06 js -rw-r--r-- 1 apeuser users 10902 Sep 15 14:26 kvm.html -rw-r--r-- 1 apeuser users 11067186 Sep 15 14:26 kvm.zip drwxr-xr-x 6 apeuser users 4096 Sep 15 14:40 pictures -rw-r--r-- 1 apeuser users 268820 Sep 15 14:42 sample_sel.txt lrwxrwxrwx 1 apeuser users 42 Nov 23 11:09 static -> /apedisk/ape/webconfig/ape/Ape/root/static drwxr-xr-x 2 apeuser users 4096 Sep 15 14:40 templates drwxr-xr-x 2 apeuser users 4096 Sep 15 14:40 tools drwxr-xr-x 7 apeuser users 4096 Nov 23 20:02 ucsm drwxr-xr-x 5 apeuser users 4096 Sep 15 14:40 visore -rwxr-xr-x 1 apeuser users 3798 Sep 15 14:40 visore.html -rw-r--r-- 1 apeuser users 2677560 Sep 15 14:39 xml_Schema_and_Samples.zip # cd ucsm # ls -al total 1088 drwxr-xr-x 7 apeuser users 4096 Nov 23 20:02 . drwxr-xr-x 13 apeuser users 4096 Nov 23 19:29 .. -rw-r--r-- 1 apeuser users 3579 Sep 15 14:40 applet.template -rw-r--r-- 1 apeuser users 4804 Sep 15 14:39 avocent.jnlp.tmpl -rw-r--r-- 1 apeuser users 3872 Sep 15 14:39 centrale-applet.jnlp.tmpl -rw-r--r-- 1 apeuser users 5691 Nov 23 19:02 centrale.jnlp.tmpl -rw-r--r-- 1 apeuser users 884462 Sep 15 14:39 centralina.swf drwxr-xr-x 2 apeuser users 4096 Sep 15 14:39 chassis -rwxr-xr-x 1 apeuser users 635 Sep 15 14:40 domains.cgi -rwxr-xr-x 1 apeuser users 4400 Sep 15 14:40 getkvmurl.cgi drwxr-xr-x 3 apeuser users 4096 Sep 15 14:39 help -rw-r--r-- 1 apeuser users 208 Sep 15 14:39 .htaccess -rwxr-xr-x 1 apeuser users 30 Nov 23 19:02 isSamInstalled.cgi -rwxr-xr-x 1 apeuser users 3669 Sep 15 14:40 javahelp.jnlp -rw-r--r-- 1 apeuser users 5132 Sep 15 14:39 kvm.html -rwxr-xr-x 1 apeuser users 3668 Sep 15 14:40 kvm.jnlp -rw-r--r-- 1 apeuser users 529 Sep 15 14:40 kvm_vm_help.html -rw-r--r-- 1 apeuser users 2229 Sep 15 14:40 log4j-applet.xml -rw-r--r-- 1 apeuser users 2381 Sep 15 14:40 log4j.kvm.xml -rw-r--r-- 1 apeuser users 2386 Sep 15 14:39 log4j.xml -rw-r--r-- 1 apeuser users 5957 Sep 15 14:40 Nuova.128.png -rw-r--r-- 1 apeuser users 562 Sep 15 14:39 Nuova.16.png -rw-r--r-- 1 apeuser users 834 Sep 15 14:39 Nuova.24.png -rw-r--r-- 1 apeuser users 1205 Sep 15 14:39 Nuova.32.png -rw-r--r-- 1 apeuser users 2006 Sep 15 14:40 Nuova.64.png -rw-r--r-- 1 apeuser users 657 Sep 15 14:39 playerProductInstall.swf drwxr-xr-x 2 apeuser users 4096 Sep 15 14:39 signed -rw-r--r-- 1 apeuser users 50910 Sep 15 14:40 splash-centrale.png -rw-r--r-- 1 apeuser users 23467 Sep 15 14:39 swfobject.js drwxr-xr-x 2 apeuser users 4096 Sep 15 14:40 tools drwxr-xr-x 3 apeuser users 4096 Sep 15 14:40 ucsm -rwxr-xr-x 1 apeuser users 2455 Sep 15 14:40 ucsm.cgi -rwxr-xr-x 1 apeuser users 3690 Nov 23 19:03 ucsm.jnlp
Note that the UCS KVM facility is also launched using a .jnlp configuration file. Also note the two Adobe Shockwave/Flash files. To fully use UCSPE, Adobe Shockwave or Flash must be enabled. The signed directory contains the jar files used by JRE to execute the UCSM application.
Apache uses three modules, i.e. mod_nuova, mod_proxy_http and mod_proxy.
You should read the ape.install, ape.run and ape.shutdown shell scripts to fully understand how UCSMPE is started and stopped.
The configuration menu that is displayed when you login as config invokes the ../os/config-sudo script. Have a read of this file. It contains lots of useful information.
Hardware configuration information is kept in /etc/ape/ape.db which is an SQLite database.
sqlite3 ape.db SQLite version 3.3.6 Enter ".help" for instructions sqlite> .schema CREATE TABLE chassis_config ( id INTEGER PRIMARY KEY AUTOINCREMENT, external_id INTEGER, -- a chassis id assigned by UCSM name TEXT, type TEXT, -- running vs startup is_removed INTEGER DEFAULT(0), pid TEXT, -- refers to CapProvider:pid sam_default_config.xml serial TEXT, switch_id TEXT, sw_slot_id INTEGER, sw_port_id INTEGER, mux_slot_id INTEGER, mux_port_id INTEGER, power INTEGER DEFAULT(0), -- (1) on (0) off locator_led INTEGER DEFAULT(0) -- (1) on (0) off ); CREATE TABLE chassis_fan ( id INTEGER PRIMARY KEY AUTOINCREMENT, chassis_config_id INTEGER REFERENCES chassis_config(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE chassis_iom_fi( id INTEGER PRIMARY KEY AUTOINCREMENT, chassis_id INTEGER DEFAULT(0) REFERENCES chassis_config(id) ON DELETE CASCADE ON UPDATE CASCADE, iom_id INTEGER DEFAULT(1), port INTEGER DEFAULT(0), chassis_external_id INTEGER DEFAULT(0), link_id INTEGER DEFAULT(0), iom_port INTEGER DEFAULT(0)); CREATE TABLE chassis_psu ( id INTEGER PRIMARY KEY AUTOINCREMENT, chassis_config_id INTEGER REFERENCES chassis_config(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT, -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) power INTEGER DEFAULT(0) -- (1) on (0) off (whether PSU power cord is connected) ); CREATE TABLE chassis_server ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, chassis_config_id INTEGER REFERENCES chassis_config(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, is_removed INTEGER DEFAULT(0), prev_chassis_id INTEGER, -- used only in trash can pid TEXT, -- refers to CapProvider:pid sam_default_config.xml serial TEXT, vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT, -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) locator_led INTEGER DEFAULT(0), -- (1) on (0) off power INTEGER DEFAULT(0) -- (1) on (0) off (whether PSU power cord is connected) ); CREATE TABLE fex_cluster(id INTEGER PRIMARY KEY AUTOINCREMENT,switch_A INTEGER DEFAULT(0) REFERENCES fex_config(id) ON DELETE CASCADE ON UPDATE CASCADE ,switch_B INTEGER DEFAULT(0) REFERENCES fex_config(id) ON DELETE CASCADE ON UPDATE CASCADE); CREATE TABLE fex_config ( id INTEGER PRIMARY KEY AUTOINCREMENT, external_id INTEGER, -- a chassis id assigned by UCSM name TEXT, type TEXT, -- running vs startup is_removed INTEGER DEFAULT(0), pid TEXT, -- refers to CapProvider:pid sam_default_config.xml serial TEXT, switch_id TEXT, sw_slot_id INTEGER, sw_port_id INTEGER, mux_slot_id INTEGER, mux_port_id INTEGER, power INTEGER DEFAULT(0), -- (1) on (0) off locator_led INTEGER DEFAULT(0), -- (1) on (0) off switch_side TEXT DEFAULT('A') ); CREATE TABLE fex_fan ( id INTEGER PRIMARY KEY AUTOINCREMENT, fex_config_id INTEGER REFERENCES fex_config(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE fex_iom_fi( id INTEGER PRIMARY KEY AUTOINCREMENT, fex_id INTEGER DEFAULT(0) REFERENCES fex_config(id) ON DELETE CASCADE ON UPDATE CASCADE, port INTEGER DEFAULT(0), fex_external_id INTEGER DEFAULT(0), link_id INTEGER DEFAULT(0), iom_port INTEGER DEFAULT(0), iom_side TEXT DEFAULT('A')); CREATE TABLE fex_psu ( id INTEGER PRIMARY KEY AUTOINCREMENT, fex_config_id INTEGER REFERENCES fex_config(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT, -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) power INTEGER DEFAULT(0) -- (1) on (0) off (whether PSU power cord is connected) ); CREATE TABLE fex_state(id INTEGER PRIMARY KEY AUTOINCREMENT,fex_id INTEGER DEFAULT(0) REFERENCES fex_config(id) ON DELETE CASCADE ON UPDATE CASCADE, fex_id_B INTEGER DEFAULT(0), state INTEGER DEFAULT(0)); CREATE TABLE rack_adapter ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES rack_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE rack_adapter_allowed (id INTEGER PRIMARY KEY AUTOINCREMENT,pid_server TEXT,pid_adapter TEXT); CREATE TABLE rack_cpu ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES rack_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE rack_cpu_allowed (id INTEGER PRIMARY KEY AUTOINCREMENT,pid_server TEXT,pid_cpu TEXT); CREATE TABLE rack_details( pid TEXT PRIMARY KEY, sockets INTEGER, rackunits INTEGER, dimms INTEGER, hdds INTEGER, cpus INTEGER, pcies INTEGER, psus INTEGER, storage_controllers INTEGER); CREATE TABLE rack_dimm ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES rack_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE rack_dimm_allowed (id INTEGER PRIMARY KEY AUTOINCREMENT,pid_server TEXT,pid_dimm TEXT); CREATE TABLE rack_fex( id INTEGER PRIMARY KEY AUTOINCREMENT, fex_id INTEGER DEFAULT(0) REFERENCES fex_config(id) ON DELETE CASCADE ON UPDATE CASCADE , fex_id_B INTEGER , adapter_id INTEGER DEFAULT(0) REFERENCES rack_adapter(id) ON DELETE CASCADE ON UPDATE CASCADE, fex_port INTEGER DEFAULT(0), fex_port_B INTEGER DEFAULT(0), swm_config INTEGER DEFAULT(0)); CREATE TABLE rack_fi( id INTEGER PRIMARY KEY AUTOINCREMENT, adapter_id INTEGER DEFAULT(0) REFERENCES rack_adapter(id) ON DELETE CASCADE ON UPDATE CASCADE, fi_port INTEGER DEFAULT(0), rack_id INTEGER DEFAULT(0) REFERENCES rack_server(id) ON DELETE CASCADE ON UPDATE CASCADE, side TEXT DEFAULT('A'), swm_config INTEGER DEFAULT(0)); CREATE TABLE rack_hdd ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES rack_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE rack_hdd_allowed (id INTEGER PRIMARY KEY AUTOINCREMENT,pid_server TEXT,pid_hdd TEXT); CREATE TABLE rack_psu ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES rack_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT, -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) power INTEGER DEFAULT(0) -- (1) on (0) off (whether PSU power cord is connected) ); CREATE TABLE rack_psu_allowed( id INTEGER PRIMARY KEY AUTOINCREMENT, pid_server TEXT, pid_psu TEXT ); CREATE TABLE rack_server(id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,fex_id INTEGER DEFAULT(0), fex_id_B INTEGER DEFAULT(0), slot_id INTEGER, pid TEXT, serial TEXT,vendor TEXT,model TEXT,locator_led INTEGER DEFAULT(0),power INTEGER DEFAULT(0), type TEXT, is_removed INTEGER DEFAULT(0), lom_fex_port_1 INTEGER DEFAULT(0), lom_fex_port_2 INTEGER DEFAULT(0)); CREATE TABLE rack_storage ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES rack_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE scaled_details( id INTEGER PRIMARY KEY AUTOINCREMENT, master_id INTEGER DEFAULT(0) REFERENCES chassis_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slave_id INTEGER DEFAULT(0) REFERENCES chassis_server(id) ON DELETE CASCADE ON UPDATE CASCADE); CREATE TABLE server_adapter ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES chassis_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE server_cpu ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES chassis_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE server_dimm ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES chassis_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE server_hdd ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES chassis_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE server_storage ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER REFERENCES chassis_server(id) ON DELETE CASCADE ON UPDATE CASCADE, slot_id INTEGER, pid TEXT, -- refers to CapProvider:pid sam_default_config.xml vendor TEXT, -- vendor and model should come from catalogue based on PID, but if during discovery model TEXT -- we get an unknown PID, we store vendor/model explicitly (i.e. if these fields are NULL, use pid) ); CREATE TABLE settings ( id INTEGER PRIMARY KEY, ha INTEGER, swm INTEGER, das INTEGER, persistence INTEGER, switchType INTEGER, startup_cfg_url TEXT -- URL of a remote config server; APE will load its config from this url, can be provided by another APE VM ,iom TEXT , use_dhcp INTEGER DEFAULT(1), ip_addr TEXT, netmask TEXT, gateway TEXT, num_uplinks INTEGER DEFAULT(1), ntp_use_default INTEGER DEFAULT(1), ntp_ip_addr TEXT,version TEXT); CREATE TABLE smartplay_details(id PRIMARY KEY, ha INTEGER, type TEXT, fi TEXT, filename TEXT, swm INTEGER); CREATE TABLE stamp ( id INTEGER PRIMARY KEY, cisco_user VARCHAR(20), name TEXT, company TEXT, email TEXT ); CREATE TABLE template_details(id PRIMARY KEY, pid INTEGER, description TEXT, name TEXT, type TEXT, filename TEXT); sqlite>
FI DMEs (Database Management Engine) are also implemented as SQLite databases. For example:
# cd /ape/ape/opt/db/ha/left/flash # ls -l total 9040 -rw-r--r-- 1 apeuser users 9240576 Nov 23 22:31 dme.db # sqlite3 dme.db SQLite version 3.3.6 Enter ".help" for instructions sqlite> .schema CREATE TABLE MODB (KEY INTEGER PRIMARY KEY, MOXML BLOB); sqlite> SELECT * FROM modb LIMIT 8 ; 10002| <aaaLog dn="aaa-log" maxSize="10000" purgeWindow="100" size="450" status="modified"/> 10003| <apeManager dn="ape" statsUpdateId="1" status="created"/> 10004| <callhomeEp adminState="off" alertThrottlingAdminState="on" configState="ok" descr="" dn="call-home" fsmDescr="" fsmPrev="configCallhomeSuccess" fsmProgr="100" fsmRmtInvErrCode="none" fsmRmtInvErrDescr="" fsmRmtInvRslt="" fsmStageDescr="" fsmStamp="1416769439.126" fsmStatus="nop" fsmTry="0" intId="10004" name="" policyLevel="0" policyOwner="local" status="modified"/> 10005| <callhomeAnonymousReporting adminState="off" count="0" dn="call-home/anonymousreporting" sleepInterval="0" status="modified" userAcknowledged="yes"/> 10006| <callhomePeriodicSystemInventory adminState="off" dn="call-home/periodicsysteminventory" intervalDays="30" lastDeadline="0.000" maximumRetryCount="1" minimumSendNowIntervalSeconds="5" nextDeadline="never" pollIntervalSeconds="300" retryCount="0" retryDelayMinutes="10" sendNow="no" status="created" timeOfDayHour="0" timeOfDayMinute="0" timeOfLastAttempt="0.000" timeOfLastSuccess="never"/> 10007| <callhomeProfile alertGroups="all,ciscoTac,diagnostic,environmental" descr="Built-in full text profile" dn="call-home/profile-full_txt" format="fullTxt" level="warning" maxSize="5000000" name="full_txt" status="created"/> 10008| <callhomeProfile alertGroups="all,ciscoTac,diagnostic,environmental" descr="Built-in text profile" dn="call-home/profile-short_txt" format="shortTxt" level="warning" maxSize="5000000" name="short_txt" status="created"/> 10009| <callhomeProfile alertGroups="ciscoTac" descr="Built-in XML Cisco-TAC profile" dn="call-home/profile-CiscoTAC-1" format="xml" level="normal" maxSize="5000000" name="CiscoTAC-1" status="created"/> sqlite>
Well, this post is getting too long and it is time to stop. By now, you should have sufficient information to explore the internals of the UCS Manager emulator by yourself.
Happy hunting!