2017年11月9日木曜日

rbvmomi で GuestFileManager を使って VM 内のファイルやディレクトリを操作してみる

概要

前回 GuestProcessManager を使って VM 内のプロセス制御をしてみました
同じようにファイルやディレクトリを制御できる GuestFileManager という機能があるので今回はこれを使ってみました
ProcessManager に比べて操作できる機能が多いです

環境

  • Ubuntu 16.04.3
  • Ruby 2.3.1p112
  • gem 2.5.1
  • rbvmomi 1.11.3

ファイルの一覧を表示する

  • vim list_files.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp/"
files = vim.serviceContent.guestOperationsManager.fileManager.ListFilesInGuest(
  vm: vm,
  auth: auth,
  filePath: path,
  # index: 0,
  # maxResults: 50,
  matchPattern: "^hoge$"
)

files.props[:files].each { |file|
  puts file.props[:path]
  puts file.props[:type]
  puts file.props[:size]
  puts file.props[:attributes].props[:modificationTime]
  puts file.props[:attributes].props[:accessTime]
  puts file.props[:attributes].props[:ownerId]
  puts file.props[:attributes].props[:groupId]
  puts file.props[:attributes].props[:permissions].to_s(8)
}

ListFilesInGuest を使います
パラメータに path, index, maxResults, matchPattern を指定できます
path はファイルでもいいですしディレクトリでも OK です
ファイルの場合は 1 つだけ取得しディレクトリの場合は指定したディレクトリ配下のファイル群を取得します
index はページネート用のインデックスです
デフォルトは 0 ページ目からの取得になります
maxResults は 1 ページで取得する最大の件数になります
デフォルトは 50 です
例えば取得件数が 100 ファイルある場合に 51 件目以降を取得する場合は index を 1 にしてそこから 50 件取得するか index を 0 のままで maxResults を 100 にするかになります

matchPattern は正規表現に合致したファイル群を取得するパラメータです
上記のサンプルのように指定した場合は hoge にマッチするファイルだけを取得します
これを ^hoge というふうにすると先頭が hoge というファイルにマッチするので hoge2 や hogefuga というファイルも検索結果に含まれます
使用できる正規表現は Perl の正規表現になります

検索結果は GuestListFileInfo というクラスのオブジェクトが返ってきます
この中のプロパティ :files にというものがあり、その中に各ファイルの情報を管理する GuestFileInfo という配列があります
あとは each とハッシュを使って必要な情報を取得するだけですがその中にファイルの権限を取得できる permissions があります
これがデフォルトだと 10 進数表記になっているのでわかりやすいように 8 進数表記に変換してあげると良いと思います

ファイルの属性情報を変更する

  • vim change_file_attrs.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp/hoge"
attr = RbVmomi::VIM::GuestPosixFileAttributes(
  # groupId: 0
  # ownerId: 0
  permissions: 33279 # 100777
)

vim.serviceContent.guestOperationsManager.fileManager.ChangeFileAttributesInGuest(
  vm: vm,
  auth: auth,
  guestFilePath: path,
  fileAttributes: attr
)

ChangeFileAttributesInGuest を使います
guestFilePath で指定したファイルの属性情報を変更します
今回 Ubuntu VM 内のファイルの属性情報を変更するので GuestPosixFileAttributes を使用します
パラメータにはファイルの管理者情報とパーミッションを指定できます
上記のサンプルでは権限を変更しています
権限の指定方法は 10 進数で指定する必要があるので注意してください

返り値が void なので結果を確認したい場合は ListFilesInGuest を実行してファイルの内容を確認してください

テンポラリのディレクトリを作成する

  • vim create_tmp_dir.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp"

ret = vim.serviceContent.guestOperationsManager.fileManager.CreateTemporaryDirectoryInGuest(
  vm: vm,
  auth: auth,
  prefix: "prefix-",
  suffix: "-suffix",
  directoryPath: path
)

puts ret

CreateTemporaryDirectoryInGuest を使います
パラメータにはディレクトリを作成するパス (directoryPath) と作成するディレクトリの prefix と suffix をオプションで指定することができます
作成されるディレクトリ名は vmware000 という形式で作成されます
000 の部分はランダムの数字が入ります
その前後に prefix と suffix で指定した文字列が付与されます

返り値は作成されたディレクトリのフルパス情報が String で返却されます

テンポラリのファイルを作成する

  • vim create_tmp_file.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp"

ret = vim.serviceContent.guestOperationsManager.fileManager.CreateTemporaryFileInGuest(
  vm: vm,
  auth: auth,
  prefix: "prefix-",
  suffix: "-suffix",
  directoryPath: path
)

puts ret

CreateTemporaryFileInGuest を使います
挙動やパラメータは前述の CreateTemporaryDirectoryInGuest とほぼ同じです
ディレクトリを作成するかファイルを作成するかの違いになります
ンポラリファイルの権限は 600 で作成されるようです

ディレクトリの削除をする

  • vim delete_dir.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp/prefix-vmware130-suffix"

vim.serviceContent.guestOperationsManager.fileManager.DeleteDirectoryInGuest(
  vm: vm,
  auth: auth,
  directoryPath: path,
  recursive: true
)

DeleteDirectoryInGuest を使います
パラメータは削除対象のディレクトリと再帰的に削除するかのフラグを渡します
recursive が false の場合に削除対象のディレクトリ配下に更にディレクトリがあるとエラーとなります

返り値は void になります

ファイルの削除をする

  • vim delete_file.rb
require 'rbvmomi'

require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp/prefix-vmware136-suffix"

vim.serviceContent.guestOperationsManager.fileManager.DeleteFileInGuest(
  vm: vm,
  auth: auth,
  filePath: path
)

DeleteFileInGuest を使います
先程はディレクトリを削除しましたがこれはファイルを削除します
ディレクトリを指定した場合やファイルが存在しない場合にはエラーとなります
返り値は void です

ディレクトリを作成する

  • vim make_dir.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp/fuga/hoge"

vim.serviceContent.guestOperationsManager.fileManager.MakeDirectoryInGuest(
  vm: vm,
  auth: auth,
  directoryPath: path,
  createParentDirectories: true
)

MakeDirectoryInGuest を使います
CreateTemporaryDirectoryInGuest とほぼ同じですがこちらの場合は作成するディレクトリ名に規則はありません
createParentDirectories は mkdir でいうところの -p オプションで上位のディレクトリがなかった場合に作成してくれます

ただ CreateTemporaryDirectoryInGuest とは違いなぜか返り値は void になっています
そして MakeFileInGuest はありません

ディレクトリを移動する

  • vim move_dir.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

src = "/tmp/fuga/hoge2"
dst = "/tmp/fuga/hoge"

vim.serviceContent.guestOperationsManager.fileManager.MoveDirectoryInGuest(
  vm: vm,
  auth: auth,
  srcDirectoryPath: src,
  dstDirectoryPath: dst
)

MoveDirectoryInGuest を使います
src にあるディレクトリを dst に移動します
dst 側にすでにディレクトリがある場合はエラーになります

返り値は void になります

ファイルを移動する

  • vim move_file.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

src = "/tmp/fuga/file1"
dst = "/tmp/fuga/file2"

vim.serviceContent.guestOperationsManager.fileManager.MoveFileInGuest(
  vm: vm,
  auth: auth,
  srcFilePath: src,
  dstFilePath: dst,
  overwrite: false
)

MoveFileInGuest を使います
移動前と移動後のファイルパスを指定します
移動前のファイルが存在しない場合はエラーになります
また移動後のファイル名がすでに存在する場合に上書きするオプションがあります
true で上書きします、false を指定した場合に移動後のファイル名がすでにある場合はエラーとなります

ホストから ESXi にファイルを転送する

  • vim transfer_from.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp/fuga/file1"

ret = vim.serviceContent.guestOperationsManager.fileManager.InitiateFileTransferFromGuest(
  vm: vm,
  auth: auth,
  guestFilePath: path
)

puts ret.props[:url]

InitiateFileTransferFromGuest を使います
これは VM 上のファイルをから ESXi 上にアップロードすることができる機能になります

返り値は RbVmomi::VIM::FileTransferInformation になります
この中に url というフィールドが含まれておりこの URL にアクセスすると ESXi 上にアップロードされたファイルを確認することができます
URL は一度しかアクセスすることができません

ESXi からホストにファイルを転送する

  • vim transfer_to.rb
require 'rbvmomi'

vim = RbVmomi::VIM.connect(
  host: '192.168.100.1',
  user: 'vcenter-user',
  password: 'vcenter-pass',
  insecure: 'true'
)

dc = vim.serviceInstance.find_datacenter('datacenter') || fail('datacenter not found')
vm = dc.find_vm('directory/path/to/vm') || fail('VM not found')

auth = RbVmomi::VIM::NamePasswordAuthentication(
  interactiveSession: false,
  username: "root",
  password: "password"
)

path = "/tmp/fuga/file1"
attr = RbVmomi::VIM::GuestPosixFileAttributes(
  # groupId: 0
  # ownerId: 0
  permissions: 33188 # 100644
)

ret = vim.serviceContent.guestOperationsManager.fileManager.InitiateFileTransferToGuest(
  vm: vm,
  auth: auth,
  guestFilePath: path,
  fileAttributes: attr,
  fileSize: 26,
  overwrite: true
)

puts ret

InitiateFileTransferToGuest を使います
ローカルにあるファイルにアクセスするために ESXi 経由で取得できるURL を取得することができます
URL には一度しかアクセスできません

最後に

GuestFileManager を使って VM 内のファイルやディレクトリの操作をしてみました
GuesetProcessManager に比べいろいろな処理ができる印象です
ただ、相変わらず返り値は void が多いので確認には工夫が必要です

今回も認証はユーザ名/パスワードにしました
SSPI or Ticketed でも頑張れば認証する方法があるかもしれません

0 件のコメント:

コメントを投稿