Ironic support for packstack
Ironic is currently not a supported plugin for packstack. This patch will create the Ironic plugin. Change-Id: Ia4a239beaf2609bd11cfc35f29527f53c0d6c9f2
This commit is contained in:
parent
ab47974d48
commit
8d2b33cddc
|
@ -44,6 +44,9 @@ Global Options
|
|||
**CONFIG_SAHARA_INSTALL**
|
||||
Set to 'y' if you would like Packstack to install Sahara ['y', 'n'].
|
||||
|
||||
**CONFIG_IRONIC_INSTALL**
|
||||
Set to 'y' if you would like Packstack to install Ironic ['y', 'n'].
|
||||
|
||||
**CONFIG_CLIENT_INSTALL**
|
||||
Set to 'y' if you would like Packstack to install the OpenStack Client packages. An admin "rc" file will also be installed ['y', 'n'].
|
||||
|
||||
|
@ -72,7 +75,7 @@ Global Options
|
|||
Set to 'y' if you would like Packstack to install Openstack Database (Trove)
|
||||
|
||||
**CONFIG_CONTROLLER_HOST**
|
||||
The IP address of the server on which to install OpenStack services specific to controller role such as API servers, Horizon, etc. This parameter replaced following deprecated parameters: CONFIG_CEILOMETER_HOST, CONFIG_CINDER_HOST, CONFIG_GLANCE_HOST, CONFIG_HORIZON_HOST, CONFIG_HEAT_HOST, CONFIG_KEYSTONE_HOST, CONFIG_NAGIOS_HOST, CONFIG_NEUTRON_SERVER_HOST, CONFIG_NEUTRON_LBAAS_HOSTS, CONFIG_NOVA_API_HOST, CONFIG_NOVA_CERT_HOST, CONFIG_NOVA_VNCPROXY_HOST, CONFIG_NOVA_SCHED_HOST, CONFIG_OSCLIENT_HOST, CONFIG_SWIFT_PROXY_HOSTS.
|
||||
The IP address of the server on which to install OpenStack services specific to controller role such as API servers, Horizon, etc. This parameter replaced following deprecated parameters: CONFIG_CEILOMETER_HOST, CONFIG_CINDER_HOST, CONFIG_GLANCE_HOST, CONFIG_HORIZON_HOST, CONFIG_HEAT_HOST, CONFIG_IRONIC_HOST, CONFIG_KEYSTONE_HOST, CONFIG_NAGIOS_HOST, CONFIG_NEUTRON_SERVER_HOST, CONFIG_NEUTRON_LBAAS_HOSTS, CONFIG_NOVA_API_HOST, CONFIG_NOVA_CERT_HOST, CONFIG_NOVA_VNCPROXY_HOST, CONFIG_NOVA_SCHED_HOST, CONFIG_OSCLIENT_HOST, CONFIG_SWIFT_PROXY_HOSTS.
|
||||
|
||||
**CONFIG_COMPUTE_HOSTS**
|
||||
The list of IP addresses of the server on which to install the Nova compute service. This parameter replaced following deprecated parameters: CONFIG_NOVA_COMPUTE_HOSTS.
|
||||
|
@ -275,6 +278,9 @@ Nova Options
|
|||
**CONFIG_NOVA_NETWORK_HOSTS**
|
||||
List of IP address of the servers on which to install the Nova Network service.
|
||||
|
||||
**CONFIG_NOVA_COMPUTE_MANAGER**
|
||||
The driver that will manage the running instances from creation to destruction.
|
||||
|
||||
**CONFIG_NOVA_DB_PW**
|
||||
The password to use for the Nova to access DB.
|
||||
|
||||
|
@ -320,6 +326,15 @@ Nova Options
|
|||
**CONFIG_NOVA_NETWORK_VLAN_START**
|
||||
First VLAN for private networks.
|
||||
|
||||
Ironic Config parameters
|
||||
-----------------------
|
||||
|
||||
**CONFIG_IRONIC_DB_PW**
|
||||
The password used by Ironic user to authenticate against MariaDB.
|
||||
|
||||
**CONFIG_IRONIC_KS_PW**
|
||||
The password to use for the Ironic to authenticate with Keystone.
|
||||
|
||||
OpenStack Horizon Config parameters
|
||||
-----------------------------------
|
||||
|
||||
|
@ -426,7 +441,8 @@ Ceilometer Config Parameters
|
|||
The password to use for Ceilometer to authenticate with Keystone.
|
||||
|
||||
**CONFIG_CEILOMETER_COORDINATION_BACKEND**
|
||||
Specify an optional backend for group membership coordination in the alarm evaluator and central agent. Currently the only valid option are 'redis' or 'none'. The default is 'redis'.
|
||||
Specify an optional backend for group membership coordination in the alarm evaluator and central
|
||||
agent. Currently the only valid option are 'redis' or 'none'. The default is 'redis'.
|
||||
|
||||
**CONFIG_REDIS_HOST**
|
||||
The IP address of the server on which to install Redis, if Redis is being used for coordination.
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Installs and configures Ironic
|
||||
"""
|
||||
|
||||
from packstack.installer import utils, validators, processors
|
||||
|
||||
from packstack.modules.shortcuts import get_mq
|
||||
from packstack.modules.ospluginutils import (getManifestTemplate,
|
||||
appendManifestFile,
|
||||
createFirewallResources)
|
||||
|
||||
# ------------------ Ironic Packstack Plugin initialization ------------------
|
||||
|
||||
PLUGIN_NAME = "OS-Ironic"
|
||||
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
|
||||
|
||||
|
||||
def initConfig(controller):
|
||||
ironic_params = [
|
||||
{"CONF_NAME": "CONFIG_IRONIC_DB_PW",
|
||||
"CMD_OPTION": "os-ironic-db-passwd",
|
||||
"PROMPT": "Enter the password for the Ironic MySQL user",
|
||||
"OPTION_LIST": [],
|
||||
"VALIDATORS": [validators.validate_not_empty],
|
||||
"DEFAULT_VALUE": "PW_PLACEHOLDER",
|
||||
"PROCESSORS": [processors.process_password],
|
||||
"MASK_INPUT": True,
|
||||
"LOOSE_VALIDATION": False,
|
||||
"USE_DEFAULT": True,
|
||||
"NEED_CONFIRM": True,
|
||||
"CONDITION": False},
|
||||
|
||||
{"CONF_NAME": "CONFIG_IRONIC_KS_PW",
|
||||
"CMD_OPTION": "os-ironic-ks-passwd",
|
||||
"USAGE": ("The password to use for Ironic to authenticate "
|
||||
"with Keystone"),
|
||||
"PROMPT": "Enter the password for Ironic Keystone access",
|
||||
"OPTION_LIST": [],
|
||||
"VALIDATORS": [validators.validate_not_empty],
|
||||
"DEFAULT_VALUE": "PW_PLACEHOLDER",
|
||||
"PROCESSORS": [processors.process_password],
|
||||
"MASK_INPUT": True,
|
||||
"LOOSE_VALIDATION": False,
|
||||
"USE_DEFAULT": True,
|
||||
"NEED_CONFIRM": True,
|
||||
"CONDITION": False},
|
||||
]
|
||||
|
||||
ironic_group = {"GROUP_NAME": "IRONIC",
|
||||
"DESCRIPTION": "Ironic Options",
|
||||
"PRE_CONDITION": "CONFIG_IRONIC_INSTALL",
|
||||
"PRE_CONDITION_MATCH": "y",
|
||||
"POST_CONDITION": False,
|
||||
"POST_CONDITION_MATCH": True}
|
||||
|
||||
controller.addGroup(ironic_group, ironic_params)
|
||||
|
||||
|
||||
def initSequences(controller):
|
||||
if controller.CONF['CONFIG_IRONIC_INSTALL'] != 'y':
|
||||
return
|
||||
|
||||
steps = [
|
||||
{'title': 'Adding Ironic Keystone manifest entries',
|
||||
'functions': [create_keystone_manifest]},
|
||||
{'title': 'Adding Ironic manifest entries',
|
||||
'functions': [create_manifest]},
|
||||
]
|
||||
|
||||
controller.addSequence("Installing OpenStack Ironic", [], [],
|
||||
steps)
|
||||
|
||||
|
||||
# -------------------------- step functions --------------------------
|
||||
|
||||
def create_manifest(config, messages):
|
||||
|
||||
if config['CONFIG_UNSUPPORTED'] != 'y':
|
||||
config['CONFIG_STORAGE_HOST'] = config['CONFIG_CONTROLLER_HOST']
|
||||
|
||||
manifestfile = "%s_ironic.pp" % config['CONFIG_CONTROLLER_HOST']
|
||||
manifestdata = getManifestTemplate(get_mq(config, "ironic"))
|
||||
manifestdata += getManifestTemplate("ironic.pp")
|
||||
|
||||
fw_details = dict()
|
||||
key = "ironic-api"
|
||||
fw_details.setdefault(key, {})
|
||||
fw_details[key]['host'] = "ALL"
|
||||
fw_details[key]['service_name'] = "ironic-api"
|
||||
fw_details[key]['chain'] = "INPUT"
|
||||
fw_details[key]['ports'] = ['6385']
|
||||
fw_details[key]['proto'] = "tcp"
|
||||
config['FIREWALL_IRONIC_API_RULES'] = fw_details
|
||||
|
||||
manifestdata += createFirewallResources('FIREWALL_IRONIC_API_RULES')
|
||||
appendManifestFile(manifestfile, manifestdata, 'pre')
|
||||
|
||||
|
||||
def create_keystone_manifest(config, messages):
|
||||
if config['CONFIG_UNSUPPORTED'] != 'y':
|
||||
config['CONFIG_IRONIC_HOST'] = config['CONFIG_CONTROLLER_HOST']
|
||||
|
||||
manifestfile = "%s_keystone.pp" % config['CONFIG_CONTROLLER_HOST']
|
||||
manifestdata = getManifestTemplate("keystone_ironic.pp")
|
||||
appendManifestFile(manifestfile, manifestdata)
|
|
@ -106,7 +106,7 @@ def create_manifest(config, messages):
|
|||
|
||||
append_for("keystone", suffix)
|
||||
for mod in ['nova', 'cinder', 'glance', 'neutron', 'heat', 'sahara',
|
||||
'trove']:
|
||||
'trove', 'ironic']:
|
||||
if config['CONFIG_%s_INSTALL' % mod.upper()] == 'y':
|
||||
append_for(mod, suffix)
|
||||
|
||||
|
|
|
@ -424,6 +424,12 @@ def initSequences(controller):
|
|||
config = controller.CONF
|
||||
if config['CONFIG_NEUTRON_INSTALL'] != 'y':
|
||||
return
|
||||
if config['CONFIG_IRONIC_INSTALL'] == 'y':
|
||||
config['CONFIG_NEUTRON_ML2_TYPE_DRIVERS'] += ', flat'
|
||||
config['CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES'] += ', flat'
|
||||
if 'openvswitch' not in config['CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS']:
|
||||
config['CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS'] += 'openvswitch'
|
||||
config['CONFIG_NEUTRON_ML2_FLAT_NETWORKS'] = 'physnet1'
|
||||
|
||||
plugin_db = 'neutron'
|
||||
plugin_path = 'neutron.plugins.ml2.plugin.Ml2Plugin'
|
||||
|
|
|
@ -110,6 +110,20 @@ def initConfig(controller):
|
|||
"NEED_CONFIRM": False,
|
||||
"CONDITION": False},
|
||||
|
||||
{"CMD_OPTION": "nova-compute-manager",
|
||||
"USAGE": ("The manager that will run nova compute."),
|
||||
"PROMPT": ("Enter the compute manager for nova "
|
||||
"migration"),
|
||||
"OPTION_LIST": [],
|
||||
"VALIDATORS": [validators.validate_not_empty],
|
||||
"DEFAULT_VALUE": "nova.compute.manager.ComputeManager",
|
||||
"MASK_INPUT": False,
|
||||
"LOOSE_VALIDATION": True,
|
||||
"CONF_NAME": "CONFIG_NOVA_COMPUTE_MANAGER",
|
||||
"USE_DEFAULT": False,
|
||||
"NEED_CONFIRM": False,
|
||||
"CONDITION": False},
|
||||
|
||||
],
|
||||
|
||||
"NOVA_NETWORK": [
|
||||
|
@ -489,6 +503,10 @@ def create_compute_manifest(config, messages):
|
|||
ssh_hostkeys += getManifestTemplate("sshkey")
|
||||
|
||||
for host in compute_hosts:
|
||||
if config['CONFIG_IRONIC_INSTALL'] == 'y':
|
||||
cm = 'ironic.nova.compute.manager.ClusteredComputeManager'
|
||||
config['CONFIG_NOVA_COMPUTE_MANAGER'] = cm
|
||||
|
||||
config["CONFIG_NOVA_COMPUTE_HOST"] = host
|
||||
manifestdata = getManifestTemplate("nova_compute")
|
||||
|
||||
|
@ -507,9 +525,12 @@ def create_compute_manifest(config, messages):
|
|||
manifestdata += createFirewallResources(cf_fw_qemu_mig_key)
|
||||
|
||||
if config['CONFIG_VMWARE_BACKEND'] == 'y':
|
||||
manifestdata += getManifestTemplate("nova_compute_vmware")
|
||||
manifestdata += getManifestTemplate("nova_compute_vmware.pp")
|
||||
elif config['CONFIG_IRONIC_INSTALL'] == 'y':
|
||||
manifestdata += getManifestTemplate("nova_compute_ironic.pp")
|
||||
else:
|
||||
manifestdata += getManifestTemplate("nova_compute_libvirt")
|
||||
manifestdata += getManifestTemplate("nova_compute_libvirt.pp")
|
||||
|
||||
if (config['CONFIG_VMWARE_BACKEND'] != 'y' and
|
||||
config['CONFIG_CINDER_INSTALL'] == 'y' and
|
||||
'gluster' in config['CONFIG_CINDER_BACKEND']):
|
||||
|
@ -602,7 +623,13 @@ def create_network_manifest(config, messages):
|
|||
|
||||
def create_sched_manifest(config, messages):
|
||||
manifestfile = "%s_nova.pp" % config['CONFIG_CONTROLLER_HOST']
|
||||
manifestdata = getManifestTemplate("nova_sched")
|
||||
if config['CONFIG_IRONIC_INSTALL'] == 'y':
|
||||
manifestdata = getManifestTemplate("nova_sched_ironic.pp")
|
||||
ram_alloc = '1.0'
|
||||
config['CONFIG_NOVA_SCHED_RAM_ALLOC_RATIO'] = ram_alloc
|
||||
manifestdata += getManifestTemplate("nova_sched.pp")
|
||||
else:
|
||||
manifestdata = getManifestTemplate("nova_sched.pp")
|
||||
appendManifestFile(manifestfile, manifestdata)
|
||||
|
||||
|
||||
|
@ -663,8 +690,12 @@ def create_neutron_manifest(config, messages):
|
|||
if config['CONFIG_NEUTRON_INSTALL'] != "y":
|
||||
return
|
||||
|
||||
virt_driver = 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver'
|
||||
config['CONFIG_NOVA_LIBVIRT_VIF_DRIVER'] = virt_driver
|
||||
if config['CONFIG_IRONIC_INSTALL'] == 'y':
|
||||
virt_driver = 'nova.virt.firewall.NoopFirewallDriver'
|
||||
config['CONFIG_NOVA_LIBVIRT_VIF_DRIVER'] = virt_driver
|
||||
else:
|
||||
virt_driver = 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver'
|
||||
config['CONFIG_NOVA_LIBVIRT_VIF_DRIVER'] = virt_driver
|
||||
|
||||
for manifestfile, marker in manifestfiles.getFiles():
|
||||
if manifestfile.endswith("_nova.pp"):
|
||||
|
|
|
@ -270,6 +270,24 @@ def initConfig(controller):
|
|||
"NEED_CONFIRM": False,
|
||||
"CONDITION": False},
|
||||
|
||||
{"CMD_OPTION": "os-ironic-install",
|
||||
"USAGE": (
|
||||
"Set to 'y' if you would like Packstack to install "
|
||||
"OpenStack Bare Metal (Ironic)"
|
||||
),
|
||||
"PROMPT": (
|
||||
"Should Packstack install OpenStack Bare Metal (Ironic)"
|
||||
),
|
||||
"OPTION_LIST": ["y", "n"],
|
||||
"VALIDATORS": [validators.validate_options],
|
||||
"DEFAULT_VALUE": "n",
|
||||
"MASK_INPUT": False,
|
||||
"LOOSE_VALIDATION": False,
|
||||
"CONF_NAME": "CONFIG_IRONIC_INSTALL",
|
||||
"USE_DEFAULT": False,
|
||||
"NEED_CONFIRM": False,
|
||||
"CONDITION": False},
|
||||
|
||||
{"CMD_OPTION": "os-client-install",
|
||||
"USAGE": (
|
||||
"Set to 'y' if you would like Packstack to install "
|
||||
|
@ -380,6 +398,7 @@ def initConfig(controller):
|
|||
'CONFIG_GLANCE_HOST',
|
||||
'CONFIG_HORIZON_HOST',
|
||||
'CONFIG_HEAT_HOST',
|
||||
'CONFIG_IRONIC_HOST',
|
||||
'CONFIG_KEYSTONE_HOST',
|
||||
'CONFIG_NAGIOS_HOST',
|
||||
'CONFIG_NEUTRON_SERVER_HOST',
|
||||
|
|
|
@ -173,7 +173,7 @@ def install_deps(config, messages):
|
|||
def copy_puppet_modules(config, messages):
|
||||
os_modules = ' '.join(('apache', 'ceilometer', 'certmonger', 'cinder',
|
||||
'concat', 'firewall', 'glance', 'heat', 'horizon',
|
||||
'inifile', 'keystone', 'memcached',
|
||||
'inifile', 'ironic', 'keystone', 'memcached',
|
||||
'mongodb', 'mysql', 'neutron', 'nova', 'nssdb',
|
||||
'openstack', 'packstack', 'qpid', 'rabbitmq',
|
||||
'redis', 'remote', 'rsync', 'sahara', 'ssh',
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
ironic_config {
|
||||
'glance/glance_host': value => hiera('CONFIG_STORAGE_HOST');
|
||||
}
|
||||
|
||||
class { 'ironic::api':
|
||||
auth_host => hiera('CONFIG_CONTROLLER_HOST'),
|
||||
admin_password => hiera('CONFIG_IRONIC_KS_PW'),
|
||||
}
|
||||
|
||||
class { 'ironic::client': }
|
||||
|
||||
class { 'ironic::conductor': }
|
|
@ -0,0 +1,14 @@
|
|||
$ironic_qpid_cfg_ironic_db_pw = hiera('CONFIG_IRONIC_DB_PW')
|
||||
$ironic_qpid_cfg_mariadb_host = hiera('CONFIG_MARIADB_HOST')
|
||||
|
||||
class { 'ironic':
|
||||
rpc_backend => 'ironic.openstack.common.rpc.impl_qpid',
|
||||
qpid_hostname => hiera('CONFIG_AMQP_HOST'),
|
||||
qpid_port => hiera('CONFIG_AMQP_CLIENTS_PORT'),
|
||||
qpid_protocol => hiera('CONFIG_AMQP_PROTOCOL'),
|
||||
qpid_username => hiera('CONFIG_AMQP_AUTH_USER'),
|
||||
qpid_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'),
|
||||
database_connection => "mysql://ironic:${ironic_qpid_cfg_ironic_db_pw}@${ironic_qpid_cfg_mariadb_host}/ironic",
|
||||
debug => true,
|
||||
verbose => true,
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
$ironic_rabbitmq_cfg_ironic_db_pw = hiera('CONFIG_IRONIC_DB_PW')
|
||||
$ironic_rabbitmq_cfg_mariadb_host = hiera('CONFIG_MARIADB_HOST')
|
||||
|
||||
class { 'ironic':
|
||||
rpc_backend => 'ironic.openstack.common.rpc.impl_kombu',
|
||||
rabbit_host => hiera('CONFIG_AMQP_HOST'),
|
||||
rabbit_port => hiera('CONFIG_AMQP_CLIENTS_PORT'),
|
||||
rabbit_user => hiera('CONFIG_AMQP_AUTH_USER'),
|
||||
rabbit_password => hiera('CONFIG_AMQP_AUTH_PASSWORD'),
|
||||
database_connection => "mysql://ironic:${ironic_rabbitmq_cfg_ironic_db_pw}@${ironic_rabbitmq_cfg_mariadb_host}/ironic",
|
||||
debug => true,
|
||||
verbose => true,
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
class {'ironic::keystone::auth':
|
||||
region => hiera('CONFIG_KEYSTONE_REGION'),
|
||||
password => hiera('CONFIG_IRONIC_KS_PW'),
|
||||
public_address => hiera('CONFIG_CONTROLLER_HOST'),
|
||||
admin_address => hiera('CONFIG_CONTROLLER_HOST'),
|
||||
internal_address => hiera('CONFIG_CONTROLLER_HOST'),
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
class { 'ironic::db::mysql':
|
||||
password => hiera('CONFIG_IRONIC_DB_PW'),
|
||||
host => '%%',
|
||||
allowed_hosts => '%%',
|
||||
charset => 'utf8',
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
remote_database { 'ironic':
|
||||
ensure => 'present',
|
||||
charset => 'utf8',
|
||||
db_host => hiera('CONFIG_MARIADB_HOST'),
|
||||
db_user => hiera('CONFIG_MARIADB_USER'),
|
||||
db_password => hiera('CONFIG_MARIADB_PW'),
|
||||
provider => 'mysql',
|
||||
}
|
||||
|
||||
$mariadb_ironic_noinstall_db_pw = hiera('CONFIG_IRONIC_DB_PW')
|
||||
|
||||
remote_database_user { 'ironic@%%':
|
||||
password_hash => mysql_password($mariadb_ironic_noinstall_db_pw),
|
||||
db_host => hiera('CONFIG_MARIADB_HOST'),
|
||||
db_user => hiera('CONFIG_MARIADB_USER'),
|
||||
db_password => hiera('CONFIG_MARIADB_PW'),
|
||||
provider => 'mysql',
|
||||
require => Remote_database['ironic'],
|
||||
}
|
||||
|
||||
remote_database_grant { 'ironic@%%/ironic':
|
||||
privileges => 'all',
|
||||
db_host => hiera('CONFIG_MARIADB_HOST'),
|
||||
db_user => hiera('CONFIG_MARIADB_USER'),
|
||||
db_password => hiera('CONFIG_MARIADB_PW'),
|
||||
provider => 'mysql',
|
||||
require => Remote_database_user['ironic@%%'],
|
||||
}
|
|
@ -40,6 +40,7 @@ class { 'nova::compute':
|
|||
vncproxy_host => hiera('CONFIG_CONTROLLER_HOST'),
|
||||
vncproxy_protocol => $vncproxy_proto,
|
||||
vncserver_proxyclient_address => hiera('CONFIG_NOVA_COMPUTE_HOST'),
|
||||
compute_manager => hiera('CONFIG_NOVA_COMPUTE_MANAGER'),
|
||||
}
|
||||
|
||||
# Tune the host with a virtual hosts profile
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
$ironic_config_controller_host = hiera('CONFIG_CONTROLLER_HOST')
|
||||
|
||||
class {'nova::compute::ironic':
|
||||
admin_user => 'ironic',
|
||||
admin_passwd => hiera('CONFIG_IRONIC_KS_PW'),
|
||||
admin_url => "http://${ironic_config_controller_host}:35357/v2.0",
|
||||
admin_tenant_name => 'services',
|
||||
api_endpoint => "http://${ironic_config_controller_host}:6385/v1",
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
nova_config {
|
||||
'DEFAULT/scheduler_host_manager':
|
||||
value => 'nova.scheduler.ironic_host_manager.IronicHostManager';
|
||||
}
|
Loading…
Reference in New Issue