2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SoftLayer CLIを拡張する: Virtual Serverの稼働ホストをsl vs listで表示する

Last updated at Posted at 2015-01-17

SoftLayerはSoftLayer CLIと呼ばれるPythonベースのコマンドラインインタフェースを提供しています。
サーバーのリストを参照したり、サーバーをオーダーしたり、一部の設定を変更したりといった操作がコマンドラインから実行できるようになっています。わざわざPortalを開いて操作しなくてもよいので、ちょっとした状況の確認や、簡単な処理の自動化をするために使うことができます。

複雑な処理を実行したい場合は、PythonなどでAPIを使って一からプログラムを書くのがよいですが、CLIでほぼやりたいことができるけど、少しだけ情報を追加したい場合など、既存のCLIを少し拡張するだけ十分な場合もあるでしょう。

ここでは、Virtual Serverの稼働ホストをsl vs listコマンドで表示させるようにCLIを拡張してみます。

Virtual Serverの稼働ホストを取得する方法はShinobiLayer: Virtual Serverの作成者や稼動ホストのRack/Slot情報を確認するスクリプトを参考にしています。

CLIのインストール場所

CLIのファイルは、以下のパスのCLIというディレクトリにインストールされています。

OS Path
Mac OS X /Library/Python/2.7/site-packages/SoftLayer
Linux /usr/lib/python2.7/site-packages/SoftLayer
Windows ??

モジュール

CLIのファイルは、CLIコマンドの<module>の単位で分かれています。

$ sl <module> [<args>...]

該当のファイルを変更することで、そのmoduleを使ったコマンドの処理を変更することができます。
vs.pyを変更すればsl vsコマンドの処理を変更できますし、server.pyを変更すればsl serverの処理を変更できます。

$ ls -l CLI/modules/*.py
-rw-r--r--  1 root  wheel    356 Jan  4 23:12 CLI/modules/__init__.py
-rw-r--r--  1 root  wheel   5679 Jan  4 23:12 CLI/modules/cdn.py
-rw-r--r--  1 root  wheel   6459 Jan  4 23:12 CLI/modules/config.py
-rw-r--r--  1 root  wheel  10400 Jan  4 23:12 CLI/modules/dns.py
-rw-r--r--  1 root  wheel    925 Jan  4 23:12 CLI/modules/filters.py
-rw-r--r--  1 root  wheel  14813 Jan  4 23:12 CLI/modules/firewall.py
-rw-r--r--  1 root  wheel   5193 Jan  4 23:12 CLI/modules/globalip.py
-rw-r--r--  1 root  wheel    908 Jan  4 23:12 CLI/modules/help.py
-rw-r--r--  1 root  wheel   5913 Jan  4 23:12 CLI/modules/image.py
-rw-r--r--  1 root  wheel   6057 Jan  4 23:12 CLI/modules/iscsi.py
-rw-r--r--  1 root  wheel  20026 Jan  4 23:12 CLI/modules/loadbal.py
-rw-r--r--  1 root  wheel  16126 Jan  4 23:12 CLI/modules/messaging.py
-rw-r--r--  1 root  wheel   6261 Jan  4 23:12 CLI/modules/metadata.py
-rw-r--r--  1 root  wheel   1484 Jan  4 23:12 CLI/modules/nas.py
-rw-r--r--  1 root  wheel   3376 Jan  4 23:12 CLI/modules/rwhois.py
-rw-r--r--  1 root  wheel  39683 Jan  4 23:12 CLI/modules/server.py
-rw-r--r--  1 root  wheel   4582 Jan  4 23:12 CLI/modules/snapshot.py
-rw-r--r--  1 root  wheel   4757 Jan  4 23:12 CLI/modules/sshkey.py
-rw-r--r--  1 root  wheel   5185 Jan  4 23:12 CLI/modules/ssl.py
-rw-r--r--  1 root  wheel   9760 Jan  4 23:12 CLI/modules/subnet.py
-rw-r--r--  1 root  wheel   1240 Jan  4 23:12 CLI/modules/summary.py
-rw-r--r--  1 root  wheel   8155 Jan  4 23:12 CLI/modules/ticket.py
-rw-r--r--  1 root  wheel   5015 Jan  4 23:12 CLI/modules/vlan.py
-rw-r--r--  1 root  wheel  42378 Jan 17 23:43 CLI/modules/vs.py

Manager

SoftLayer CLIは、APIを抽象化して使いやすくしたManagerと呼ばれるクラスを使用して実装されています。

Managerで取得できない情報は当然CLIでも利用できません。そのような場合には、Managerでデータを取得している部分を少し変更すれば対応できます。具体的には、Managerの処理の中で必要なObject Maskを追加して、Reference Propertyが取得できるようにしてあげます。

utils.py

様々な共通の処理を簡単に実行できるように、共通の関数やクラスが定義されています。
ひとまず、深くネストされたdictionaryデータを簡単に検索するのに使われるlookup()を理解しておけばよいでしょう。

utils.py
def lookup(dic, key, *keys):
    """A generic dictionary access helper.

    This helps simplify code that uses heavily nested dictionaries. It will
    return None if any of the keys in *keys do not exist.

    ::

        >>> lookup({'this': {'is': 'nested'}}, 'this', 'is')
        nested

        >>> lookup({}, 'this', 'is')
        None

例えば以下の処理では、guestというVirtual_Guestオブジェクトのインスタンスに対して、Object Maskで取得されるRelational PropertiesをbillingItems -> orderItem -> order -> userRecord -> username という順にたどって、最終的にユーザー名を取得しています。

CLI/modules/vs.py
utils.lookup(guest, 'billingItem', 'orderItem', 'order', 'userRecord', 'username')

変更部分

managers/vs.py

  • VSmangerのlist_instance()で、location.pathStringをObject Maskに追加
managers/vs.py
$ diff -U 10 managers/vs.py.orig managers/vs.py
--- managers/vs.py.orig	2015-01-17 23:41:45.000000000 +0900
+++ managers/vs.py	2015-01-17 23:42:52.000000000 +0900
@@ -81,21 +81,22 @@
                 'fullyQualifiedDomainName',
                 'primaryBackendIpAddress',
                 'primaryIpAddress',
                 'lastKnownPowerState.name',
                 'powerState',
                 'maxCpu',
                 'maxMemory',
                 'datacenter',
                 'activeTransaction.transactionStatus[friendlyName,name]',
                 'status',
-                'billingItem.orderItem.order.userRecord[username]'
+                'billingItem.orderItem.order.userRecord[username]',
+                'location.pathString'
             ]
             kwargs['mask'] = "mask[%s]" % ','.join(items)

         call = 'getVirtualGuests'
         if not all([hourly, monthly]):
             if hourly:
                 call = 'getHourlyVirtualGuests'
             elif monthly:
                 call = 'getMonthlyVirtualGuests'

CLI/modules/vs.py

  • 表のヘッダにlocationフィールドを追加
  • lookup()でlocation.pathStringを取得
CLI/modules/vs.py
$ diff -U 10 CLI/modules/vs.py.orig CLI/modules/vs.py
--- CLI/modules/vs.py.orig	2015-01-04 23:12:47.000000000 +0900
+++ CLI/modules/vs.py	2015-01-18 00:58:01.000000000 +0900
@@ -87,34 +87,35 @@
                                     domain=args.get('--domain'),
                                     cpus=args.get('--cpu'),
                                     memory=args.get('--memory'),
                                     datacenter=args.get('--datacenter'),
                                     nic_speed=args.get('--network'),
                                     tags=tags)

         table = formatting.Table([
             'id', 'datacenter', 'host',
             'cores', 'memory', 'primary_ip',
-            'backend_ip', 'active_transaction', 'owner'
+            'backend_ip', 'location', 'active_transaction', 'owner'
         ])
         table.sortby = args.get('--sortby') or 'host'

         for guest in guests:
             guest = utils.NestedDict(guest)
             table.add_row([
                 guest['id'],
                 guest['datacenter']['name'] or formatting.blank(),
                 guest['fullyQualifiedDomainName'],
                 guest['maxCpu'],
                 formatting.mb_to_gb(guest['maxMemory']),
                 guest['primaryIpAddress'] or formatting.blank(),
                 guest['primaryBackendIpAddress'] or formatting.blank(),
+                utils.lookup(guest, 'location', 'pathString') or formatting.blank(),
                 formatting.active_txn(guest),
                 utils.lookup(guest, 'billingItem', 'orderItem', 'order',
                              'userRecord', 'username') or formatting.blank(),
             ])

         return table


 class VSDetails(environment.CLIRunnable):
     """

実行結果

$ sl vs list --sortby=location
:.........:............:............................:.......:........:.................:...............:.......................:....................:.....................:
:    id   : datacenter :             host           : cores : memory :    primary_ip   :   backend_ip  :        location       : active_transaction :        owner        :
:.........:............:............................:.......:........:.................:...............:.......................:....................:.....................:
: 6954216 :   hkg02    :      vyattama01.ibm.com    :   1   :   1G   :   119.81.xxx.x  :  10.110.2.210 :    hkg02.rk12.sl01    :         -          :   aaaa@jp.ibm.com   :
: 6030072 :   sng01    :    idera01.softlayer.com   :   1   :   2G   :   119.81.xx.xx  :  10.64.234.87 :    sng01.rk238.sl08   :         -          :  bbbbbbb@jp.ibm.com :
: 7688858 :   sng01    :    centos1.softlayer.com   :   1   :   1G   :  119.81.xxx.xxx :  10.64.234.79 :    sng01.rk238.sl17   :         -          :  bbbbbbb@jp.ibm.com :
: 7629262 :   tok02    :     tok01.softlayer.com    :   1   :   2G   :  161.202.xx.xx  :  10.132.2.216 : tok02.sr01.rk122.sl17 :         -          :  ccccccc@jp.ibm.com :
: 7642180 :   tok02    :    mywin01.softlayer.com   :   1   :   2G   :  161.202.xx.xx  :  10.132.2.213 : tok02.sr01.rk122.sl22 :         -          :  ccccccc@jp.ibm.com :
: 7684248 :   tok02    : docker-centos7.example.com :   1   :   1G   :  161.202.xx.xx  :  10.132.2.214 : tok02.sr01.rk126.sl21 :         -          : dddddddd@jp.ibm.com :
:.........:............:.............................:.......:........:.................:...............:.......................:....................:.....................:

簡単ですね。

データのRelational Propertyの関連がわかっていれば、同じように必要なObject Maskを追加して、lookup()で必要なデータを取得して表示することができます。

Relational Propertyの辿り方

今回の場合は、

という形で、データが関連付けられています。
この関連付けは、Data Typesからオブジェクトを検索してRelational Propertyを辿っていくことで確認できます。

Relational PropertyについてはShinobiLayer: SoftLayer API 次の一歩: データ型オブジェクト(2) - Qiitaが詳しいので、合わせて参照ください。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?