Good news: my car’s transmission is failing!

Possibly, my last car

Focus… on your DOOM! Great on the Autobahnen, not so much for quick trips around town

On Monday evening, I dropped my 2008 Ford Focus diesel wagon at the dealer to get the timing belt changed and other 180,000 km/10 yr maintenance done and winter tires put on, with a request that they call if it was going to be over 100 EUR more than the 1350 EUR on the quotation.

On Tuesday morning, they called to tell me that the trouble starting I reported was actually to do with the transmission, and they had the failure codes from the ODBC to prove it, but were not sure that doing the 450 EUR transmission oil change would fix it, my first reaction was panic, assisted by already panicking over what my fellow Americans would do that day at the polls.

But then I remembered that I had ridden to work with my colleague, and was planning to take the U-Bahn and walk to the dealer to pick up my car. In fact, I drive to work about once per month and to the grocery store most Saturdays. I could buy another 10 year old Focus wagon for about 4000 EUR, if it turned out I really did miss having my own car.

On Tuesday afternoon, I asked for a purchase offer; the most the dealer was willing to pay was 650 EUR, because my car is pretty much unsaleable in Germany (older diesel + automatic transmission). Instead of spending the minimum of 1800 EUR for the scheduled maintenance and attempt at fixing the transmission, I paid 75 for the initial diagnosis and installation of my winter tires, with the intention of driving it until the transmission really did go.

On Wednesday morning, as I drove home from the dealer, I saw all those sketchy-looking used car lots, promising cash purchase for all cars…

The first wasn’t interested because of the automatic transmission, but the second offered me 1700, down from my opening offer of 2500. I smiled, thanked him and said I’d think it over while driving home to pick up the car’s title.

I pulled over at another car lot, and a fellow came running across the street, asking if I’d consider selling. I nodded and told him I’d be very happy to have 2500 for it. He countered with 1500, I with 2000, and we finally agreed on 1800. I dropped into a more permanent-looking lot downtown, but the most they’d offer was 1300: “Our friends to the East don’t like automatic transmissions.”

On Wednesday afternoon, instead of spending 1800 plus 1000 on the year’s insurance and taxes on a car that might or might not make it another year, I deposited 1800 EUR in my bank account, for a net 4600 EUR. I might have been able to get somewhat more by listing it on autoscout24.de or ebay-kleinanzeigen.de, but not much more – there’s no way I couldn’t tell a potential buyer about the transmission.

It will force me to walk and bike more, to be more careful at the grocery store, and should save us at least 3700 EUR/yr, long term (see below). For long trips, renting is surprisingly cheap: I just booked a station wagon for our post-Christmas ski week for 230 EUR – ADAC is amazing. Instead of hoping my transmission won’t finally give up in the Swiss Alps, we’ll get to drive a nearly new car! And my husband still has his smaller, cheaper car when I actually do need one.

The day after finding out my car might need a new transmission turned out to be great; my fellow Americans came through on Tuesday, too, making it even better 🙂

Seven years of the Focus – the boring arithmetic

Starting Kms: 61000
Ending Kms: 185600
Total Kms: 124600
Purchase price: 15100 EUR
Sale price: 1800 EUR
Depreciation: 13300 EUR
Annual registration tax (higher because it is a diesel): 308 EUR * 7 = 2156 EUR
Annual insurance (I kept comprehensive with a 2500 EUR deductible; this was silly after the first few years): started at 1100/yr, got down to 730 = 5990 EUR
Annual maintenance in non-transmission oil change years: 400 EUR * 5 = 2000 EUR
Annual maintenance with transmission and brake work in 2014: 1500 EUR
Two sets of tires, plus mounting to rims: 600 EUR
Semiannual wheel changes (winter+summer): 70 EUR * 7 = 490 EUR
Fuel with average consumption of 6.5 liters/100km, at price of 1.225 EUR/liter (range: 0.95-1.40 EUR/liter): (124600/100)*6.5*1.225 = 9921.28
Annoying habit of burning out headlights: 20 EUR/yr * 7 = 140 EUR
Total cost of ownership: 36097.28 EUR, 5156 EUR/yr, 430 EUR/mo (0.29 EUR/km avg)
Total cost of ownership, minus fuel (because I’ll have to buy that for rental cars, too): 26176 EUR, 3739 EUR/yr, 311 EUR/mo (0.21 EUR/km avg)

Conclusions and expectations upon going semi-carless by choice

  • Buying a three-year-old, off-lease car was an excellent idea; it was over 30000 EUR new
  • Buying an automatic transmission in Germany was not an excellent idea
  • Owning a diesel with extremely comfortable seats made sense when I drove 85 km each way every day to work
  • Owning a diesel for weekly grocery runs and occasional long trips does not make sense
  • An annual transit pass that lets me bring my bike and/or husband around on weekends and holidays for 780 EUR/yr is worth considering
  • Despite six weeks of annual vacation time, there is no way I could blow an additional 2900 EUR/yr on train tickets and/or renting small station wagons
  • Panic-buying a replacement car is *always* a mistake; you are better off renting for a week or two if you absolutely must have a car
Advertisements

Docker for Windows behind a corporate web proxy: tips and tricks

Why setting the http_proxy and https_proxy environment variables has no effect on Docker for Windows (or, why there is no docker.ini or Windows Registry setting for this)

Docker for Windows allows you to use docker commands from cmd or PowerShell as if the Docker host were running locally on your PC. This is a clever illusion: while docker.exe is a Windows program, the Docker host you’re connecting to is really running in a Hyper-V virtual machine named MobyLinuxVM. So far, I have not found a way to SSH into this VM; had I done so, I could have set the HTTP_PROXY and HTTPS_PROXY environment variables by PowerShell script every time my PC’s IP address changed.

Caveats before beginning

I use this setup on Windows 10 and Docker for Windows 17.06. A colleague still using Docker for Windows 17.03 reports that he has over 20 instances of the DummyDesperatePoitras virtual switch, so if you’re not on 17.06 yet, I recommend updating.

The IP address (169.254.123.45), DNS host (10.1.1.1) and domain (mandie.net) are DEFINITELY not the right options for your configuration, and are just here to make the examples easier to read. Do NOT just cut and paste things from this page – but you shouldn’t do that anyway 😉

DummyDesperatePoitras: this weird Docker for Windows artifact turns out to be key

The Hyper-V DummyDesperatePoitras virtual switch gets made when the Docker virtual switch is. This is a workaround for some issue or other. It turns out to be extremely useful! I’d tried using the Docker virtual switch’s IP address as the proxy address, but that didn’t work.

DummyDesperatePoitras gets a random, non-routable (169.254.0.0/16) IP address.

Get that IP address using PowerShell (no need to be admin):

(GetNetIPAddress -InterfaceAlias "*DummyDesperate*" -AddressFamily IPv4).IPAddress

For this example, I’ll use 169.254.123.45 as the result of this command. Your randomly-generated IP address will almost certainly be different.

If you get more than one result, it might be due to the problem described earlier in this post that some older versions of Docker for Windows had, where the Docker virtual switch was removed every time and remade, without removing the DummyDesperatePoitras, but still being made every time the Docker virtual switch was made. As mentioned earlier, try uninstalling Docker for Windows (removing the MobyLinuxVM will remove any images or containers you’ve created), remove all the DummyDesperatePoitras virtual switches, and then installing the 17.06 or later version.

Just enough CNTLM

CNTLM is an executable primarily available on SourceForge (now under new management and no longer dispensing spyware with its downloads, but still…) that has not been updated in over 5 years. It runs as a service, which requires local admin. It goes against all my principles.

It is also the only practical way to use Unix-style command line tools with NTLM-authenticating corporate web proxies.

Promising alternative: the Python-based Windows proxy px (https://github.com/genotrance/px). It has the major advantage of not requiring your Windows password in any form, and the major disadvantage of needing to understand more than I do about Python to build and run it. If you manage this feat, please tell me about it, and better yet, write your own blog post about how you pulled it off.

Listening on 127.0.0.1:3128 or just 3128 and setting http://127.0.0.1:3128 as your proxy will not work for Docker for Windows, because the guest VM that is really your Docker host interprets that address as *itself*, not your Windows host running CNTLM.

Having it listen to 0.0.0.0:3128 and setting the PC’s IP address as the proxy works, but you have to then change your Docker settings any time your PC gets a new IP address – a routine occurrence for consultants or anyone moving around a large campus. It also means that your PC will act as a web proxy for ANYTHING that isn’t blocked by its firewall. This can be either a bug or a feature, but I officially recommend that you do not use it as a proxy for things outside of your desktop.

The advantage of having CNTLM listen on a non-routable but static IP address is that only traffic that originated on your PC can use the proxy, but you still don’t have to change it when your PC’s IP address changes.

CNTLM configuration is set in cntlm.ini, under C:\Program Files (x86)\cntlm. The easy way to use it is to set your Windows password directly in the file. That is also the terrible way to use it. If you store the NTLMv2 hash, at least it can’t be used anywhere other than your PC (which is still not great). Set your cntlm.ini file to only be readable to the account the cntlm Windows service is running under.

Here is a way to get your NTLMv2 hash: https://stackoverflow.com/a/44238035

Set CNTLM to listen for (DummyDesperatePoitras IP) 3128 – in this example:

Listen 169.254.123.45 3128

Remember to set your NoProxy subnets here: usually, 127.0.0.*, 10.*, 172.16.*-172.31.* and 192.168.*, but you might have others that shouldn’t go via the corporate web proxy.

Set your http_proxy and https_proxy in Windows for other command line tools

While testing, set it at the command line for your current session – note the http:// (not https://) for both.

For cmd:

set http_proxy=http://169.254.123.45:3128
set https_proxy=http://169.254.123.45:3128

PowerShell:

$env:http_proxy = "http://169.254.123.45:3128"
$env:https_proxy = "http://169.254.123.45:3128"

This will only have effect for this session, and only as long as you have the window open.

Once you’re sure this works, set them in your profile’s environment variables. This change will not take effect until you log off and log back on to Windows.

Docker for Windows settings: Proxies and daemon.json

Right-click the little whale icon in the system tray and select “Settings…”, then click “Proxies”

HTTP and HTTPS Proxy Settings in Docker GUI

Docker Proxy Settings

In the “Web Server (HTTP)” blank, type http://169.254.123.45:3128 (replace with the IP address you got from running the Get-NetIPAddress cmdlet at the beginning) and click the “Use same for both” box. You should set your proxy bypass addresses in cntlm.ini for consistency between all the command line tools you use.

Click “Apply” – this is necessary to save your changes (writing them to MobyLinuxVM), but will also restart Docker (MobyLinuxVM). Go get a coffee – this takes a minute or two.

Next, click “Daemon” so that we can give it a DNS server to use for your internal domains. Click the “Experimental features” checkbox and the “Basic” switch so that it turns to “Advanced”

Docker Daemon screen before daemon.json editing is enabled

Docker Daemon – Enable daemon.json editing

Add entries for dns and dns-search, remembering to separate each entry with a comma.

%title%_%YYYY%-%MM%-%_%hh%-%mm%-%ss%

Your resulting JSON file should look like this, but with your internal domain and DNS server’s IP address instead of mandie.net’s:

{
 "registry-mirrors": [],
 "insecure-registries": [],
 "debug": true,
 "experimental": true,
 "dns": [
 "10.1.1.10"
 ],
 "dns-search": [
 "mandie.net"
 ]
}

Click “Apply,” and wait that minute or two again.

Testing, and extra help for docker build

Were we successful? Open cmd or PowerShell, and try pulling the hello-world image. Even if you have the latest version already, this goes out to docker.io and checks.

docker pull hello-world:latest

This configuration should be sufficient for pulling Docker images and running containers on your Docker host. However, any image builds that pull components from outside (apt-get, npm, etc.) will need to get the proxy information explicitly. You don’t want to store this in your Dockerfiles, since it’s specific to your PC. You can feed build-time environment variables like this:

docker build --build-arg http_proxy=http://169.254.123.45:3128 --build-arg https_proxy=http://169.254.123.45:3128 -t myawesomeimage:latest .

Let me know if something about this doesn’t work for you – I’m still a bit surprised that it works at all.

Now for something completely different: offline patching for IBM Cloud private expired product certificate

In case you were wondering why I’ve not posted any silly Skype tricks lately, I seem to have ended up in charge of Kubernetes at my company, and for reasons I won’t bore you with, we’ve decided to set up IBM Cloud private on-prem.

The product certificate expired on 22 August 2017, so there’s a patch: https://www.ibm.com/developerworks/community/blogs/fe25b4ef-ea6a-4d86-a629-6f87ccf4649e/entry/Certificate_update?lang=en

However, the included bash scripts presume that all of the nodes have access to Docker Hub. Since ours don’t, because we are not heathens who allow our servers to talk to the Internet, I made a workaround:

1) Get the updated ibmcom/cfc-router:1.2.0 image using a machine that can connect to Docker Hub and pack it into a tarball:

docker pull ibmcom/cfc-router:1.2.0
docker save ibmcom/cfc-router:1.2.0 -o cfc-router-fix.tar

(rant about pushing an updated Docker image with THE SAME EXACT VERSION TAG goes here)

2) Copy this tarball to all of the nodes in your cluster

3) SSH into each node in the cluster and load the image:

docker load -i /wherever/you/put/it/cfc-router-fix.tar

4) Copy the update-cert.sh script and remove the following lines, because they are the ones that wanted to go onto the scary Internet and pull the images directly. Leave in all the other docker commands! If you’re using Windows, copy it to a Linux machine and edit it there to avoid any weird linefeed stuff:

if [[ "$(uname -m)" == "x86_64" ]]; then
    docker pull ibmcom/cfc-router:1.2.0
else
    docker pull ppc64le/cfc-router:1.2.0
fi

5) Copy your modified script to each of the nodes. You then need to set execute permission on it, and can finally run it:

chmod +x update-certs.sh
./update-certs.sh

 

What Version Are Your AudioCodes SBA Web Interfaces? A One-Liner.

How your AudioCodes SBA login pages should look, as of May 2016

How your AudioCodes SBA login pages should look, as of May 2016

Unlike the components the SBAs share with their big Front End Server brothers, like RTCSRV and RTCMEDSRV, the manufacturer-custom web interfaces are NOT updated in the Cumulative Updates. You need to check on these periodically with AudioCodes, Sonus or whoever else you got your SBAs from.

These management interface updates are for security and performance issues. If you’re running your SBAs the way the manufacturer recommended, though, there are a lot of remote operations that just won’t work, making version checking painful.

However, if you’ve got AudioCodes SBAs, here is a one-liner that only requires that you have a consistent naming convention (we have “sba” in all of our SBA names) and at least ViewOnlyAdmin access to Lync/Skype, using the magic of very simple webscraping:

(Get-CsPool).computers.where({$_ -like "*sba*"}) | foreach { (Invoke-WebRequest -Uri "http://$_/Home/LogOn").content -match "(1\.\d+\.\d+\.\d+)" | out-null; [pscustomobject]@{ComputerName = $_; Version = $matches[0] } }

Substitute whatever your SBAs have in common for “*sba*” (remember the asterisks!)

Or, here’s a version using nested Where() expressions that will work even if you have no naming conventions:

(Get-CsPool).where({$_.services -like "*registrar*" -and $_.services.where({$_ -like "WebServer*"}).count -eq 0}).computers | foreach { (Invoke-WebRequest -Uri "http://$_/Home/LogOn").content -match "(1\.\d+\.\d+\.\d+)" | out-null; [pscustomobject]@{ComputerName = $_; Version = $matches[0] } }

I have no idea if a similar approach will work with other manufacturers’ SBAs.