1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
#!/usr/bin/python3
# Copyright (c) 2026, Thomas Goirand <zigo@debian.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from keystoneauth1 import exceptions as ka_exceptions
from openstack.config import OpenStackConfig
from openstack import connection
from openstack import exceptions
from oslo_config import cfg
from oslo_log import log as logging
from vigietools import validate_compute
LOG = logging.getLogger(__name__, project='vigietools')
cli_opts_validate_compute = [
cfg.StrOpt('hosts-to-validate-aggregate',
default='hosts-to-validate',
help='Hosts to validate aggregate name. Will be used with the '
'enable_isolated_aggregate_filtering nova.conf option to '
'select the correct host'),
cfg.StrOpt('host',
help='The hostname to validate. Mandatory parameter.'),
cfg.StrOpt('custom-trait-name',
default='CUSTOM_COMPUTE_TO_VALIDATE',
help='Name of the compute host trait to use when validating.'),
cfg.StrOpt('project-name',
default='vgt',
help='Project name to spawn a test VM.'),
cfg.StrOpt('user-name',
default='vgt',
help='User name to spawn a test VM.'),
cfg.StrOpt('image-name',
default='Debian 13',
help='Image to use to spawn the VM.'),
cfg.StrOpt('flavor-name',
default='medium-flavor',
help='Image to use to spawn the VM.'),
cfg.StrOpt('network-name',
default='internal-shared-routable-network',
help='Network name when creating the VM.'),
cfg.StrOpt('ssh-username',
default='debian',
help='SSH username to use when checking SSH connectivity.'),
cfg.StrOpt('volume-name',
default='vgt_validation',
help='Cinder volume name used for compute validation.'),
cfg.StrOpt('server-name',
default='vgt-validation-vm',
help='VM name used for compute validation.'),
cfg.StrOpt('keypair-name',
default='vgt-keypair',
help='SSH keypair name used for compute validation.'),
cfg.StrOpt('security-group-name',
default='vgt-sec-group',
help='Security group name used for compute validation.'),
cfg.BoolOpt('keep-enabled',
default=False,
help='Keep the compute host enabled after validation. '
'By default, the host will be disabled after '
'validation.'),
]
def create_connection():
try:
cloud_region = OpenStackConfig().get_one_cloud()
conn = connection.Connection(config=cloud_region)
# Nice to check if it works:
# projects = list(conn.identity.projects())
# print(f"Connected OK. Found {len(projects)} projects.")
return conn
except ka_exceptions.MissingRequiredOptions as e:
LOG.error("OpenStack authentication failed: Missing required "
"credentials (e.g., auth_url, username): %s", e)
LOG.error("Ensure you have sourced a valid OpenRC file or "
"configured clouds.yaml.")
sys.exit(1)
except exceptions.ConfigException as e:
LOG.error("OpenStack configuration error: %s", e)
LOG.error("Ensure you have sourced a valid OpenRC file or "
"configured clouds.yaml.")
sys.exit(1)
except Exception as e:
# Catch-all for connection timeouts, SSL errors,
# unreachable endpoints, etc.
LOG.error("Unexpected error creating OpenStack connection.")
LOG.error("Error: %s", e)
sys.exit(1)
def register_cmd_opts(conf, cli_opts=None):
conf.register_cli_opts(cli_opts)
return conf
def cmd_validate_compute(conf):
conf = register_cmd_opts(conf, cli_opts_validate_compute)
logging.register_options(conf)
sysargs = [arg for arg in sys.argv[1:] if arg != 'validate-compute']
conf(args=sysargs, project='vigietools', default_config_files=[])
logging.setup(conf, 'vigietools')
if not conf.host:
LOG.error('The --host parameter is mandatory but was not '
'provided.')
sys.exit(1)
conn = create_connection()
validate_compute.validate_compute(
conn=conn,
hostname=conf.host,
c_agg=conf.hosts_to_validate_aggregate,
trait_name=conf.custom_trait_name,
project_name=conf.project_name,
user_name=conf.user_name,
image_name=conf.image_name,
flavor_name=conf.flavor_name,
network_name=conf.network_name,
ssh_username=conf.ssh_username,
volume_name=conf.volume_name,
server_name=conf.server_name,
keypair_name=conf.keypair_name,
security_group_name=conf.security_group_name,
keep_enabled=conf.keep_enabled
)
return
def cmd_validate_cleanup(conf):
conf = register_cmd_opts(conf, cli_opts_validate_compute)
logging.register_options(conf)
sysargs = [arg for arg in sys.argv[1:] if arg != 'validate-cleanup']
conf(args=sysargs, project='vigietools', default_config_files=[])
logging.setup(conf, 'vigietools')
conn = create_connection()
validate_compute.validate_cleanup(
conn=conn,
c_agg=conf.hosts_to_validate_aggregate,
trait_name=conf.custom_trait_name,
project_name=conf.project_name,
user_name=conf.user_name,
volume_name=conf.volume_name,
server_name=conf.server_name,
keypair_name=conf.keypair_name,
security_group_name=conf.security_group_name
)
def main():
conf = cfg.ConfigOpts()
if 'validate-compute' in sys.argv:
cmd_validate_compute(conf)
elif 'validate-cleanup' in sys.argv:
cmd_validate_cleanup(conf)
else:
print('Not recogized command line argument.')
print('Choose one of the below commands:')
print('- validate-compute')
exit(1)
exit(0)
if __name__ == '__main__':
main()
|