# -*- coding: utf-8 -*-
#
# VCP API SDK
#
import logging
import time
import pandas as pd
import json
from vcplib import occtr
from vcplib.occtr import vcp_df_color
from vcplib.occtr import set_privilege_mode
from vcplib.occtr import unset_privilege_mode
from vcpsdk.vcp_tools import merge_xxx_addresses, VcpSDKError
from vcpsdk.vcp_config_yaml import VcpConfigYaml
from vcpsdk.vcpsdk_config import VCP_SDK_VERSION
# plugins
from vcpsdk.plugins.aws import VcpSpecResourceAws
from vcpsdk.plugins.aws_disk import VcpSpecResourceAwsDisk
from vcpsdk.plugins.aws_spot import VcpSpecResourceAwsSpot
from vcpsdk.plugins.sakura import VcpSpecResourceSakura
from vcpsdk.plugins.sakura_disk import VcpSpecResourceSakuraDisk
from vcpsdk.plugins.oracle import VcpSpecResourceOracle
from vcpsdk.plugins.oracle_disk import VcpSpecResourceOracleDisk
from vcpsdk.plugins.proxmox import VcpSpecResourceProxmox
from vcpsdk.plugins.azure import VcpSpecResourceAzure
from vcpsdk.plugins.azure_disk import VcpSpecResourceAzureDisk
from vcpsdk.plugins.vmware import VcpSpecResourceVmware
from vcpsdk.plugins.aic import VcpSpecResourceAic
from vcpsdk.plugins.abc import VcpSpecResourceAbc
from vcpsdk.plugins.hokudai import VcpSpecResourceHokudai
from vcpsdk.plugins.mdx2 import VcpSpecResourceMdx2
from vcpsdk.plugins.mdx2_disk import VcpSpecResourceMdx2Disk
from vcpsdk.plugins.gcp import VcpSpecResourceGcp
from vcpsdk.plugins.onpremises import VcpSpecResourceOnpremises
from vcpsdk.plugins.chameleon import VcpSpecResourceChameleon
from vcpsdk.plugins.chameleon_ext import ( # noqa
VcpExtResourceChameleonNetwork,
VcpExtResourceChameleonHostLeaseInfo,
VcpExtResourceChameleon,
)
logger = logging.getLogger("vcp.sdk")
VCP_VAULT_SCHEME = "https"
#
# VCP SDK Spec Class
#
[ドキュメント]
class VcpSpecClass:
"""
VCP 各Cloud毎のResource(spec) 情報管理用
"""
def __init__(self, config_dir):
"""
Spec情報の初期化
:param config_dir: vcp_config.yml、vcp_flavor.yml ファイルの保存場所
:return: スペックリソースobject
"""
self._config_dir = config_dir
def class_(self, class_name):
return globals()[class_name]
[ドキュメント]
def find_spec(self, provider_name, flavor):
"""
プロバイダ名と、flavorからspec情報を生成
:param provider_name: real cloud provider名
:param flavor: フレーバー名(ex small, medium, large)
:return: スペックリソースobject
"""
spec = None
# CloudProvider名のSNAKE -> CHAMEL
words = provider_name.split("_")
resource_class_name = "".join(x.capitalize() for x in words)
class_name = "VcpSpecResource{}".format(resource_class_name)
if class_name in globals():
spec = self.class_(class_name)(provider_name, flavor, self._config_dir)
else:
# 存在しないflavor
VcpSDKError(
"no flavor provider_name[{}] flavor[{}]".format(provider_name, flavor)
)
return spec
#
# VCP SDK Ext Class
#
[ドキュメント]
class VcpExtClass:
"""
VCP 各Cloud毎のExt 情報管理用
"""
def __init__(self, config_dir, vcc_access_token):
"""
Ext情報の初期化
:param config_dir: vcp_config.yml、vcp_flavor.yml ファイルの保存場所
:param vcc_access_token: VC Controller/ Vault 用アクセストークン
:return: スペックリソースobject
"""
self._config_dir = config_dir
self._vcc_access_token = vcc_access_token
def class_(self, class_name):
return globals()[class_name]
[ドキュメント]
def find_extension(self, provider_name):
"""
プロバイダ名からextension情報を生成
:param provider_name: real cloud provider名
:return: VcpExtResource Object
"""
extension = None
# CloudProvider名のSNAKE -> CHAMEL
words = provider_name.split("_")
resource_class_name = "".join(x.capitalize() for x in words)
class_name = "VcpExtResource{}".format(resource_class_name)
if class_name in globals():
extension = self.class_(class_name)(
provider_name, self._config_dir, self._vcc_access_token
)
else:
# 存在しないextension
VcpSDKError("no extension provider_name[{}]".format(provider_name))
return extension
#
# VCP SDK unit&node Class(vcplib::VcUnit & vcplib::VcNode相当)
#
[ドキュメント]
class VcpUnitClass:
"""
VcpUnitクラス(VCP Lib::VcUnit & VCP Lib::VcNode相当)
サンプルコード
.. code-block:: python
...
ugroup = sdk.create_ugroup('UnitGroup名', 'compute|storage')
unit = ugroup.create_unit('Unit名', spec)
# Unit内のnodeをpower off
unit.power_off_nodes()
# Unit内のnodeをpower on
unit.power_on_nodes()
# Node追加
unit.add_nodes(ノード数)
# Node削除
unit.delete_nodes(ノード数)
# Node情報出力
unit.df_nodes()
# Node情報取得
ips = unit.find_ip_adresses()
nodes = unit.find_nodes()
"""
def __init__(self, ugroup, unit):
"""
VcpUnit
:param vc: 既存VCP Lib::Vc情報
"""
self._unit = unit
self._wait_timeout_sec = ugroup._wait_timeout_sec
@property
def name(self):
"""
VCP Lib::VcUnit の name
"""
return self._unit.name
@property
def state(self):
"""
VCP Lib::VcUnit の state
"""
return self._unit.state
[ドキュメント]
def watch(self, wait_for=True):
"""
Unit監視開始
:param wait_for: nodeの削除待ち条件(True: 待つ)
.. note::
power_on_nodes() の利用を推奨
"""
self._unit.watch()
# waiting wakeup
if wait_for is True:
self.wait_nodes_applied()
logger.info("watching successe.")
[ドキュメント]
def unwatch(self):
"""
Unit監視停止
.. note::
power_off_nodes() の利用を推奨
"""
self._unit.unwatch()
[ドキュメント]
def df_nodes(self, privileged=False):
"""
node一覧(DataFrame形式)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
"""
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# DataFrame出力
dfs = self._unit.nodes_df()
unset_privilege_mode(privileged=privileged)
return vcp_df_color(dfs)
[ドキュメント]
def find_nodes(
self,
node_id="",
node_state="",
node_no="",
ip_addresses=[],
ip_address=None,
cloud_instance_id=None,
mapper=None,
privileged=False,
):
"""
検索条件にマッチするnode検索
:param node_id: 検索条件node_id
:param node_state: 検索条件node_state
:param node_no: 検索条件node_no
:param ip_addresses: 検索条件cloud_instance_addresses
:param ip_address: 検索条件cloud_instance_address
:param cloud_instance_id: 検索条件cloud_instance_id
:param mapper: 検索結果のnodeに適用する関数
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: node情報(vcplib::VcNode配列)
.. note::
* ip_address と ip_addresses を両方指定すると和集合として扱う
* 検索条件指定が複数あれば、AND条件とする
* 複数nodeの場合、node_no の昇順にsortした結果を返す
"""
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# ip_addresses 指定をmergeしておく
ip_addr_conditions = merge_xxx_addresses(ip_address, ip_addresses)
# 条件に一致するnode を検索
nodes = [
node if mapper is None else mapper(node)
for node in self._unit.nodes
if (node_id == "" or node.id == node_id)
and (node_state == "" or node.state == node_state)
and (node_no == "" or node.no == node_no)
and (
len(ip_addr_conditions) == 0
or node.cloud_instance_address in ip_addr_conditions
)
and (
cloud_instance_id is None or node.cloud_instance_id == cloud_instance_id
)
]
unset_privilege_mode(privileged=privileged)
# node_no 順にsort
return sorted(nodes, key=lambda x: x.no)
def find_ip_addresses(self, privileged=False, **conditions):
"""
検索条件にマッチするnodeのIPアドレスリストを返す
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: IPアドレス(配列)
.. note::
* パラメータは、find_nodes() からmapperを除いたもの
"""
set_privilege_mode(privileged)
nodes = self.find_nodes(privileged=privileged, **conditions)
unset_privilege_mode(privileged=privileged)
return list(map(lambda node: node.cloud_instance_address, nodes))
[ドキュメント]
def add_nodes(
self,
num_add_nodes=1,
ip_addresses=[],
ip_address=None,
mac_addresses=[],
mac_address=None,
wait_for=True,
verbose=0,
privileged=False,
):
"""
Nodeの追加
:param num_add_nodes: 追加起動Node数
:param ip_addresses: 追加起動するNodeのIPアドレス(配列)
:param ip_address: 追加起動するNodeのIPアドレス
:param mac_addresses: 追加起動するNodeのMACアドレス(配列)
:param mac_address: 追加起動するNodeのMACアドレス
:param wait_for: nodeの起動待ち条件(True: 待つ)
:param verbose: verbose=0 でverboseなし
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: node情報(vcplib::VcNode配列)
.. note::
* ip_address と ip_addresses を両方指定すると和集合として扱う
* ip_address と ip_addresses を storageタイプのunitに指定するとエラーとする
* ip_addresses, ip_address のいずれかを指定した場合、num_add_nodes を無視する
"""
# 引数チェック
if isinstance(ip_addresses, list) is False:
VcpSDKError("ip_addresses is not list")
if isinstance(mac_addresses, list) is False:
VcpSDKError("mac_addresses is not list")
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# vc_typeのチェック
vc_type = self._unit.vc.type
if vc_type == "storage" and (len(ip_addresses) != 0 and ip_address is not None):
VcpSDKError("can't set ip_address(es) to storage")
# node追加
ip_address_list = merge_xxx_addresses(ip_address, ip_addresses)
mac_address_list = merge_xxx_addresses(mac_address, mac_addresses)
self._unit.add_node(num_add_nodes, ip_address_list, mac_address_list)
# node追加完了待ち
if wait_for is True:
self.wait_nodes_applied()
logger.info("add_node completed.")
new_nodes = self.find_nodes(privileged=None)
unset_privilege_mode(privileged=privileged)
return new_nodes
def check_search_cond_(
self, num_nodes, node_no, cloud_instance_id, ip_addresses, ip_address, wait_for
):
"""
Node の検索条件指定チェック
"""
vals = [num_nodes, node_no, cloud_instance_id, ip_addresses, ip_address]
none_num = vals.count(None)
valid_arg_num = len(vals) - none_num
# 検索条件が2個以上かチェック
if valid_arg_num != 0 and valid_arg_num != 1:
VcpSDKError("invalid argment, one condition parameter allowed")
# 検索条件がない場合、num_nodes=1
if valid_arg_num == 0:
num_nodes = 1
if wait_for is not True:
# 複数nodeを削除するのにwait_for=False ならエラー
# (power off自体は1個ずつ)
if (num_nodes is not None and num_nodes > 1) or (
ip_addresses is not None and len(ip_addresses) > 1
):
VcpSDKError("invalid argment, delete multi-node must be wait_for=True")
# 対象VcNode個数
return num_nodes
[ドキュメント]
def delete_nodes(
self,
num_delete_nodes=None,
node_no=None,
cloud_instance_id=None,
ip_addresses=None,
ip_address=None,
wait_for=True,
verbose=0,
privileged=False,
):
"""
検索条件にマッチするNode削除
:param num_delete_nodes: 削除対象Node最大数
:param node_no: 検索条件node_no
:param cloud_instance_id: 検索条件cloud_instance_id
:param ip_addresses: 検索条件cloud_instance_address(配列)
:param ip_address: 検索条件cloud_instance_address
:param wait_for: nodeの削除待ち条件(True: 待つ)
:param verbose: verbose=0 でverboseなし
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: node情報(vcplib::VcNode配列)
.. note::
* 検索条件は、最大1個のみ指定可能
* 検索条件未指定の場合は、num_delete_nodes=1 のみ指定と同様
* wait_for=False の場合、複数nodeの削除はできない。(node削除は1個ずつ)
"""
# 引数チェック
num_delete_nodes = self.check_search_cond_(
num_delete_nodes,
node_no,
cloud_instance_id,
ip_addresses,
ip_address,
wait_for,
)
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# 検索条件にマッチしたnodeを返す
ip_addr_conditions = merge_xxx_addresses(ip_address, ip_addresses)
# 対象となるnodeを削除
deleted_num = 0
for node in self._unit.nodes:
if num_delete_nodes is not None and deleted_num >= num_delete_nodes:
break
if (
(node_no is None or node.no == node_no)
and (
cloud_instance_id is None
or node.cloud_instance_id == cloud_instance_id
)
and (
len(ip_addr_conditions) == 0
or node.cloud_instance_address in ip_addr_conditions
)
):
# nodeを削除
node.delete()
# node削除待ち
self.wait_nodes_applied()
logger.info("a node deleted.")
deleted_num += 1
if deleted_num > 0:
logger.info("deleted node(s) completed.")
new_nodes = self.find_nodes(privileged=None)
unset_privilege_mode(privileged=privileged)
return new_nodes
[ドキュメント]
def watch_nodes(
self,
num_watch_nodes=None,
node_no=None,
cloud_instance_id=None,
ip_addresses=None,
ip_address=None,
wait_for=True,
privileged=False,
verbose=0,
):
"""
検索条件にマッチするNodeの監視開始
:param num_watch_nodes: watch対象Node最大数
:param node_no: 検索条件node_no
:param cloud_instance_id: 検索条件cloud_instance_id
:param ip_addresses: 検索条件cloud_instance_address(配列)
:param ip_address: 検索条件cloud_instance_address
:param wait_for: nodeの監視開始待ち条件(True: 待つ)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:param verbose: verbose=0 でverboseなし
:return: node情報(vcplib::VcNode配列)
.. note::
* power_off_nodes の利用を推奨
"""
# 引数チェック
num_watch_nodes = self.check_search_cond_(
num_watch_nodes,
node_no,
cloud_instance_id,
ip_addresses,
ip_address,
wait_for,
)
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# 検索条件にマッチしたnodeを返す
ip_addr_conditions = merge_xxx_addresses(ip_address, ip_addresses)
# 対象となるnodeを監視開始
watched_num = 0
for node in self._unit.nodes:
if num_watch_nodes is not None and watched_num >= num_watch_nodes:
break
if (
(node_no is None or node.no == node_no)
and (
cloud_instance_id is None
or node.cloud_instance_id == cloud_instance_id
)
and (
len(ip_addr_conditions) == 0
or node.cloud_instance_address in ip_addr_conditions
)
):
# nodeを監視開始
node.watch()
# nodeのRUNNING待ち
self.wait_nodes_applied()
logger.info("a node watching start.")
watched_num += 1
if watched_num > 0:
logger.info("watching node(s) has started.")
new_nodes = self.find_nodes(privileged=None)
unset_privilege_mode(privileged=privileged)
return new_nodes
[ドキュメント]
def unwatch_nodes(
self,
num_watch_nodes=None,
node_no=None,
cloud_instance_id=None,
ip_addresses=None,
ip_address=None,
privileged=False,
verbose=0,
):
"""
検索条件にマッチするNodeの監視停止
:param num_watch_nodes: unwatch対象Node最大数
:param node_no: 検索条件node_no
:param cloud_instance_id: 検索条件cloud_instance_id
:param ip_addresses: 検索条件cloud_instance_address(配列)
:param ip_address: 検索条件cloud_instance_address
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:param verbose: verbose=0 でverboseなし
:return: node情報(vcplib::VcNode配列)
.. note::
* power_on_nodes の利用を推奨
"""
# 引数チェック
num_watch_nodes = self.check_search_cond_(
num_watch_nodes, node_no, cloud_instance_id, ip_addresses, ip_address, False
)
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# 検索条件にマッチしたnodeを返す
ip_addr_conditions = merge_xxx_addresses(ip_address, ip_addresses)
# 対象となるnodeを監視停止
watched_num = 0
for node in self._unit.nodes:
if num_watch_nodes is not None and watched_num >= num_watch_nodes:
break
if (
(node_no is None or node.no == node_no)
and (
cloud_instance_id is None
or node.cloud_instance_id == cloud_instance_id
)
and (
len(ip_addr_conditions) == 0
or node.cloud_instance_address in ip_addr_conditions
)
):
# nodeを監視停止
node.unwatch()
watched_num += 1
if watched_num > 0:
logger.info("unwatch node(s) completed.")
new_nodes = self.find_nodes(privileged=None)
unset_privilege_mode(privileged=privileged)
return new_nodes
[ドキュメント]
def power_off_nodes(
self,
num_power_off_nodes=None,
node_no=None,
cloud_instance_id=None,
ip_addresses=None,
ip_address=None,
wait_for=True,
privileged=False,
verbose=0,
):
"""
検索条件にマッチするNodeのInstanceのpower off
:param num_power_off_nodes: power off対象Node最大数
:param node_no: 検索条件node_no
:param cloud_instance_id: 検索条件cloud_instance_id
:param ip_addresses: 検索条件cloud_instance_address(配列)
:param ip_address: 検索条件cloud_instance_address
:param wait_for: nodeの監視開始待ち条件(True: 待つ)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:param verbose: verbose=0 でverboseなし
:return: node情報(vcplib::VcNode配列)
.. note::
* 検索条件は、最大1個のみ指定可能
* 検索条件未指定の場合は、num_power_off_nodes=1 のみ指定と同様
* wait_for=False の場合、複数nodeのpower offはできない。(node power offは1個ずつ)
"""
# 引数チェック
num_power_off_nodes = self.check_search_cond_(
num_power_off_nodes,
node_no,
cloud_instance_id,
ip_addresses,
ip_address,
wait_for,
)
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# 検索条件にマッチしたnodeを返す
ip_addr_conditions = merge_xxx_addresses(ip_address, ip_addresses)
# 対象となるnodeを監視開始
power_off_num = 0
for node in self._unit.nodes:
if num_power_off_nodes is not None and power_off_num >= num_power_off_nodes:
break
if (
(node_no is None or node.no == node_no)
and (
cloud_instance_id is None
or node.cloud_instance_id == cloud_instance_id
)
and (
len(ip_addr_conditions) == 0
or node.cloud_instance_address in ip_addr_conditions
)
):
# nodeをpower off
node.power_off()
# nodeのRUNNING待ち
self.wait_nodes_applied()
logger.info("a node power off start.")
power_off_num += 1
if power_off_num > 0:
logger.info("power off node(s) has started.")
new_nodes = self.find_nodes(privileged=None)
unset_privilege_mode(privileged=privileged)
return new_nodes
[ドキュメント]
def power_on_nodes(
self,
num_power_on_nodes=None,
node_no=None,
cloud_instance_id=None,
ip_addresses=None,
ip_address=None,
wait_for=True,
privileged=False,
verbose=0,
):
"""
検索条件にマッチするNodeのInstanceのpower on
:param num_power_on_nodes: power on対象Node最大数
:param node_no: 検索条件node_no
:param cloud_instance_id: 検索条件cloud_instance_id
:param ip_addresses: 検索条件cloud_instance_address(配列)
:param ip_address: 検索条件cloud_instance_address
:param wait_for: nodeの監視開始待ち条件(True: 待つ)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:param verbose: verbose=0 でverboseなし
:return: node情報(vcplib::VcNode配列)
.. note::
* 検索条件は、最大1個のみ指定可能
* 検索条件未指定の場合は、num_power_on_nodes=1 のみ指定と同様
* wait_for=False の場合、複数nodeのpower onはできない。(node power onは1個ずつ)
"""
# 引数チェック
num_power_on_nodes = self.check_search_cond_(
num_power_on_nodes,
node_no,
cloud_instance_id,
ip_addresses,
ip_address,
wait_for,
)
set_privilege_mode(privileged)
# 自分のunit情報更新
self._unit.config()
# 検索条件にマッチしたnodeを返す
ip_addr_conditions = merge_xxx_addresses(ip_address, ip_addresses)
# 対象となるnodeを監視開始
power_on_num = 0
for node in self._unit.nodes:
if num_power_on_nodes is not None and power_on_num >= num_power_on_nodes:
break
if (
(node_no is None or node.no == node_no)
and (
cloud_instance_id is None
or node.cloud_instance_id == cloud_instance_id
)
and (
len(ip_addr_conditions) == 0
or node.cloud_instance_address in ip_addr_conditions
)
):
# nodeをpower on
node.power_on()
# nodeのRUNNING待ち
self.wait_nodes_applied()
logger.info("a node power on start.")
power_on_num += 1
if power_on_num > 0:
logger.info("power on node(s) has started.")
new_nodes = self.find_nodes(privileged=None)
unset_privilege_mode(privileged=privileged)
return new_nodes
def wait_nodes_applied(self):
"""
自unit内のnodeへの操作が終わるまで待つ
"""
state = None
is_complete = False
num_of_retry = int(self._wait_timeout_sec / 5)
for retry_no in range(num_of_retry):
# 自分のunit情報更新
self._unit.config()
is_stability = True
if self._unit.state in [
"BOOTING",
"STOPPING",
"SUSPENDING",
"RESUMING",
"DELETING",
"SHUTTING_DOWN",
]:
is_stability = False
if self._unit.state == "INDEFINITE":
# unit 内のnodeの状態が安定しているかチェック
for node in self.find_nodes(privileged=None):
if node.state in [
"BOOTING",
"STOPPING",
"SUSPENDING",
"RESUMING",
"DELETING",
"SHUTTING_DOWN",
]:
is_stability = False
break
if is_stability is False:
logger.info("%s ... %d sec" % (self._unit.state, retry_no * 5))
time.sleep(5)
continue
is_complete = True
state = self._unit.state
break
logger.info("unit {} is {}".format(self._unit.name, self._unit.state))
if state == "ERROR":
# エラー表示にVC情報を出力
logger.error(self._unit.error())
elif is_complete is False:
# 待ち時間いっぱい
VcpSDKError("Full of waiting time")
def __str__(self):
"""
Unit情報(Unit)
"""
return str(self._unit)
#
# VCP UnitGroup Class
#
[ドキュメント]
class VcpUnitGroupClass:
"""
VcpUnitGroupClassクラス(VCLIB::Vc相当)
サンプルコード
.. code-block:: python
# 初期化
sdk = VcpSDK('アクセストークン',
config_dir="vcp_config.yml, vcp_flavor.yml のdirectory")
spec = sdk.get_spec('プロバイダ名', 'flavor名')
# UnitGroup作成
ugroup = sdk.create_ugroup('UnitGroup名', 'compute|storage')
# Unit作成
unit = ugroup.create_unit('Unit名', spec)
# Unit削除
ugroup.delete_units('Unit名')
# 各種情報出力
ugroup.df_units()
ugroup.df_nodes()
# 各種情報取得
ips = ugroup.find_ip_address()
units = ugroup.find_units()
unit = ugroup.get_unit('Unit名')
nodes = ugroup.find_nodes()
# UnitGroup削除
ugroup.cleanup()
# UnitGroupの所有者変更
ugroup.change_owner("new_owner")
"""
def __init__(self, vc=None, vcp_config=""):
"""
VcpUnitGroupClass
:param vc: 既存vcplib::Vc情報
:param config_dir: vcp_config.yml のdirname
"""
self._vc = vc
# VcNodeの起動、操作待ち時間の調整
self._wait_timeout_sec = 1000 # 1000sec = 15minutes
self._vcp_config = vcp_config
if "wait_timeout_sec" in self._vcp_config["vcc"]:
self._wait_timeout_sec = self._vcp_config["vcc"]["wait_timeout_sec"]
@property
def state(self):
"""
vcplib::Vcの state
"""
return self._vc.state
@property
def owner(self):
"""
vcplib::Vcの owner
"""
return self._vc.owner
@property
def name(self):
"""
Unit groupの名前を取得する
"""
# 必要な場合は外側で_vc.config() を呼び出しているという前提
return self._vc.name
@name.setter
def name(self, v):
"""
Unit groupの名前を更新する
:param v: Unit groupの名前
"""
# 現在の名前と異なる場合のみ変更処理を行う
self._vc.config()
if self.name != v:
self._update_name(v)
[ドキュメント]
def create_unit(self, unit_name, spec, wait_for=True, privileged=False, verbose=-1):
"""
Unit作成
:param unit_name: 起動Unit名
:param spec: 起動spec情報
:param wait_for: nodeの起動待ち条件(True: 待つ)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:param verbose: verbose=0 でverboseなし
:return: Unit情報(vcpsdk::VcpUnit)
"""
if self._vc is None:
VcpSDKError("no yet setup unit_group")
set_privilege_mode(privileged)
# unit_name(unit名) が既存かチェック
vcp_units = self.find_units(unit_name=unit_name)
if len(vcp_units) > 0:
VcpSDKError("already exist unit[{}]".format(unit_name))
# unit の type と spec の typeが合致するかチェック compute|storage
if self._vc.type != spec.unit_type:
VcpSDKError(
"not much ugroup_type vc[{}] and spec[{}]".format(
self._vc.type, spec.unit_type
)
)
# CCIの生成
my_cci = spec.cci(unit_name)
# Unit追加
result = self._vc.add_unit(unit_name, my_cci)
if result is False:
VcpSDKError("can't create unit")
# VC情報更新
self._vc.config()
# node追加完了待ち
if wait_for is True:
self.wait_unit_applied(unit_name=unit_name)
# 作成したunitを返す
vcp_units = self.find_units(unit_name=unit_name)
unset_privilege_mode(privileged=privileged)
# 1回1個なので先頭の1個を返す
return vcp_units[0]
[ドキュメント]
def delete_units(
self, unit_name, wait_for=True, force=False, privileged=False, verbose=0
):
"""
検索条件にマッチするUnit削除
:param name: 検索条件Unit名
:param wait_for: nodeの削除待ち条件(True: 待つ)
:param force: force=Trueで、配下にnodeが存在してもnode毎削除する
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:param verbose: verbose=0 でverboseなし
"""
set_privilege_mode(privileged)
# VC情報更新
self._vc.config()
# 指定unit名に対応するunitがなければなにもしない
vcp_units = self.find_units(unit_name=unit_name)
if len(vcp_units) == 0:
VcpSDKError("no unit unit_name[{}]".format(unit_name))
# 対象となる Unitを削除
vcp_units[0]._unit.delete(force=force)
# unit削除待ち
if wait_for is True:
self.wait_unit_applied(unit_name)
logger.info("delete_unit completed.")
unset_privilege_mode(privileged=privileged)
def wait_unit_applied(self, unit_name):
"""
指定unitがbooting以外になるまで待つ
:param unit_name: Unit名
"""
state = None
is_complete = False
num_of_retry = int(self._wait_timeout_sec / 5)
for retry_no in range(num_of_retry):
# 処理中のサーバをチェック
vcp_units = self.find_units(unit_name)
if len(vcp_units) == 0:
is_complete = True
break
# unitは、1つのunit_group内でuniq
unit = vcp_units[0]._unit
if unit.state in [
"BOOTING",
"STOPPING",
"SUSPENDING",
"RESUMING",
"DELETING",
"SHUTTING_DOWN",
"INDEFINITE",
]:
logger.info("%s ... %d sec" % (unit.state, retry_no * 5))
time.sleep(5)
continue
state = unit.state
is_complete = True
break
if state != "ERROR":
# 連続起動の待ち
time.sleep(6)
logger.info("unit %s is %s" % (unit_name, state))
if state == "ERROR":
# エラー表示にVC情報を出力
logger.error(self._vc)
VcpSDKError("failed ({})".format(unit_name))
elif is_complete is False:
# 待ち時間いっぱい
VcpSDKError("Full of waiting time ({})".format(unit_name))
[ドキュメント]
def df_units(self, privileged=False):
"""
unit一覧(DataFrame形式)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
"""
set_privilege_mode(privileged)
# VC情報更新
self._vc.config()
unset_privilege_mode(privileged=privileged)
return self._vc.units_df()
[ドキュメント]
def df_nodes(self, privileged=False):
"""
node一覧(DataFrame形式)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
"""
set_privilege_mode(privileged)
# VC情報更新
self._vc.config()
# DataFrame出力
dfs = []
for vcp_unit in self._vc.units:
if len(vcp_unit.nodes) > 0:
dfs.append(vcp_unit.nodes_df())
unset_privilege_mode(privileged=privileged)
return vcp_df_color(dfs)
[ドキュメント]
def find_units(self, unit_name="", privileged=False):
"""
検索条件にマッチするunit検索
:param unit_name: 検索条件Unit名
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: VcpUnit情報
.. note::
* 検索条件指定がない場合、UnitGroup内の全てのUnitを返す
"""
set_privilege_mode(privileged)
# VC情報更新
self._vc.config()
# 対象のUnitGroupを設定
vcp_units = []
for unit in self._vc.units:
if unit_name == "" or unit.name == unit_name:
vcp_units.append(VcpUnitClass(self, unit))
unset_privilege_mode(privileged=privileged)
return vcp_units
[ドキュメント]
def get_unit(self, unit_name, privileged=False):
"""
unit名を指定してunit取得
:param unit_name: ユニット名
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: Unit情報(vcpsdk::VcpUnitClass)
"""
set_privilege_mode(privileged)
# 既存のunitをunit_nameで検索して、最初に見つかったunit
units = self.find_units(unit_name=unit_name)
unset_privilege_mode(privileged=privileged)
if len(units) > 0:
return units[0]
else:
return None
def create_empty_vc(self, ugroup_name, ugroup_type):
"""
空のVCを作成する
:param ugroup_name: UnitGroup名
:return: Vc情報
"""
#
# VC作成
[ドキュメント]
def find_nodes(
self,
unit_name="",
node_id="",
node_state="",
node_no="",
ip_addresses=[],
ip_address=None,
cloud_instance_id=None,
mapper=None,
privileged=False,
):
"""
検索条件にマッチするnode検索
:param unit_name: 検索条件unit名
:param node_id: 検索条件node_id
:param node_state: 検索条件node_state
:param node_no: 検索条件node_no
:param ip_addresses: 検索条件cloud_instance_addresses(配列)
:param ip_address: 検索条件cloud_instance_address
:param cloud_instance_id: 検索条件cloud_instance_id
:param mapper: 検索結果のnodeに適用する関数
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: node情報(vcplib::VcNode配列)
.. note::
* ip_address と ip_addresses を両方指定すると和集合として扱う
* 検索条件指定が複数あれば、AND条件とする
"""
set_privilege_mode(privileged)
# 自分のunit情報更新
self._vc.config()
# 検索条件にマッチしたnodeを返す
ip_addr_conditions = merge_xxx_addresses(ip_address, ip_addresses)
unset_privilege_mode(privileged=privileged)
return [
node if mapper is None else mapper(node)
for unit in self._vc.units
for node in unit.nodes
if (unit_name == "" or unit.name == unit_name)
and (node_id == "" or node.id == node_id)
and (node_state == "" or node.state == node_state)
and (node_no == "" or node.no == node_no)
and (
len(ip_addr_conditions) == 0
or node.cloud_instance_address in ip_addr_conditions
)
and (
cloud_instance_id is None or node.cloud_instance_id == cloud_instance_id
)
]
def find_ip_addresses(self, privileged=False, **conditions):
"""
検索条件にマッチするnodeのIPアドレスリストを返す
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: IPアドレス(配列)
.. note::
* パラメータは、find_nodes() と同じ
"""
set_privilege_mode(privileged)
return self.find_nodes(
**conditions,
mapper=lambda node: node.cloud_instance_address,
privileged=None
)
unset_privilege_mode(privileged=privileged)
[ドキュメント]
def change_owner(self, new_owner, privileged=False):
"""
VCの所有者変更
:param new_owner: 新しい所有者
"""
set_privilege_mode(privileged)
if self._vc:
result = self._vc.change_owner(new_owner)
if result is False:
VcpSDKError(
"failed ugroup change owner http status({})".format(
self._vc.last_error_http_status
)
)
unset_privilege_mode(privileged=privileged)
[ドキュメント]
def cleanup(self, wait_for=True, privileged=False):
"""
VC初期化(Vc配下の全てのUnitとNodeを削除)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:param wait_for: nodeの削除待ち条件(True: 待つ)
"""
set_privilege_mode(privileged)
if self._vc:
result = self._vc.delete(force=True)
if result is False:
VcpSDKError(
"failed ugroup cleanup http status({})".format(
self._vc.last_error_http_status
)
)
if wait_for is True:
self.wait_cleanup()
logger.info(
"cleanup completed. vc {} is cleanup(no unit)".format(self._vc.name)
)
unset_privilege_mode(privileged=privileged)
self._vc = None
def wait_cleanup(self):
"""
自分のvc内の全てのunitが消えるまで待つ
"""
if self._vc:
is_end = False
num_of_retry = int(self._wait_timeout_sec / 5)
for retry_no in range(num_of_retry):
# VC状態を更新
result = self._vc.config()
if result is False:
# VCの削除が完了
is_end = True
break
if len(self._vc.units) == 0:
is_end = True
break
# unit がまだある
status_units = []
is_exist_not_error = False
for unit in self._vc.units:
status_units.append("%s is %s" % (unit.name, unit.state))
# 状態遷移の完了状態
# - エラー
# - Instanceがmount済みで削除できないDiskがRUNNING状態になった
if unit.state != "ERROR" and not (
self._vc.type == "storage" and unit.state == "RUNNING"
):
# まだ処理中のunitがある
is_exist_not_error = True
logger.info("%s ... %d sec" % ("\n".join(status_units), retry_no * 5))
if is_exist_not_error is True:
time.sleep(5)
continue
break
if is_end is False:
VcpSDKError("not completed!!!")
def _update_name(self, name, group_type="compute"):
"""
UnitGroup名を変更する
:param name: UnitGroup名
:param group_type: compute | storage
"""
cci = VcpSDK.empty_cci(name, ugroup_type=group_type)
self._vc.update(cci)
def __str__(self):
"""
UnitGroup情報(VC)
"""
return str(self._vc)
@staticmethod
def empty_cci(ugroup_name, ugroup_type="compute"):
"""
空のVC用CCIを作成
:param ugroup_name: unitGroup名
:param ugroup_type: compute | storage
:return: CCI文字列
"""
my_cci = """
- vc:
cci_version: "{cci_version}"
type: {ugroup_type}
description: "{ugroup_name}"
name: {ugroup_name}""".format(
ugroup_type=ugroup_type,
cci_version=VCP_SDK_VERSION,
ugroup_name=ugroup_name,
)
return my_cci
[ドキュメント]
def update_ugroup_name(self, ugroup_name, ugroup_type="compute", privileged=False):
"""
UnitGroup名を設定
:param ugroup_name: unitGroup名
:param ugroup_type: compute | storage
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
"""
set_privilege_mode(privileged)
if self._vc:
my_cci = VcpUnitGroupClass.empty_cci(ugroup_name, ugroup_type)
self._vc.update(my_cci)
unset_privilege_mode(privileged=privileged)
#
# VCP SDK BASE Class
#
[ドキュメント]
class VcpSDK:
"""
VCP SDKベースクラス
サンプルコード
.. code-block:: python
# 初期化(confi_dir省略時は、 `/notebooks/notebook/vcp_config` )
sdk = VcpSDK('アクセストークン',
config_dir="vcp_config.yml, vcp_flavor.yml のdirectory")
# バージョン情報
sdk.version()
# フレーバー情報
sdk.df_flavors('プロバイダ名')
# vaultやdocker registory のurl情報
sdk.vcc_info()
# spec作成
spec = sdk.get_spec('プロバイダ名', 'flavor名')
# UnitGroup情報出力
sdk.df_ugroups()
# UnitGroup情報取得
ugroups = sdk.find_ugroups()
ugroup = sdk.get_ugroup('UnitGroup名')
# 既存サーバ用 ssh 公開鍵取得
sdk.get_publickey()
# UnitGroupの作成
ugroup = sdk.create_ugroup('UnitGroup名', 'compute|storage')
"""
def __init__(self, vcc_access_token="", config_dir="", verbose=0):
self._vcc_access_token = vcc_access_token
self._config_dir = config_dir
#
# vcpsdk の初期パラメータ設定
# - config/vcp_config.yml
# - config/vcp_flavor.yml
#
vcy = VcpConfigYaml(config_dir)
self._vcp_config = vcy.load("vcp_config")
# VCP Lib初期化
vcc_host = self._vcp_config["vcc"]["host"]
if "vcc_port" in self._vcp_config["vcc"]:
vcc_host = "{}:{}".format(vcc_host, self._vcp_config["vcc"]["vcc_port"])
# SSL insecure request warning 表示設定
insecure_request_warning = True # 表示
if "insecure_request_warning" in self._vcp_config["vcc"]:
insecure_request_warning = self._vcp_config["vcc"][
"insecure_request_warning"
]
self._oc = occtr.Occtr(
self._vcc_access_token,
vcc_host=vcc_host,
insecure_request_warning=insecure_request_warning,
verbose=verbose,
)
if not self._oc:
VcpSDKError("initialize occtr failed")
# 認証チェック
self.authority()
[ドキュメント]
def authority(self):
"""
authority 情報の取得
結果サンプル
.. code-block:: none
{
'role': 'fullaccess',
'user_name': 'nobody',
'user_role': 'regular'
}
:return: authority情報
"""
return json.loads(self._oc.authority())
@property
def verbose(self):
"""
VCP Lib:verbose
"""
return self._oc.verbose
@verbose.setter
def verbose(self, verbose):
"""
VCP Lib:verbose 設定
"""
self._oc.verbose = verbose
@property
def config_dir(self):
"""
config ファイルのディレクトリ
"""
return self._config_dir
@config_dir.setter
def config_dir(self, config_dir):
"""
config ファイルのディレクトリ設定
VCP Lib:verbose 設定
"""
self._config_dir = config_dir
[ドキュメント]
def get_spec(self, provider_name, flavor):
"""
Spec情報の取得
:param provider_name: プロバイダ名
:param flavor: small, medium, large などのfalvor文字列
:return: SPECのリソース情報(vcpsdk::VcpSpecResource)
"""
spec = VcpSpecClass(self._config_dir)
return spec.find_spec(provider_name, flavor)
[ドキュメント]
def get_extension(self, provider_name):
"""
extension(plugin拡張項目)情報の取得
:param provider_name: プロバイダ名
:return: extensionのリソース情報(vcpsdk::VcpExtResource)
"""
ext = VcpExtClass(self._config_dir, self._vcc_access_token)
return ext.find_extension(provider_name)
[ドキュメント]
def create_ugroup(self, ugroup_name, ugroup_type="compute", privileged=False):
"""
UnitGroupの作成
:param ugroup_name: vc名
:param ugroup_type: vcタイプ compute|storage
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: UnitGroup情報(vcpsdk::VcpUnitGroupClass)
"""
set_privilege_mode(privileged)
# 既存のvcをugroup_nameで検索
ugs = self.find_ugroups(ugroup_name=ugroup_name)
if len(ugs) > 0:
# 既存エラー
VcpSDKError("aleady exist UnitGroup. change name or cleanup first!")
# 新規UnitGroupの作成
vc = self.create_empty_vc(ugroup_name, ugroup_type)
ug = VcpUnitGroupClass(vc, vcp_config=self._vcp_config)
unset_privilege_mode(privileged=privileged)
return ug
[ドキュメント]
def df_ugroups(self, privileged=False):
"""
UnitGroup 一覧(DataFrame)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
"""
set_privilege_mode(privileged)
self._oc.config()
unset_privilege_mode(privileged=privileged)
return self._oc.vcs_df()
[ドキュメント]
def df_nodes(self, privileged=False):
"""
All node一覧(DataFrame形式)
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
"""
set_privilege_mode(privileged)
self._oc.config()
dfs = []
for vc in self._oc.vcs:
for unit in vc.units:
if len(unit.nodes) > 0:
dfs.append(unit.nodes_df())
unset_privilege_mode(privileged=privileged)
return vcp_df_color(dfs)
[ドキュメント]
def find_ugroups(
self,
ugroup_name="",
vcid="",
vcno="",
state=None,
ugroup_type="",
privileged=False,
):
"""
検索条件にマッチするVC検索
:param ugroup_name: 検索条件Vc名
:param vcid: 検索条件vcid
:param vcno: 検索条件vcno
:param ugroup_type: 検索条件UnitGroupタイプ
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: UnitGroup情報(vcpsdk::VcpUnitGroupClass)
.. note::
* 検索条件指定が複数あれば、AND条件とする
"""
set_privilege_mode(privileged)
# 自分のVC(全UnitGroup)情報更新
self._oc.config()
ugs = []
for vc in self._oc.vcs:
if (
(ugroup_name == "" or vc.name == ugroup_name)
and (vcid == "" or vc.vcid == vcid)
and (vcno == "" or vc.vcno == vcno)
and (ugroup_type == "" or vc.type == ugroup_type)
and (state is None or vc.state == state)
):
ugs.append(VcpUnitGroupClass(vc, vcp_config=self._vcp_config))
unset_privilege_mode(privileged=privileged)
return ugs
[ドキュメント]
def get_ugroup(self, ugroup_name, privileged=False):
"""
unit group名を指定して、UnitGroup取得
:param ugroup_name: vc名
:param privileged: 特権モードを指定する場合は True、指定しない場合は False (デフォルト)
:return: UnitGroup情報(vcpsdk::VcpUnitGroupClass)
"""
set_privilege_mode(privileged)
# 既存のunit group をugroup_nameで検索して、最初に見つかったunit group
ugs = self.find_ugroups(ugroup_name=ugroup_name)
unset_privilege_mode(privileged=privileged)
if len(ugs) > 0:
return ugs[0]
else:
return None
def create_empty_vc(self, ugroup_name, ugroup_type):
"""
空のVCを作成する
:param ugroup_name: UnitGroup名
:return: Vc情報
"""
#
# VC作成
#
cci = VcpUnitGroupClass.empty_cci(ugroup_name, ugroup_type)
vc = self._oc.create_vc(cci)
return vc
def __str__(self):
"""
VCP SDK 自体は VC配下の情報をもたない
stdoutに、version出力
"""
self.version()
return ""
[ドキュメント]
def version(self):
"""
VCP Libのバージョン出力
"""
# VCP Libのバージョン
self._oc.version()
# VCP SDKのバージョン
print(
"""
vcpsdk:
filename: {filename}
version: {version}""".format(
filename=__file__, version=VCP_SDK_VERSION
)
)
# plugin のバージョン
print(
"""
plugin:
aws: {aws}
aws_disk: {aws_disk}
aws_spot: {aws_spot}
azure: {azure}
vmware: {vmware}
azure_disk: {azure_disk}
sakura: {sakura}
sakura_disk: {sakura_disk}
oracle: {oracle}
oracle_disk: {oracle_disk}
proxmox: {proxmox}
mdx2: {mdx2}
mdx2_disk: {mdx2_disk}
aic: {aic}
abc: {abc}
hokudai: {hokudai}
chameleon: {chameleon}
chameleon_ext: {chameleon_ext}
gcp: {gcp}
onpremises: {onpremises}""".format(
aws=VcpSpecResourceAws.version,
aws_disk=VcpSpecResourceAwsDisk.version,
aws_spot=VcpSpecResourceAwsSpot.version,
azure=VcpSpecResourceAzure.version,
azure_disk=VcpSpecResourceAzureDisk.version,
vmware=VcpSpecResourceVmware.version,
sakura=VcpSpecResourceSakura.version,
sakura_disk=VcpSpecResourceSakuraDisk.version,
oracle=VcpSpecResourceOracle.version,
oracle_disk=VcpSpecResourceOracleDisk.version,
proxmox=VcpSpecResourceProxmox.version,
aic=VcpSpecResourceAic.version,
abc=VcpSpecResourceAbc.version,
hokudai=VcpSpecResourceHokudai.version,
mdx2=VcpSpecResourceMdx2.version,
mdx2_disk=VcpSpecResourceMdx2Disk.version,
gcp=VcpSpecResourceGcp.version,
onpremises=VcpSpecResourceOnpremises.version,
chameleon=VcpSpecResourceChameleon.version,
chameleon_ext=VcpExtResourceChameleon.version,
)
)
# VCC情報
wait_timeout_sec = "1000(default 15min)"
if "wait_timeout_sec" in self._vcp_config["vcc"]:
wait_timeout_sec = self._vcp_config["vcc"]["wait_timeout_sec"]
print(
"""
vc_controller:
host: {host}
name: {name}
wait_timeout_sec: {wait_timeout_sec}""".format(
host=self._vcp_config["vcc"]["host"],
name=self._vcp_config["vcc"]["name"],
wait_timeout_sec=wait_timeout_sec,
),
end="",
)
# VC Controllerのバージョン
occtr_version = self._oc.occtr_version()
print(
"""
vc_controller: {occtr_version}
vc_controller_git_tag: {git_tag}""".format(
occtr_version=occtr_version["version"], git_tag=occtr_version["git_tag"]
)
)
# VC Controllerのpluginバージョン
print(
"""
plugin:""",
end="",
)
for name, version in occtr_version["plugin"].items():
print(
"""
{name}: {version}""".format(
name=name, version=version
),
end="",
)
[ドキュメント]
def version_dict(self) -> dict:
"""
VCP Libのバージョン出力(dict)
"""
sdk_plugins = dict(
aws=VcpSpecResourceAws.version,
aws_disk=VcpSpecResourceAwsDisk.version,
aws_spot=VcpSpecResourceAwsSpot.version,
azure=VcpSpecResourceAzure.version,
azure_disk=VcpSpecResourceAzureDisk.version,
vmware=VcpSpecResourceVmware.version,
sakura=VcpSpecResourceSakura.version,
sakura_disk=VcpSpecResourceSakuraDisk.version,
oracle=VcpSpecResourceOracle.version,
oracle_disk=VcpSpecResourceOracleDisk.version,
proxmox=VcpSpecResourceProxmox.version,
aic=VcpSpecResourceAic.version,
abc=VcpSpecResourceAbc.version,
hokudai=VcpSpecResourceHokudai.version,
mdx2=VcpSpecResourceMdx2.version,
mdx2_disk=VcpSpecResourceMdx2Disk.version,
gcp=VcpSpecResourceGcp.version,
onpremises=VcpSpecResourceOnpremises.version,
chameleon=VcpSpecResourceChameleon.version,
chameleon_ext=VcpExtResourceChameleon.version,
)
vcpsdk = dict(
filename=__file__,
version=VCP_SDK_VERSION,
plugin=sdk_plugins,
)
occtr_version = self._oc.occtr_version()
vc_controller = dict(
host=self._vcp_config["vcc"]["host"],
name=self._vcp_config["vcc"]["name"],
wait_timeout_sec=self._vcp_config["vcc"].get("wait_timeout_sec", "1000(default 15min)"),
version=occtr_version["version"],
git_tag=occtr_version["git_tag"],
plugin=occtr_version["plugin"],
)
return dict(
vcplib=self._oc.version(output=False),
vcpsdk=vcpsdk,
vc_controller=vc_controller,
)
[ドキュメント]
def df_flavors(self, provider_name):
"""
flavor定義の一覧(DataFrame形式)
:param provider_name: 表示対象とするプロバイダ名
"""
LABEL_FLAVOR = "flavor"
flavors = VcpConfigYaml(self._config_dir).load_config("vcp_flavor")
df = pd.json_normalize(
[
{LABEL_FLAVOR: flavor, **params}
for flavor, params in flavors[provider_name].items()
]
)
columns = df.columns.tolist()
columns.remove(LABEL_FLAVOR)
columns.insert(0, LABEL_FLAVOR)
return df.loc[:, columns]
[ドキュメント]
def vcc_info(self):
"""
VC Controllerに関する情報の取得
:return: VCCに関する情報
結果サンプル
.. code-block:: none
{
{ "host": "10.0.0.1:443" },
{ "vault_url": "https://10.0.0.1:8443" },
{ "docker_registry": {
"official": "10.0.0.1:5000",
"user": "10.0.0.1:5001"
}
}
"""
loader = VcpConfigYaml(self._config_dir)
config = loader.load("vcp_config")
# VCコントローラ
vcc_host = config["vcc"]["host"]
vcc_port = 443 # default
if "vcc_port" in config["vcc"]:
vcc_port = "{}:{}".format(vcc_host, config["vcc"]["vcc_port"])
# Vault
vault_port = 8443 # default
if "vault_port" in config["vcc"]:
vault_port = config["vcc"]["vault_port"]
# docker registry
private_ip = vcc_host # default
if "private_ip" in config["vcc"]:
private_ip = config["vcc"]["private_ip"]
# 必要な情報は随時追加する
return {
"host": "{}:{}".format(vcc_host, vcc_port),
"vault_url": "{}://{}:{}".format(VCP_VAULT_SCHEME, vcc_host, vault_port),
"docker_registry": {
"official": "{}:5000".format(private_ip),
"user": "{}:5001".format(private_ip),
},
}
[ドキュメント]
def get_vpn_catalog(self, provider=None, vpn_catalog_name="default"):
"""
VC Controller からVPNカタログ情報を取得する
:param provider: プロバイダ名
:param vpn_catalog_name: VPNカタログ名
:return: vpnカタログ情報
"""
return self._oc.vpn_catalog(provider, vpn_catalog_name=vpn_catalog_name)
[ドキュメント]
def get_publickey(self):
"""
既存サーバ用 ssh 公開鍵取得
:return: ssh 公開鍵文字列
"""
return self._oc.publickey()