Syncthing install on CentOS 7.5

screenshot-720I will start by quoting the product. What is syncthing? “Syncthing is an application that lets you synchronize your files across multiple devices. This means the creation, modification or deletion of files on one machine will automatically be replicated to your other devices.” This says it all. Next question is: What for? This can vary: I’m going to say here because it’s  multi-platform: there are apps, a web interface, a GUI, and so on, and all of if for free. Unfortunately installing it on CentOS is not for newbies. Let’s start.

Step one: create a yum repository. There’s an entry abut syncthing on the centos forum. It means to create a special repository for syncthing. What I did is I copied an already existing repository, rename it, and edit it.

cd /etc/yum.repos.d/
cp epel.repo syncthing.repo
gedit syncthing.repo

Inside the edited repo file, we copy this. Then yum clean all, yum update. Or even better, reboot if you can. At the end

yum install syncthing
systemctl stop firewalld
/bin/syncthing

And if you have the browser open, the Syncthing web UI as above will open. Now what? We go to the syncthing configuration, and we edit it so that it has my CentOS client IP, not the default one.  We may want to create a service for the process, but I’m not going to tell you how to do that.

I test that I can access to the web UI from another computer, and I can. Then I install the syncthing android app (that runs on the same network than my syncthing web server) and add the device on the web interface. It’s not very intuitive: to add the device you get a QR code or a very long set of letters and numbers.  Anyway, once I add it, I see on the web UI that syncthing wants to add one of the folders of my phone to the “Folders” section. I click “it’s OK” and the sync begins. Once you are done, you have the typical options: Pause, Rescan, Edit…

I must say the final sensation is very good, so I approve it. The problem will be, as usual, to propagate and promote its usage. We’ll see how it goes!

Advertisements

The Huawei incident

I’m a multi-platform user by need. So I can’t call myself an Android, an OSX or a Windows user. Of course, all of that said with the big mouth, without specifying any device. And of course I have my favourites. I must say I’m lucky I don’t have an Huawei terminal, or any of their clones (Honor and similar). But the big news of today about Google ending its deal with the technology firm Huawei sound like good news for me. I’ll try to explain why.

Previously I managed to install Android on my old DELL netbook just to find out the specs of it are way below my current mobile phone, to the point of looking ridiculous. But it worked. The install was quite easy, being the most complicated step to mount Oreo on a pen drive.

I do have a micro USB to USB adapter, and I do frequently read an USB with my generic handy. So why not let the users to install custom-designed ROMs on a handy, without the hassle of breaking the warranty or rooting the phone? In this way, I could, let’s say, install Windows XP on it, or something like that, if needed. I consider myself a pro, and I did brick an HTC already trying to root it.

If a company like Huawei goes ahead and let the people use their terminals whatever way you like (of course under certain circumstances, maybe after registering it as a test device, providing a valid email address, opening a developer’s profile with the company, or something like that) I think we will all be more free. I’m looking forward to be able to have a smartphone the way I like it, like one you can control what you send back home or not, or the apps you get and what they say. And maybe in that near future, I will finally have CentOS on my handy, if I need it. Or Windows XP 🙂

Windows 7 Update error 8007000e

snap227Back to work, I found out that one of the Windows 7 PCs that run VIP hardware crashed like the old computer that is indeed. Windows 7 is already 10 years old, but it’s still the weapon of choice for VIP hardware. The reason is clear, the development and upgrade of the drivers (and the software) is not an easy candy for the companies. I understand it very well.

Anyway, time for a Windows 7 complete reinstall in a computer that was previously running it already. Fortunately I keep the original disk and the original Product Key. I remove the useless old disk (it’s not even readable, and it makes funny noises when plugged) put a new SSD and go through the easy Windows 7 install. I give it the same PC name, and I configure the same user, so that there are no troubles for the hardware clients. After typing the Product Key, the total installation time is around one hour. Not so much. I can’t comment if it’s a long or a short time, I don’t have too much data about. It’s when I try to update the system to the latest patch that I find two issues.

Issue number one: the Product Key I entered during the install was not taken at the end as a valid one. Why is that? the hardware (that is check to validate the key) is the same. Maybe it was not taken at installation time? I try giving it in again and it works.

Issue number two: the above windows update error. I follow the solution that you can find here. The picture is also from there. The problem is, I can’t even open the browser to download the IE11! What now? I do manage to download an install Chrome, and with it, I get the desired IE11. Unfortunately after step 9 (the last reboot) I still get the update error. On the other hand, if I do afterwards what I found here, it works! So my recipe to get rid of the error is as follows:

  1. Install IE11. I got it from Chrome.
  2. Remove the two hot fixes KB2534111, KB2639308
  3. Download KB3102810, reboot, install the patch.
  4. Stop the Windows update service via services.msc, restart it.

Of course this is my solution, so try it under your own risk 🙂

Mellanox OFED install linux CentOS 7

I don’t know if this works with the latest CentOS 7 kernel. The current OFED version is 4.5-1 (downloadable here) but my logs correspond to my first install (version 2.4-1). I need this procedure written and easy to reach, and I hope it helps you also. Below, XXX correspond to your version.

root@client ~/MLNX_OFED-XXX ## > ./mlnxofedinstall 
Logs dir: /tmp/MLNX_OFED-XXX.logs 
The XXX kernel is installed, 
MLNX_OFED does not have drivers available for this kernel. 
You can run mlnx_add_kernel_support.sh 
in order to to generate an MLNX_OFED package 
with drivers for this kernel. 

root@client ~/MLNX_OFED-XXX ## > 
./mlnx_add_kernel_support.sh \
-m /path/MLNX_OFED-XXX/ 
Note: This program will create MLNX_OFED TGZ for XXX 
under /tmp directory. 
All Mellanox, OEM, OFED, or Distribution IB packages 
will be removed. 
Do you want to continue?[y/N]:y 
See log file /tmp/mlnx_ofed_iso.XXX.log 

Building OFED RPMs. Please wait... 
Created /tmp/MLNX_OFED-XXX-ext.tgz 
root@client ~/MLNX_OFED-XXX ## > cd /tmp/ 
root@client /tmp ## > tar -xvf MLNX_OFED-XXX-ext.tgz 
. 
. 
. 
root@client /tmp ## > cd MLNX_OFED_XXX-ext/ 
root@client /tmp/MLNX_OFED_XXX-ext ## > ./mlnxofedinstall 
Logs dir: /tmp/MLNX_OFED_XXX.logs 
This program will install the MLNX_OFED package on your machine. 
Note that all other Mellanox, OEM, OFED, 
or Distribution IB packages will be removed. 
Do you want to continue?[y/N]:y 

/bin/rpm --nosignature -e --allmatches \
--nodeps libibverbs libmlx4 libibcm libibumad \
librdmacm opensm-libs ibutils openmpi \
libibverbs libmlx4 libibcm libibumad \
librdmacm opensm-libs opensm-libs openmpi \
openmpi-devel ibutils ibutils-libs \
fcoe-utils scsi-target-utils openmpi \
rdma-2.0-12.fc20.noarch openmpi rdma 

Starting MLNX_OFED_XXX installation ... 
Installing kernel-ib RPM 
Preparing... ################################## 
Updating / installing... 
kernel-ib-XXX ################################# 
Installing kernel-ib-devel RPM 
. 
. 
. 
. 
Preparing... ######################################## 
mpitests_mvapich2__XXX ############################## 
Preparing... ######################################## 
mpitests_openmpi__XXX################################ 
Device (02:00.0): 
    02:00.0 InfiniBand: Mellanox Technologies MT25204 
    [InfiniHost III Lx HCA] (rev 20) 
    Link Width: 8x 
    PCI Link Speed: 2.5Gb/s 

Installation finished successfully. 

Attempting to perform Firmware update... 
Querying Mellanox devices firmware ... 

Device #1: 
---------- 
  Device Type:      InfiniHostIIILx 
  Part Number:      -- 
  Description: 
  PSID: 
  PCI Device Name:  0000:02:00.0 
  Port1 GUID:       N/A 
  Port2 GUID:       N/A 
  Versions:         Current        Available 
     FW             -- 

  Status:           Failed to open device 
--------- 
-E- Failed to query 0000:02:00.0 device, error : 
File exists. MFE_OLD_DEVICE_TYPE 

Log File: /tmp/MLNX_OFED_XXX.logs/fw_update.log 
Failed to update Firmware. 
Collecting debug info... 
See /tmp/MLNX_OFED_XXX.logs/fw_update.log 
To load the new driver, run: 
/etc/init.d/openibd restart 
Configuring /etc/security/limits.conf.

In short: when we add kernel support, we build our own version of the installer, that we run afterwards. Now we restart and test that we see the other infiniband hosts.

root@client ~ ## > ibhosts 
Ca    : An-IB-Mac-Address ports 2 "ibnode1 HCA-1" 
... my nodes here...
Ca    : Another-IB-Mac-Address ports 2 "ibnodelast HCA-1"  
Ca    : My-Client-IB-Mac-Address ports 1 "client HCA-1" 
root@client ~ ## > ibnodes 
Ca    : An-IB-Mac-Address ports 2 "ibnode1 HCA-1" 
... my nodes here...
Ca    : Another-IB-Mac-Address ports 2 "ibnodelast HCA-1"  
Ca    : My-Client-IB-Mac-Address ports 1 "client HCA-1" 
Switch    : IB-switch-identifier-one ports 24 
"MT47396 Infiniscale-III Mellanox Technologies" 
base port 0 lid 0 lmc 0
... more switch identifiers...
Switch    : IB-switch-identifier-last ports 24 
"MT47396 Infiniscale-III Mellanox Technologies" 
base port 0 lid 0 lmc 0 
root@client ~ ## > ibstat 
CA 'mthca0' 
    CA type: MT25204 
    Number of ports: 1 
    Firmware version: 1.2.0 
    Hardware version: a0 
    Node GUID: Some-Random-Numbers-And-Letters
    System image GUID: Another-Random-Chain
    Port 1: 
        State: Initializing 
        Physical state: LinkUp 
        Rate: 20 
        Base lid: 0 
        LMC: 0 
        SM lid: 0 
        Capability mask: XXX
        Port GUID: XXX 
        Link layer: InfiniBand 
root@client ~ ## > ibstatus 
Infiniband device 'mthca0' port 1 status: 
    default gid:  Some:long:set:of:letters:and:numbers 
    base lid:     0x0 
    sm lid:       0x0 
    state:        2: INIT 
    phys state:   5: LinkUp 
    rate:         20 Gb/sec (4X DDR) 
    link_layer:     InfiniBand

Probably this post is useless for you. But I repeat, not for me 🙂

Package atomic-registries requires python-pytoml error installing docker on CentOS 7

I’m moving dockers around. Most of my machines are Intel running CentOS 7. But on one Opteron running CentOS 7 (but same kernel than the intel) I got the next error when running yum.

yum install docker
..stuff here, repository list, fastest mirrors...
Resolving Dependencies
--> Running transaction check
...the checks here...
---> Package libsepol-devel.x86_64 0:2.5-8.1.el7 
will be an update
--> Finished Dependency Resolution
Error: Package: 1:atomic-registries-XXX.el7.centos.x86_64 (extras)
Requires: python-pytoml
Available: python-pytoml-0.1.14-1.XXX.el7.noarch (extras)
python-pytoml = 0.1.14-1.XXX.el7
Available: python2-pytoml-0.1.18-1.el7.noarch (epel)
python-pytoml = 0.1.18-1.el7
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest

The same command works flawlessly on other machines. Maybe it’s my machine, that has remnants from other installations. Maybe it is Opteron, maybe it’s something else. But let’s fix it. First we better be sure there’s no previous docker installed on the system:

yum remove docker docker-client \ 
docker-client-latest docker-common \
docker-latest docker-latest-logrotate \
docker-logrotate docker-selinux \
docker-engine-selinux docker-engine

Then we apply the official patch to install it.

 wget -qO- https://get.docker.com/ | sh

After that, everything seems to work! Time to move my babies around! I want to try to convert my servers to dockers so that I stop doing what I call the dance: this server here, this GPU card there, this RAM removed, this RAM added 🙂 a lonesome and tiring job the one of the moving man 😛

Repairing a old OS disk with fsck

I have a Fedora 19 system that has been running as a data proxy without a break for like 4 years already. It’s on another subnet, and I don’t have easy access to it, so it has not been updated or something like that since JC was born. Well, that system died to grub.

I have said, I don’t have easy access, so I took the system disk to analyze it at “home”, in my subnet. I have a hard disk USB docking station that I want to use to save the old system. Why I want to save the old system instead of using a new one? Because it’s the old system the one registered in that other subnet and the one with the ssh keys and users data. And it’s always a pain in the a** to chase people you don’t know where they are or what they do now. Yeah, welcome to research, my friend.

How do we do it then? I first try to mount the disk, that I read with the docking station.

root@mine ~ ## > fdisk -l
... some primary disks here...
Disk /dev/sdc: 320.1 GB, 320072933376 bytes, 625142448 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000e4e43
Device Boot Start End Blocks Id System
/dev/sdc1 * 2048 409602047 204800000 83 Linux
/dev/sdc2 409602048 488396799 39397376 82 Linux swap / Solaris

I know it is a 320 GB disk, so “sdc” is my OS disk. Let’s try to mount it.

root@mine ~ ## >mount /dev/sdc2 /data_temp/
mount: /dev/sdc1: can't read superblock

This means the disk is somehow corrupt. That was expected. Let’s fix it with fsck:

root@mine / ## > fsck /dev/sdc1
fsck from util-linux 2.23.2
e2fsck 1.42.9 (28-Dec-2013)
/dev/sdc1: recovering journal
Error reading block 25213422 
(Attempt to read block from filesystem resulted in short read). 
Ignore error<y>? yes
Force rewrite<y>? yes
Clearing orphaned inode 7864634 
(uid=0, gid=0, mode=0100644, size=1536)
...a lot of orphaned inodes here...
Clearing orphaned inode 10631668 
(uid=42, gid=42, mode=0100644, size=732)
Setting free inodes count to 10977762 (was 11137724)
Setting free blocks count to 33270091 (was 33568375)
/dev/sdc1: clean, 1826334/12804096 files, 
17929909/51200000 blocks
root@mine / ## > mount /dev/sdc1 /data_temp/
root@mine / ## > ls /data_temp/

OK! On /data_temp/ we are able to access now to OS configuration details. So let’s take what is interesting us. For example:

  • data_temp/etc/ssh/ (the ssh keys)
  • data_temp/etc/sysconfig/network-scripts/ (the network configuration)
  • data_temp/home (the home folder)

These folders and the user definition we can copy “eventually” to a new disk, in case the one we just repaired doesn’t work. If you sync everything, it will not work! Don’t be rude, one thing is hacking, the other smashing 😀

A Tkinter python multi-platform app/GUI

We wrote on python/wxpython Hello World a very simple window/gui. This time we are going to do it for real. The aim is to write “the app/GUI” that will run one command or another depending on the OS. We are going to use pure python, so that provided we have it installed (and we probably have it) our app will do the same. This time, instead of wxPython we are going to use Tkinter message boxes, for the simple reason that this seem to be more popular for doing what I want at the end. You can find a comparison on this activestate blog entry from 2015. I will cut to the chase for you:

wxPython: 6 seconds
tkinter: 1 second

Speed is important: nobody likes to wait for a window you don’t know if it’s going to pop up or not. Tkinter is also the default GUI toolkit for Python. So let’s do this. I’m going to write pieces of code, so this is going to be an ikea-type of post (build the app yourself). First we are going to discriminate by OS. How can we do that?

import sys
if sys.platform == "win32":
    print " Current OS: " + sys.platform 
    cmd = 'C:\Python27\python.exe --version'
elif sys.platform == "linux2":
    print " Current OS: " + sys.platform
    cmd = 'echo hello' 
else:
    print "No support for the " + sys.platform + " OS"

Remember to indent your code. Python is very sensible with that. Depending on your editor, this will be more or less easier. To know how your OS is called, you can use the python command line.

>> import sys
>> print ” Current OS: ” + sys.platform

Next step is define the layout of our GUI. You can start with a working one, for example, here you have a simple hello world GUI. Now that you saw a Tkinter GUI, we can write one from scratch. On a GUI, the layout is very important. Also very annoying. So making a simple sketch of the app may help. Like here the title, here an entry field, here a check button, here start/stop button. We can change the look of the Tkinter buttons as we like to have the text is in blue or the background in yellow. It is important to know, anyway, what is a button, what is a Tkinter Entry, and so on. After a little fiddling with frames and grids, and with packing options, for my app I use the more natural absolute positioning. How all of this is coded?  In principle, we need a main loop.

#### MAIN LOOP ### 
if __name__ == '__main__':
          root = Tk()
          root.geometry("600x300")
          root.wm_title('My-Tkinter-GUI')
          app = App(root)
          root.mainloop()
          root.destroy()

This can go to the end of your file. Over it we need to define App. On App we have the buttons, entries, and functions linked with the buttons. That is, what your app does. A basic example is:

class App(object):
    def __init__(self,master):
    ### GUI elements
    self.clock = tk.Label(root, text='H:00 M:00 S:00')
    self.clock_button = 
           tk.Button(root, text='Start', fg="red", 
           command=self.startclock)
    self.source_label = tk.Label(root, 
           text='Get a Directory')
    self.source_button = tk.Button(root, text='...',
           command=self.get_dir)
    self.source = tk.Entry(root,width=10)
    ### GUI positioning
    self.clock.place( x=210, y=10)
    self.clock_button.place( x=10, y=10)
    self.source_label.place( x=10, y=40)
    self.source.place( x=150, y=40)
    self.source_button.place(x=260, y=40)
    ### button functions
    def get_dir(self):
         source_dir = askdirectory(mustexist=True, 
                      title='Select Directory')
         self.source.delete(0, len(self.source.get()))
         self.source.insert(0, str('"{}"').
              format(source_dir.replace('/', '\\')))
         return source_dir

What was that? Our class App has 5 components (buttons. labels, entries). They are drawn at fixed positions using place. The command keyword points out to functions that we define later on, like get_dir.

Note that we don’t define startclock. This has a reason. Dealing with time and Tkinter is very tricky. There are hundreds of post about it. I will refer a few here. At the end I used a modified version of the stopwatch example from StackOverflow. I needed a timer also. For that, I used the after call. I tried with sleep, and stop, without reaching stability. So please learn how to use the after method. Otherwise, you’re doomed. Specially if you use infinite loops (while 1: or similar). Another concern was the stability of the GUI on long runs. You know, sometimes you need to refresh your Tkinter window or something similar. I did that using the method update_idletasks over my main loop:

#### MAIN LOOP ### 
root = Tk()
root.geometry("600x300")
root.wm_title('My-Tkinter-GUI')
app = App(root)
root.update_idletasks()
root.mainloop()
root.destroy()

I added that in addition to my after call on “App”. I used update_idletasks instead of update because update seems to have some issues. There is of course a StackOverflow post discussing that. But it is not clear for me which one is the most stable. My after call looks like this:

def run_timer(self):
   ### a lot of code here
   timestep="6000"
   self.clock.after(timestep, self.run_timer)

What I try to show is that after is called with the same function it is as an argument.

On a happy ending,  another example: here you have a color changing window written on tkinter using after timer events. It’s doing nothing but it’s a nice one 😀