Out-of-Band Management

IPMI

…For Fun and Profit!

Users
# Let's look at what we currently have before adding anything
$ ipmitool user list
ID Name              Callin Link Auth   IPMI Msg   Channel Priv Limit
1                    true   false       false      Unknown (0x00)
2 ADMIN              true   false       false      Unknown (0x00)
...

$ ipmitool user set name 3 devopsuser
$ ipmitool user list
ID  Name	     Callin  Link Auth	IPMI Msg   Channel Priv Limit
1                    true    false      false      Unknown (0x00)
2   ADMIN            true    false      false      Unknown (0x00)
3   devopsuser       true    false      false      Unknown (0x00)
...

$ ipmitool user set password 3
Password for user 3: 
Password for user 3: 
Set User Password command successful (user 3)
$ ipmitool channel setaccess 1 3 link=on ipmi=on callin=on privilege=4
Set User Access (channel 1 id 2) successful.
$ ipmitool user enable 3
 

Serial

In my lab, I began adopting serial as an alternative to IPMI and standard Layer3 management interfaces.  Serial comes with its own set of problems.  Mostly, redirecting to serial.  There are several things to be cognizant of.

  1. The stage(s) of a system’s boot procedure that are responsible for output redirection
  2. The inputs and outputs of a system
  3. The behavior of a system when more than one redirection is possible

References

Thomas-Krenn.com

Algorithms and Data Structures

dynamic programming

The method of solving problems exhibiting the properties or overlapping subproblems.[1]  Real-world applications that have been solved using dynamic programming: the magnet selection tool in Photoshop uses dynamic programming.[2]

exponentiation by squaring

Also called left-to-right binary exponentiation or square-and-multiply[3].

  1. Right the exponent in binary.  Example 225.  The exponent is 25.  In binary it is 11001
  2. Remove the first binary digit leaving 1001 and then replace each remaining 1 with the pair of letters “sx” and each 0 with the letter “s” to get: sx s s sx (remember, using 1001)
  3. “s” means square, “x” means multiply.  So, we have square mutiply by x, square, square, square, multiply by x where “x” is the base

In general, binary exponentiation (or square-and-multiply as learned in class) will take less than 2log(n)/log(2) multiplications.

There is also a right-to-left binary exponentiation. It is easier to program but takes more storage.[3]

Primality Testing

Fermat, Pierre de

Fermat’s Little Theorem (non-deterministic)if p is prime, then 2p divides 2p-2.

Other Algorithms

Sieve of Eratosthenes (deterministic)

Better to use when you are dealing with a certain range of numbers.

Incrementally testing up to sqrt(n) (deterministic)

Fermat primality test and Miller-Rabin primality test (non-deterministic)

Miller-Rabin has a deterministic variant but you have to balance time complexity and accuracy.

Hashing

A mapping of keys to values in an efficient manner.  Data structure is referred to as a hash-map, hash-table, or dictionary.  Choosing the proper hash function depends on the scenario.

search algorithms

Binary Search: Efficient search on sorted data with time complexity of O(log2N). Continue to divide the portion of the list that could have it in half until it is narrowed down to one possible item.

Depth/Breadth First Search: tree/graph traversing and searching.

Sorting Algorithms

SO Reference

Noteworthy:

Merge sort: When you need a stable, O(N log N) sort, this is about your only option. The only downsides to it are that it uses O(N) auxiliary space and has a slightly larger constant than a quick sort. There are some in-place merge sorts, but AFAIK they are all either not stable or worse than O(N log N). Even the O(N log N) in place sorts have so much larger a constant than the plain old merge sort that they’re more theoretical curiosities than useful algorithms.

Quick sort: When you don’t need a stable sort and average case performance matters more than worst case performance. A quick sort is O(N log N) on average, O(N^2) in the worst case. A good implementation uses O(log N) auxiliary storage in the form of stack space for recursion.

Bucket sort: When you can guarantee that your input is approximately uniformly distributed.

Heap sort: When you don’t need a stable sort and you care more about worst case performance than average case performance. It’s guaranteed to be O(N log N), and uses O(1) auxiliary space, meaning that you won’t unexpectedly run out of heap or stack space on very large inputs.

Counting sort: When you are sorting integers with a limited range.

Others:

Bubble sort, selection sort: When you’re doing something quick and dirty and for some reason you can’t just use the standard library’s sorting algorithm. The only advantage these have over insertion sort is being slightly easier to implement.

Bogosort: In computer science, bogosort (also known as permutation sort, stupid sort, slowsort, shotgun sort, or monkey sort) is a highly inefficient sorting algorithm based on the generate and test paradigm. The function successively generates permutations of its input until it finds one that is sorted. It is not useful for sorting, but may be used for educational purposes, to contrast it with more efficient algorithms.


[1] https://en.wikiversity.org/wiki/Dynamic_programming
[2] https://www.quora.com/What-are-some-real-world-problems-that-have-been-solved-with-dynamic-programming
[3] https://primes.utm.edu/glossary/page.php?sort=BinaryExponentiation

 

Java

I’ve only ever heard bad things about Java so I have steered clear of it. But, I will tell you one thing, Java’s BigInteger is nice and easy and very powerful for calculations with very large numbers.

Now that I’m spending more time with Java, I wanted to jot down a few things that I’ve learned along the way.

What I like About Java

It’s an Object-Oriented Programming

While I can handle and adapt to a flat structure consisting primarily of variables passed around and functions that have to be created to extend functionality and called to process a selection of data, being object-oriented seems to keep things more modular, cleaner, and extensible.  If given an opportunity to interact with OOP I won’t shy away from it.

Low Effort Requirement to Get a Program Up and Running

If I need to whip something up, I’ll use either Python, Bash, or Java.  If I want to perform simple admin tasks, Bash works just fine.  If I need to perform somewhat more complex HTTP/S requests, Python works well.  If I need more complex structures and decent performance, Java can let you put things together rather quickly.

Command Line Arguments

Still parsing this information myself.  Looks like I ought to try JCommander

Importing Packages

You may run into this when you’re working on a Java project:

SmallProjectThree.java:8: error: package org.bouncycastle.math.ec does not exist

This means your environment is not familiar with a package called bouncycastle.math.ec.  The reason this error is thrown is because I am attempting to do some Elliptic-curve calculations and am using a snippet from im-infamou5 on GitHub.com

In general, to use a non-standard library, you need to find the *.jar file yourself, download it, and drop it in your CLASSPATH (if this doesn’t exist or you want to redefine it, you can do so; see -cp below)

Specific to Bouncy Castle, these are the steps I took.

  1. Download the .jar file from the org’s download page directly.  Now, there are a ton of options available to you on that page.
    1. Trust but verify.  I recommend using signed jar files so you can digitally trust the source.  Once the package has been downloaded check the sha hash.
    2. What JDK is installed on your system?  Your system probably has Java installed (java -version) but the JDK is separate.  Only one Java can exist but several JDKs can exist (in a given environment at a time).  I am currently running Java build 13.0.2+8 and have 13.0.3 and 1.8.0_241 JDK present on my system.  I am downloading JDK 14 and dropping it into the same directory.
      1. $ java -version
        java version "13.0.2" 2020-01-14
        Java(TM) SE Runtime Environment (build 13.0.2+8)
        Java HotSpot(TM) 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing)
      2. $ pwd
        /System/Volumes/Data/Library/Java/JavaVirtualMachines
        $ ls
        jdk-13.0.2.jdk jdk-14.jdk jdk1.8.0_241.jdk
    3. Which .jar file do you need?  I looked through the documentation and found that the “provider” had the math.ec library so I need the “provider” .jar
  2. Add the *.jar file to my project’s directory tree.
    1. Download it to the same directory that contains my SmallProject3.java program.
  3. Compile my program using -cp or --classpath
  4. $ javac -cp ./org/bouncycastle/bcprov-jdk14-164.jar SmallProjectThree.java

     

MAKEFILE

An expert in neither Java nor Make dropped this off.

JAVAC=javac
JAVA=java
sources = $(wildcard *.java)
classes = $(sources:.java=.class)

all : $(classes)

run : all
    $(JAVA) PrimitiveRoots

clean :
    rm -f *.class

%.class : %.java
    $(JAVAC) $<

 

Groovy & Jenkins

 

Groovy Scripts

How to List Git Branches Dynamically in Jenkins Pipeline Job

I am growing weary of always having to update the list of branches in the choice parameter every time I wish to build a branch that isn’t listed.  I like using the Choice Parameter because it cuts down on a.) typo errors; and, b.) having to type something in each time like you’d have to if you used a String Parameter.  But, an even better option would be to query GitHub for a list of branches and populate the choices dynamically, further removing the user from being required to type anything…ever!

It appears as though I have two general options: 1.) use a plugin that speaks to GitHub directly, like the Git Parameter List plugin; or, 2.) use a groovy script that gives me full control over what is being queried and what is being displayed.

 

Resources

Jenkins is the hub of activity for my day-to-day.  As is Foreman, Proxmox, GitHub Enterprise, and good ol’ physical machines.  We’re not doing anything too complicated with Jenkins, aside from webhook triggers and Groovy libraries.

Here are some helpful resources, to start.

Jenkins Groovy Cheat Sheet

 

External USB Refuses to Mount on macOS

I was working on some cryptography homework and remembered that I wanted to plug my iPhone into my iMac to charge it up.  I have a USB dongle that gives me room for 4 more ports.  I have noticed that the dongle is rather pathetic and can’t handle much throughput or utilization.  It doesn’t have enough for all of my peripherals so I try to use it for light-weight things like a wireless receiver for my Microsoft mouse and other stuff.  Well, this time I had a USB drive plugged in in addition to my iPhone, wireless sensor, and something else.  I opened Finder and checked my iPhone and noticed that it hadn’t been backed up for over two months.  I started an encrypted backup of my phone.  A few moments later, my external hard drive unmounted on its own.  I think the dongle basically stopped communicating with it because of the communication requirements of the iPhone backup.  I decided to move that USB drive to a port that is on my iMac directly.  When I plugged it in, after roughly two or three minutes, I recieved the error that the disk could not be mounted.

Could not mount DiskManagement disenter error 0
Could not mount DiskManagement disenter error 0

I tried to mount it by hand from the command line and got “Resource busy”.  Interesting.  What’s using it?  I’m not.

What disks are attached?

$ diskutil list
/dev/disk0 (internal, physical):
#:                     TYPE NAME                SIZE     IDENTIFIER
0:    GUID_partition_scheme                    *3.0 TB   disk0
1:                      EFI EFI                 209.7 MB disk0s1
2:               Apple_APFS Container disk2     3.0 TB   disk0s2

/dev/disk1 (internal, physical):
#:                     TYPE NAME                SIZE     IDENTIFIER
0:    GUID_partition_scheme                    *121.3 GB disk1
1:                      EFI EFI                 209.7 MB disk1s1
2:               Apple_APFS Container disk2     121.1 GB disk1s2

/dev/disk2 (synthesized):
#:                     TYPE NAME                SIZE     IDENTIFIER
0:    APFS Container Scheme -                  +3.1 TB   disk2
                            Physical Stores disk1s2, disk0s2
1:              APFS Volume Macintosh HD - Data 728.4 GB disk2s1
2:              APFS Volume Preboot             81.8 MB  disk2s2
3:              APFS Volume Recovery            526.6 MB disk2s3
4:              APFS Volume VM                  9.7 GB   disk2s4
5:              APFS Volume Macintosh HD        11.0 GB  disk2s5

/dev/disk3 (external, physical):
#:                     TYPE NAME                SIZE     IDENTIFIER
0:    GUID_partition_scheme                    *2.0 TB   disk3
1:                      EFI EFI                 209.7 MB disk3s1
2:     Microsoft Basic Data PJADATA             2.0 TB   disk3s2

Let’s do a generalized search for “disk” because a) I know /dev/disk3s2 isn’t mounted; and b) if something is using that device, it is using the device itself, not a disk as a mount:

$ sudo lsof | grep disk
UserEvent 155 root txt REG 1,7 29360 1152921500312401745 /System/Library/UserEventPlugins/com.apple.diskarbitration.plugin/Contents/MacOS/com.apple.diskarbitration
diskarbit 184 root cwd DIR 1,7 704 2 /
diskarbit 184 root txt REG 1,7 161760 1152921500312399232 /usr/libexec/diskarbitrationd
diskarbit 184 root txt REG 1,7 28056 12987595370 /Library/Preferences/Logging/.plist-cache.8jY7AXDN
diskarbit 184 root txt REG 1,7 28504528 1152921500312401357 /usr/share/icu/icudt64l.dat
diskarbit 184 root txt REG 1,7 1558736 1152921500312400397 /usr/lib/dyld
diskarbit 184 root 0r CHR 3,2 0t0 319 /dev/null
diskarbit 184 root 1u CHR 3,2 0t0 319 /dev/null
diskarbit 184 root 2u CHR 3,2 0t846 319 /dev/null
diskmanag 388 root cwd DIR 1,7 704 2 /
diskmanag 388 root txt REG 1,7 2190864 1152921500312399722 /usr/libexec/diskmanagementd
diskmanag 388 root txt REG 1,7 28056 12987595370 /Library/Preferences/Logging/.plist-cache.8jY7AXDN
diskmanag 388 root txt REG 1,7 1558736 1152921500312400397 /usr/lib/dyld
diskmanag 388 root 0r CHR 3,2 0t0 319 /dev/null
diskmanag 388 root 1u CHR 3,2 0t0 319 /dev/null
diskmanag 388 root 2u CHR 3,2 0t0 319 /dev/null
UserEvent 511 pja txt REG 1,7 29360 1152921500312401745 /System/Library/UserEventPlugins/com.apple.diskarbitration.plugin/Contents/MacOS/com.apple.diskarbitration
fsck_exfa 50042 root 3u CHR 1,13 0t0 2223 /dev/rdisk3s2

Ah! fsck is running!  The disk filesystem is being checked.  Now, let’s narrow our search just out of curiosity of what else fsck is doing:

$ sudo lsof | grep fsck
fsck_exfa 50042 root cwd DIR 1,7 704 2 /
fsck_exfa 50042 root txt REG 1,7 90400 1152921500312404229 /System/Library/Filesystems/exfat.fs/Contents/Resources/fsck_exfat
fsck_exfa 50042 root txt REG 1,7 1558736 1152921500312400397 /usr/lib/dyld
fsck_exfa 50042 root 0u CHR 3,2 0t180 319 /dev/null
fsck_exfa 50042 root 1u CHR 3,2 0t180 319 /dev/null
fsck_exfa 50042 root 2u CHR 3,2 0t180 319 /dev/null
fsck_exfa 50042 root 3u CHR 1,13 0t0 2223 /dev/rdisk3s2

When it was finished, my disk mounted all by itself.

$ mount |grep disk3
/dev/disk3s2 on /Volumes/PJADATA (exfat, local, nodev, nosuid, noowners)

Python Snippets

File handling

You can use a file handle or you can work with file objects using with.  Using with has the benefits of easier-to-read syntax and cleaner exception handling.  Any files that are open will automatically be closed after your done when you use with.

Checking if a File Exists
from pathlib import Path

my_file = Path("/path/to/file")
if my_file.is_file():
    # file exists
Looping Over File Object
myfile = "output.txt"

# file handle
file = open(myfile, "r")         # a=append, r=read, w=write, rw=read/write
for line in file: 
    print(line)

# file object
with open(myfile) as file:
    # read file line by line and output to list
    data = file.readlines()
    for line in data:
        print(line)
Writing To a File
myfile = "output.txt"

# file handle
file = open(myfile, "w")
file.write("Write these lines to your file") 
file.write("And close it when you're done")
file.close()

# file object
with open(myfile) as file:
    file.write("Write these lines to your file")
    file.write("And close it when you're done")
Writing to a File, Option 2
import sys

print("Send this error to stderr", file = sys.stderr)

f_handle = open('/tmp/output_20200511.txt', 'w')
print("Output to file", file = f_handle)
f_handle.close()

Types

Dustin Ingram – Static Typing in Python


VirtualEnv

When trying to run make htmldocs from kernel source, it recommends doing so from a Python virtualenv.  It’s a perfect time to document setting one up (per their recommendation).

sudo yum install -y ImageMagick graphviz python-virtualenv
virtualenv sphinx_1.4
. sphinx_1.4/bin/activate
pip install -r Documentation/sphinx/requirements.txt

XML Parsing

xml.dom.minidom

 

System Administration Links

chroot

An excellent guide from Bart Simons

Classics

hunter2

Support and Help

Password Recovery

[CentOS] Reset Root Password (single user mode)

If you don’t remember the root password, or you just want to boot in the most minimal way, you can add init=/bin/bash to your linux line to bypass the regular init sequence and just drop to a shell. The line should look like

linux /vmlinuz-xxx root=xxx ro init=/bin/bash

Whatever is after vmlinuz and root (where the xxxs are) leave as-is.  You can remove everything else on that line except for the leading word linux, vmlinuz, root and ro.  Add init=/bin/bash

The system ought to boot and present a bash shell running as user root.  If your system has full-disk encryption, you will need to enter the encryption password.

At this command line, run the following commands:

mount -o remount,rw /
mount /proc

Then you can view and modify the user database. The main user database file is /etc/passwd. It contains user names (for both physical users and system accounts), but passwords are in a different file /etc/shadow. If you’ve forgotten a password, you can’t recover it, all you can do is change it.

If you want to change the password for an account, run

passwd root

to change user root’s password.

If you see a token manipulation error then make sure you booted into an environment that supports read/write (use rw in linux line or remount as rw).

Once you’re finished, you can reboot.

umount /
reboot

[CentOS] Reset Root Password (live CD chroot mode)

  1. Boot into your live environment
  2. Make directory on which to mount your partition
    mkdir ./mnt || /bin/true
  3. Identify your disks using fdisk
    fdisk -l
  4. Look for the bootable partition of type Linux
  5. If your partition is a standard Linux partition:
    mount /dev/sda1 ./mnt
  6. If your partition is a Linux LVM:
    pvscan
    vgscan
    vgchange -a y
    lvscan
    mount /dev/sda1 ./mnt
    mount --bind /dev ./mnt/dev<
    mount --bind /proc ./mnt/proc
    mount --bind /sys ./mnt/sys
    
  7. Change root into your mounted directory
    chroot ./mnt /bin/bash
  8. Type passwd and enter a new password
  9. Type reboot to reboot your system
Provisioning

Foreman – PXEless Bare Metal & Virtual Machine Provisioning

Volume Management

[LVM] Working With LVM Volumes