Onishi take on issue

備忘録と好き勝手言います

pythonでこのインストールはシステムポリシーで許可されていませんと出たので解決したメモ

ただインストールしようとしただけなのに

pythonをインストールしようとしたら

このようにこのインストールはシステムポリシーで許可されていませんというエラーが出ました。

解決法

様々な記事を見るとレジストリの設定を変えるなどがありますが、僕の例は簡単でした
ただインストーラーを管理者権限で実行するだけです。

これで僕の場合はインストールが出来ました。レジストリの設定をする前に管理者権限で実行を押してみてそれでもインストール出来なさそうならレジストリ変更をお試しするのがおすすめです。
管理者権限で実行できる環境じゃなければレジストリ設定しかないかもですが。。。

ASP.NET Core Web APIで作成したAPIをIISに配置する

いよいよIISに作成したAPIを導入してみましょう

learn.microsoft.com

正直このリンク先で全部理解できると思います。参考程度に当記事も見ていただけたらと思います。

公開手順

APIサーバーを立ててIISをインストールする

APIサーバーをまずは作成します。APIHyper-Vで活用したいというテーマがあるのでHyper-VVMを作成し、APIサーバーとします。

  • Windows ServerをインストールしたVMを作成します。

名前はなんでも大丈夫です(僕はAPIcontrollerとしています。
スペックはWindows Serverが余裕で動くくらいでお願いします


  • IISを導入する

サーバーマネージャーからIISを導入してください。
設定は全部デフォルトで大丈夫なはずです。


  • IISを開いてサーバーを立てる

名前とかも適当で大丈夫です。
ただここでの設定ポートとAPIのほうのPropertiesにあるlaunchSettings.jsonにあるポートは統一してください。

ここまでできたら一旦準備完了です。

Visual Studioでプロジェクトを発行する

上のビルドタブから○○の発行があるのでそれをクリックします

フォルダを選択します

フォルダの場所は先ほどIISで作成したサイトのパスにします。

右上の発行を押せばそのフォルダにプロジェクトが発行されます。

動作確認

こんな感じでフォルダにプロジェクトが発行されていることを確認します。

次に早速動作確認をします。

ブラウザでURLを入力してみましょう。何もエラー画面がないということは。。。

できてますね!

VMの親ホストからInvoke-webrequestで叩いてもAPIは機能しました!

というわけで簡単なAPIの公開手順は以上でございます

APIが使えることでHyper-V管理をより効率化

このようにAPIPowershellを実行できるようになりました。
APIを利用してコントロールパネル等を作成すると、
Hyper-VでVDI等を導入されている組織等でシャットダウン・起動やスペック変更などを行えたり、
様々な管理を効率よく行うことが出来ます。

またAPIHyper-VでオールインワンVDI環境などを作成する記事なども書いてみたいですね。。

ASP.NET Core Web APIで自作powershellモジュールを実行する

前の記事ではPowershellASP.NET APIで動かすことが出来ました。
しかしこの書き方だと自作の関数やモジュールを動かすことができませんでした。
日本語ではこの情報がまったく見つからなかったので海外Webの海に飛び込み必死に調べ、ついに完全に理解したので記事にします。

動作環境
.NET 7.0
Microsoft.Powershell.SDK(7.3.2) NuGetからインストール

実際に自作モジュールを動かしてみよう

簡潔にコードから

今回実行する自作関数は別ホストにinvokeしてhostnameを取ってくるというものです。

前の記事から加えたところはinitialsessionstateという部分と、その中でPowershellの実行ポリシーを指定しているところですね。

// Use Custom Powershell Module in C#
using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace test.Controllers //ここはプロジェクト名.controllerです
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {

        //GET hostnameを取得
        [HttpGet]
        [Route("gethost")]
        public void RunPowerShell()
        {
            var initialState = InitialSessionState.CreateDefault2();
            initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
            using var ps = PowerShell.Create(initialState);
            var results = ps.AddScript(@"
Import-Module 'C:\Users\User\Documents\WindowsPowerShell\Modules\gethostname'

gethostname
").Invoke();
//import-moduleのモジュール部分はフルパスで
        }
    }
}


無事swaggerで200が帰ってきて、かつ画像の通り宛先ホストのhostnameが取得できました。

どうやらInitial Session Stateがキモみたいです

learn.microsoft.com

Initial Session Stateはセッションを作るときのコマンド、変数、モジュールなど、実行空間の特性を指定できると書いてあります。
前の記事ではどうやら実行ポリシーの関係上Import-Moduleを実行することができなかったようなので、
Initial Session Stateに実行ポリシーをUnrestrictedに指定することによって、自作モジュールを動かすことができたというわけです。

実行ポリシーが指定されていないと怒られます

InitialSessionState.CreateDefault2メソッドだとMicrosoft.PowerShell.Core モジュールがインポートされています。
InitialSessionState.CreateメソッドだとCoreモジュールもないまっさらな実行空間が作られます。

Runspaceは必須ではないみたいですが、なぜいらないのかあまりわかっていないので一応Runspaceを付けたいですね。。
あと好みの問題ですが、複数行のスクリプトよりもコマンドで実行させたいなと。。

改良してみた


// Use Custom Powershell Module in C#

using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace test.Controllers //ここはプロジェクト名.controllerです
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {

        //GET hostnameを取得
        [HttpGet]
        [Route("gethost")]
        public void RunPowerShell()
        {
            var initialState = InitialSessionState.CreateDefault2();
            initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
            initialState.ImportPSModulesFromPath(@"C:\Users\User\Documents\WindowsPowerShell\Modules\hosttest");

            Runspace runspace = RunspaceFactory.CreateRunspace(initialState);
            runspace.Open();

            using var ps = PowerShell.Create(initialState);
            ps.Runspace = runspace;

            var results = ps.AddCommand("hostget").Invoke();

        }
    }
}

Initial Session Stateで実行ポリシーとモジュールも先に追加することによってImport-moduleコマンドをなくし、一応Runspaceを追加しています。
InitialSessionState.Createメソッドで一から使うコマンドの指定をするのもありかとは思いますが、一つ一つ作っていかないといけないのでCreateDefault2メソッドが最適だと思います。
とてもセキュリティが厳しい環境ならCreateメソッドを使うのはありだとは思います。。

まとめ

モジュール読み込みができるようになったことでAPIから自作関数を実行できるようになりました。
これでAPIから様々なPowershellの機能を短く便利に叩くことができますね!

一応二つの方法を記事にしましたが、好みですねここは。。
そして、モジュールさえも作らなくても一番目のコードのようにps.AddScript(@"")で囲むと複数行のスクリプトも実行できるのでそれでもいいと思います。。
ただ、様々な機能を含んだ複雑な実装になると管理も可読性も低くなるので、Powershellの部分はモジュール化してしまうのがおすすめでございます。

また情報があれば記事にします

ASP.NET Core Web APIでPowershellを実行する

この前C#Powershellを動かせたので、ASP.NET Core Web APIPowershellを動かしてみたという記事です

実際に作ってみよう

事前準備

Visual Studioを起動して新規プロジェクトの作成画面から、ASP.NET Core Web APIを選択します


ここはお好みで


ここでは.NET6.0にしましたが、7.0でもいいと思います(後述のnugetパッケージのバージョンに注意)

動作テストとnugetパッケージの追加


初期画面ですね、早速上にある再生ボタンみたいなボタンを押してみます。


実行されてAPIのテストができるSwaggerが開きました。動作確認したのでブラウザを閉じるかVisual Studioから停止させます。

次にパッケージを導入していきます。


依存関係のところでNuGetパッケージの管理を押します


たぶんOffline Packageが導入されているかと思うので右の歯車をクリックしてパッケージソースをオンラインから取ってこれるようにします。


パッケージソースを新規追加し、
https://api.nuget.org/v3/index.jsonを追加します


powershellと検索してMicrosoft.Powershell.SDKを見つけて入れます。
ここで重要なポイントです。
.Net 6.0にした場合は基本バージョン6.2.7を入れます。
7.x.xを入れる場合は.Net 7.0のプロジェクトにしてください。


(画像は後付けなので7.3.2が入ってます)

APIコントローラーの作成とコード作成


次にpowershellを実行するコントローラーを作成します。APIコントローラー(空)を選択しました。
特に指定がなければValuesControllerという名前で作成されます。


こんな感じが初期画面ですが、全部消して以下をコピペします

using Microsoft.AspNetCore.Mvc;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace test.Controllers //ここはプロジェクト名.controllerです
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {

        //GET hostnameを取得
        [HttpGet]
        [Route("gethost")]
        public void RunPowerShell()
        {
            using (PowerShell ps = PowerShell.Create())
            {
                var script = @"
$res = invoke-command -scriptblock {hostname} | out-file C:\log\hostname.txt
";

                ps.AddScript(script);
                //PowerShellコマンドを実行
                ps.Invoke();
            }
        }
    }
}

今回のAPIでは前の記事と違ってRunspaceを使わない簡単なpowershellの実行方法にしています。
中身はコンピューター名をC:\log\hostname.txtに入れるという動作になっています。
そのため、事前にC直下にlogファイルを作成してください。

(変数に入れたりinvoke-commandを使ったり無駄な部分がありますが検証で試した跡なので気にしないでください)

ちゃんとpowershellのパッケージを入れておけば動作すると思います

動作確認

それでは実行してみましょう。


こんな感じにちゃんと表示されると思います。

Get⇒try it out ⇒executeの順に押していくとAPIが動きます

200が帰ってきたことが確認できました


ちゃんと出力も出来てました


もちろんswaggerに書いてあるRequest URLを直接ブラウザに入力しても動きます。完璧なAPIです。

まとめ

このような感じで簡単にpowershellを実行できるAPIを作ることが出来ました。

活用方法としてはAPI用のサーバーの中にpowershellで運用に必要な機能を作ったモジュールを作成しておき、APIからinvoke-commandでAPI用サーバーへコマンドを投げることによって、
APIを駆使したWindows Server環境が作成できます。(不特定多数のユーザーが個別でVMを作ったり、消したり、メモリを変えたりなど)

ただこの前実行したrunspaceとの違いがよくわかっていないのでもうちょっと調べたいですね。。。
ただ.NET 6ではもうrunspaceinvokeが使えないっぽいです。。?これが後継ってことでいいのかな。。
また情報があれば記事にします

C#でPowershellを実行してみる

味気なかったのでフリーのwindowを張っておきます

Hyper-VAPIで管理することを目標にしながら、やっていこうかなと思います。

.NETでHyper-Vを管理する手法はどうやら二つあるようです。

今回は簡単そうなPowershellを実行する手法を試してみたメモです。
VBC#もあんま知らないですが、C#のほうが役に立ちそうなのでC#でやります

C#Powershellを呼び出す

PowershellWindows上で実行するスクリプトとして最強なので正直この手法が楽だと思います

Get-VMなどの標準のコマンドレットや自作コマンドレットも実行できるので、C#Powershellを実行するところは簡単にしておき、難しい処理はPowershellを作りこめばいいだけです。
Hyper-V WMI Providerの資料が全然ないのもこの方法で十分だからかもしれませんね。。。

とりあえずやってみましょう

参考にしたのはこちらのページ
developers.gmo.jp
このページの下部にあるサンプルコードをダウンロードしてVisual Studioで開きます

開いたらProgram.csの中身を見てみましょう
.net frameworkが古いと言われるかもですが、推奨って書いてるやつ選択してください)
構造は

MainーーRunPowerShell
|
|ーRemotePowerShell
|
|ーRemotePipeline

的な感じになっており、Powershellを実行できるメソッドが三つあるようです。
33~35行目のコメントアウトを一つ外すことで三つのうちどれかを試せます。
(コメントアウト外すの忘れて時間無駄にしたので気を付けてください)

参考記事が最強すぎてこれ読むだけでも良いのですが
一つ一つのメソッドを一応簡単にかみ砕いてみました

RunPowershell

Mainで始めにアカウントやパスワード、実行するコマンドを入れておきます。
それで認証やinvoke-comanndなどにまとめて送信してくれるというものです。
Invoke-commandを使うのでWinRM接続設定をしておく必要があります

実行時にアクセスが拒否されました的なエラーが出たらTrustedHostsの設定が上手くいっていないかもしれません

strCmdの最初のTrustedHostsの部分をコメントアウトしましょう。
Powershellにて別でTrustedHostsの処理を実行しておきましょう

Set-Item WSMan:\localhost\Client\TrustedHosts -Value 実行元のIP -Force -ErrorAction Stop
RemotePowershell

Invoke-commandではなく、WinRMのURLを利用したコマンド送信方法です。
WinRMの接続設定とファイアウォールを開く必要があります。

RemotePipeline

RemotePowershellではStrGet-VM | Out-stringというパイプラインを事前に設定していましたが、
RemotePipelineはGet-VMだけで、あとはobjpipelineでOut-stringを埋め込んでいる手法です

絶対このパイプラインを使うっていうときに使えるかもしれません。

実行結果


こんな感じで成功しました
設定をしっかりしていれば三つどの手法でもこんな感じで出来ると思います。

今はdebug.writelineで出力してますが、これをファイルに書き込みしたりもできますね

この機能がHyper-V APIの核となります。
例えばVMを作る機能なら、
VMを作るコマンドレットを作成しておいて、それをこのRunPowershellで送信する的な感じで作っておけば
APIとして作れそうです。
次はAPIの作成について書いていきたいと思います

minrootを変えたらWindowsサーバーが起動しなくなった

minrootとは

minrootはハイパーバイザー(Hyper-V)で使われるそのホストのCPUのコア数を指定して、予め占有させておく機能です。
つまり、minroot8コアだとホスト用に8コア占有して、VMには使わせません。逆にその8コア以外はVM達が占有できます。
つまりCPUのコアをホスト用とVM用に住み分けるという機能ですね。

bcdedit /set hypervisorrootproc 任意のコア数

これが設定コマンドです。

あるサーバーを動かしていてminrootを16コアから8コアにしたところ、OSが起動しなくなりました。OS再インストールしてもダメでした。。。

暫定解決法はminrootを戻すことだけ

とりあえずセーフモードを起動してminrootを16コアに戻したら通常通り起動してくれるようにはなりましたが、8コアにするとOSが起動しなくなります。。
そのサーバー全てがそうなのではなくて、結構再起動とか何回も設定変更したものだけがそうなったので、ごちゃごちゃにしたやつだけがこんな症状になっているみたいですね。

Hyper-Vをアンインストールしてみたりなど試してみましたがダメでした。
NICRSSの割り当てなどいろいろ見てみようと思いますので、進捗があれば追記しようと思います。

GPU-P vGPU付きVMを10台同時にベンチ回す (GPU-PV)

GPU-P (GPU-PV) 10台で回してみよう

最近GPU-Pのことを思い出しました。これからどんどんDaaS市場が発展していくと常々思うのでもう少し発展させてほしいと願っております。
NVIDIA GRIDや VMwareなどは発達しているみたいなんですけどね。。。Hyper-Vではうんともすんとも言わないですね。。
GPU-Pが次期WindowsWindows Serverで何か情報が来ることを祈りまして、10台ベンチを回します。

なぜ10台でベンチマークを回すか

以前の記事で3台同時に回したことがあるのですが、3台だと余裕だったので限界を知りたいという意味を込めて10台にします。10台がCPUもメモリもGPUも限界って感じでした。。。
どこかで理論上は32分割が限界だとか書いてたと思うのですが、さすがに32VM作れるのはサーバーにGPUぶちこむかRyzen Threadripperとかに24GBメモリ級のGPU詰め込むかですね。。。
でも仕組み的に32分割以上も出来そうな予感はするのですが、これ以上は個人的には出来なかったです。。。

10台のVMの作成方法

onissue.hatenablog.jp
これをぜひご参照ください。
今回のスペックも前の記事と同じでございます。

ベンチマークを回した結果

ベンチマークは簡単早いNovabenchで測定しました。


なんかすごい光景


気分はこんな感じですね。。。

結果は10台一応ちゃんと回りました!すごいえらい!

平均はこんな感じでした。まあこのスペックで10台回せただけでもよしとしましょう。

10台同時にYoutubeも再生してみた

Youtubeベンチもやってみましょう。結果はこんな感じでした。
(動画はトップにあった適当なの流してます)

https://onissue.hatenablog.jp/entry/2022/06/14/025607

結構ちゃんと再生できているのが驚きでした。。。
GPUなしだとザコCPUなので10台同時は難しかったと思います。
まあYoutubeはさっきのベンチマークよりかは動作が軽いとは思うのですが、それでもこの光景は高スペックVDIとしての可能性を秘めていて面白いですね。。。

ということなので、Azureばっかり頑張ってないで、こっちもよろしくお願いしますマイクロソフト
(Azureのほうが儲かるんでしょうけど)

以上です。またGPU-Pについて記事にできるような情報が出てきたらうれしいですね