バイクとプログラミング

Category: 未分類

任意のサービスが仮想ネットワーク(virbr)より先に起動するのを防ぐ

QEMU/KVMを動かしているホスト上でMirakurunを動かし、仮想ネットワークを通してゲスト上で動いているChinachuで受信したい。基本的にデフォルト設定ではゲストとホストが直接通信することはできないため、isolatedモードの仮想ネットワークを追加し、それ経由で通信する。

が、この仮想ネットワークの起動タイミングが遅く、Mirakurunのような起動時にIPが取得できているネットワークのみをlistenするように書かれているプログラムでは、仮想ネットワークのlistenがすり抜けてしまうことがある。

これを解決するためには、netplanとnetworkd-wait-online.serviceを組み合わせるか、Mirakurunを起動させているデーモンの順番を調整する必要がある。今回は後者で対策。

仮想ネットワークを起動しているサービスはlibvirtd.service これより後に任意のサービスが起動できるようにすればよい。

Mirakurunを起動させているデーモンはPM2のため、PM2のサービスファイルを編集する。

nano /etc/systemd/system/pm2-root.service

UnitにAfter=libvirtd.serviceを追記する。

[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target
After=libvirtd.service

daemon-reloadで設定を適応する。

sudo systemctl daemon-reload

これで仮想ネットワークの起動以降にPM2が起動されるため、ネットワークを取りことがなくなる。

忘備録 Ubuntu 20.04 QEMU/KVMで仮想環境建ててGPUパススルーするまで

走り書き。

IOMMUなどの設定は必要。OVMFの記事ではあるがArchWikiに参考になる情報が載っている。

IOMMU の有効化 – OVMF による PCI パススルー – ArchWiki
GPUの分離 – OVMF による PCI パススルー – ArchWiki

  1. 基本的なインストール

とりあえず周辺パッケージを入れる。基本的には

libvirt-binはUbuntu 18.xからなくなったようなので注意。基本的にWikiにしたがってインストールすれば問題ない。

KVM/Installation – Community Help Wiki

E: Unable to locate package libvirt-bin

virsh list --all してエラーがでなければOk

2. Macのvirt-managerから接続する

virt-managerをMacBookにインストール – Qiita

このあたり。SSHで接続するので、コマンドでソケットの場所を指定するのを忘れずに。忘れるとデフォルトの場所に探しに行くため引っかかる。

3. `virt-install` でとりあえず生成

Mac等のリモートからの接続だと、ISOなんかをアップロードすることができない。そのため、ホストにSSHで入りvirt-installを使って一度VMを作成する。

virt-install --name=test --vcpus=8 --memory=4096 --cdrom=ubuntu-20.04-live-server-amd64.iso --disk=path=/var/lib/libvirt/images/test.img,size=20,format=raw

コマンド叩いてしばらくすると、Macの方からコンテナを観測できる。一度強制的に終了させることで、設定の編集が可能になる。設定はお好み。

4. ホスト側でGPUを

GPUの分離は下のコマンド叩いて[]の中のIDをvfioで使うようにする。mkinitcpio は書かなくてもできた(あまり良くなさそう)。

> lspci -nn | grep -i nvidia

26:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU117 [GeForce GTX 1650] [10de:1f82] (rev a1)
26:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10fa] (rev a1)

> vi /etc/modprobe.d/vfio.conf

options vfio-pci ids=10de:1f82,10de:10f0

適応してから lsmod | grep -i nouveau 、なにも出なければOK

5. ゲスト側XMLの編集

例のやつ。kvm, hypervを追加。適応後ホストの再起動が必要?ゲストのみではうまく行かなかった。

  <features>
    <acpi/>
    <apic/>
    <hyperv>
      <vendor_id state="on" value="whatever"/>
    </hyperv>
    <kvm>
      <hidden state="on"/>
    </kvm>
    <vmport state="off"/>
  </features>

再起動して、公式ドライバ入れて sudo nvidia-smi でエラーがでなければOK。

NodejsのTypeScriptでGlobalな変数定義

ゲームプログラミングにて、様々なステータスを引数で渡すことなくアクセスするためのFluxライクなライブラリを書いた。その際にグローバル変数を定義する必要があり、すこしハマったので調べたことをメモ。

グローバルな型定義を行うにはおなじみの.d.tsファイルを使用する。どこに設置しても良いが、今回は/types/index.d.tsに設置する。また、必ず@types/nodeを入れる必要がある。

index.d.tsファイルの内容は以下のような形。

import { State, Dispatcher } from '../src/xxx/State';

declare global {
    namespace NodeJS {
        interface Global {
            state: State;
            dispatcher: Dispatcher
        }
    }
}

declare global宣言でモジュールの型定義を拡張することができる。もちろんNodejsのglobalオブジェクトはNodeJS namespace内に定義されているため、それを拡張することになる。@types/nodeを必要とする理由はこのことから。

また、index.d.tsをtsconfig.jsonで明示的に読み込む必要がある。

{
  "compilerOptions": {
    ...
    "typeRoots": ["types"], // 型定義ファイルを設置したディレクトリ
    "types": ["node"],
    ...
  }
}

これでglobalオブジェクトを使用する準備ができた。あとはコードを書けばコンパイルできる。

global.dispatcher = new Dispatcher();
global.dispatcher.dispatch('your_event');

以上です。

ES Modulesではシビアな循環参照

タイトルの通りです。ES Modulesでどハマりしました。

DOMを所定の形式に変換して出力を行う処理を書いていましたが、その中で循環参照が生まれ二進も三進もいかなくなってしまったためメモを残します。

下記のようなファイル群を用意します。Chrome Version 74.0.3729.169で再現。

// script.js
import ModuleA from './ModuleA.js';

new ModuleA().createModuleB();
// ModuleA.js
import ModuleB from './ModuleB.js';

export default class ModuleA {
    createModuleB() {
        return new ModuleB();
    }
}
// ModuleB.js
import ModuleA from './ModuleA.js';

export default class ModuleB extends ModuleA {
}

上記のコードをHTMLから読み込むと下記のようなエラーが出ます。

ReferenceError: can't access lexical declaration `ModuleA' before initialization

まさか循環参照が悪さをしているとは知らず、直感的にはわかりにくいエラーで大変混乱しました。これは普段宣言していない変数を参照しようとすると出るエラーです。

これを解決するには、ModuleA.jsを読み込む前に、あらかじめModuleB.jsを読み込んでおく必要があります。

// script.js
import ModuleB from './ModuleB.js'; //  ここで読み込む
import ModuleA from './ModuleA.js';

new ModuleA().createModuleB();

これで問題なく読み込むことができました。

まだ理解が浅く、なぜこうなるのかを断言できないので詳しくは次回以降にメモできればいいかなと思います。

TypeScript Enumの値をオブジェクトのキーとして使う。

TLDR ブランケットを忘れるな

TypeScriptを使っているとオブジェクトのキーにEnumの値を使いたい時があります。まぁ当たり前なんですが、下のコードはコンパイルできません。

enum myStatus { int, act, typing }
const yourObject = {
myStatus.int : 5
}

TypeScript上でのEnumは要はオブジェクトなので、ちゃんとキーをブランケットで指定しないと怒られます。

enum myStatus { int, act, typing }
const yourObject = {
[myStatus.int] : 5
}


TypeScriptで動的インポート import() を使う。

自作ゲームのスキル計算の自由度を上げようと、JSONから単一クラスによるスキル情報定義に変更しました。JSONの場合、それ自体はただの文字列なので読み込むのは簡単だったのですが、TypeScriptの場合は動的インポートを使用する必要が出てきます。

動的インポートというのは、プログラムの実行時に関数やクラスをインポートすることを言います。TypeScriptやJavaScriptでは動的インポートを行なうためにimport()関数を利用します。

使い方は非常にシンプルです。import()関数は利用時にPromiseを返却します。

// ./modules/module1
export class Module1 {
constuctor() {
console.log('Hello');
}
}
// 読み込む側
import('./modules/module1')
.then((modData) => {
new modaData.Module1(); // => 'Hello'
})
.catch((error) => {
console.error(error);
});

Promiseなので、Async / Await関数でも利用することができます。

とりあえず以上です。

管理の続かないWordPressサイトを脱却するための工夫

タイトルの通りです。

私は以前からWordPressを使ったサイトをいくつか立ち上げ、運用したことがあります。このドメインでも、もともと`blog.anyfrog.net`というホストでブログを書いていました。

しかし、そのブログも含め基本的に運用が一年以上続きませんでした。

WordPressを自主運用すると、SaaSなどのサービスを使わない限り、物理的なサーバのヘルスケアから、仮想PC上ののOS, PHP, DB等の維持がもれなくくっついてきます。

数ヶ月経つと、”記事を書く気力はあるがバックエンドの維持管理が面倒くさい”状態となり、そのままサイトごとフェードアウトと言うことが数回、ありました。

そのため、維持管理の必要ないQiitaを気に入って使っていたのですが、先述の理由からまた個人ブログに戻ることにしました。そこで、同じ過ちを侵さぬようできるだけ管理の楽な方法でサイトを作ろうと考えました。

そのような場合、一般的にはWordPress.com等のホスティングやブログサービスを使うべきですが、独自ドメインの設定にお金がかかったり、カスタマイズが容易でなさそうなどの理由から結局自主運用のWordPressを使うことにしました。その中で選択したことをメモします。

まず、サーバサイドについて。今までは自宅サーバのWindows Server上で動いているHyper-V上のUbuntuに構築していましましたが、前述の通り物理サーバ+Windows Server+仮想Ubuntu+サーバソフトウェアの維持管理のコストが発生するため、VPSを利用することにしました。

選んだVPSはさくらVPSの1Gプラン。この点は単純にさくらインターネットに個人的な信用があるからです。石狩DCの無停電運用とか。さすがです。

一方で、このままだとOSとサーバソフトウェアの維持管理コストが発生するため、サーバ側のOSにも目を向けました。さくらVPSでは、KUSANAGIというWordPress専用仮想マシンが利用できるので、それを採用しました。

KUSANAGIについてはしばらく触ってからレビューをしようと思いますが、最適化がすでに済んでいるため非常に高速という点や、提供会社によりRPMパッケージ(ベースはCentOS)の提供が行われているためサーバソフトウェアの維持管理が楽、という点があります。

上の2つにより、だいぶ維持管理が楽になった気がします。

最後に、このブログを運用するにあたって一週間に一記事を投稿することを目標に設定したいと思います。ブログの利用を習慣づけることによって、アウトプットを活性化して、維持管理も含めたブログに対するモチベーションを高めることが目的です。

以上です。

Hello world!

WordPress へようこそ。これは最初の投稿です。編集もしくは削除してブログを始めてください !

Powered by WordPress & Theme by Anders Norén