add client script to install openstack by script.

Change-Id: Iab9e234050c602211258f76e328a69a53d1c173c
This commit is contained in:
xiaodongwang 2014-09-09 16:27:19 -07:00
parent 277185e954
commit e8efc9210d
4 changed files with 729 additions and 429 deletions

View File

@ -16,10 +16,12 @@
"""binary to deploy a cluster by compass client api."""
import logging
import netaddr
import os
import re
import requests
import site
import socket
import sys
import time
@ -48,7 +50,7 @@ flags.add('switch_ips',
default='')
flags.add('switch_credential',
help='comma separated <credential key>=<credential value>',
default='version=v2c,community=public')
default='version=2c,community=public')
flags.add('switch_max_retries', type='int',
help='max retries of poll switch',
default=5)
@ -61,39 +63,90 @@ flags.add_bool('poll_switches',
flags.add('machines',
help='comma separated mac addresses of machines',
default='')
flags.add('adapter_os_name',
flags.add('subnets',
help='comma seperated subnets',
default='')
flags.add('adapter_os_pattern',
help='adapter os name',
default=r'(?i)centos.*')
flags.add('adapter_target_system',
flags.add('adapter_target_system_pattern',
help='adapter target system name',
default='openstack')
flags.add('adapter_flavor',
default='openstack.*')
flags.add('adapter_flavor_pattern',
help='adapter flavor name',
default='allinone')
flags.add('cluster_name',
help='cluster name',
default='cluster1')
flags.add('credentials',
flags.add('language',
help='language',
default='EN')
flags.add('timezone',
help='timezone',
default='GMT')
flags.add('http_proxy',
help='http proxy',
default='')
flags.add('https_proxy',
help='https proxy',
default='')
flags.add('no_proxy',
help='no proxy',
default='')
flags.add('ntp_server',
help='ntp server',
default='')
flags.add('dns_servers',
help='dns servers',
default='')
flags.add('domain',
help='domain',
default='')
flags.add('search_path',
help='search path',
default='')
flags.add('default_gateway',
help='default gateway',
default='')
flags.add('server_credential',
help=(
'comma separated credentials formatted as '
'<credential_name>:<username>=<password>'
'server credential formatted as '
'<username>=<password>'
),
default=(
'server:root=root,service:service=service,'
'console:console=console'
))
flags.add('networking',
default='root=root')
flags.add('service_credentials',
help=(
'semicomma seperated network property and its value '
'<network_property_name>=<value>'
'comma seperated service credentials formatted as '
'<servicename>:<username>=<password>,...'
),
default='')
flags.add('console_credentials',
help=(
'comma seperated console credential formated as '
'<consolename>:<username>=<password>'
),
default='')
flags.add('hostnames',
help='comma seperated hostname',
default='')
flags.add('host_networks',
help=(
'semicomma seperated host name and its networks '
'<hostname>:<interface_name>=<ip>|<is_mgmt>|<is_promiscous>,...'
),
default='')
flags.add('partitions',
help=(
'comma seperated partitions '
'<partition name>:<partition_type>=<partition_value>'
'<partition name>=<partition_value>'
),
default='tmp:percentage=10,var:percentage=20,home:percentage=40')
default='tmp:percentage=10%,var:percentage=30%,home:percentage=30%')
flags.add('network_mapping',
help=(
'comma seperated network mapping '
'<network_type>=<interface_name>'
),
default='')
flags.add('host_roles',
help=(
'semicomma separated host roles '
@ -106,9 +159,9 @@ flags.add('deployment_timeout',
flags.add('progress_update_check_interval',
help='progress update status check interval in seconds',
default=60)
flags.add('dashboard_role',
help='dashboard role name',
default='os-dashboard')
flags.add('dashboard_url',
help='dashboard url',
default='')
flags.add('dashboard_link_pattern',
help='dashboard link pattern',
default=r'(?m)(http://\d+\.\d+\.\d+\.\d+:5000/v2\.0)')
@ -186,6 +239,10 @@ def _poll_switches(client):
switch_ip for switch_ip in flags.OPTIONS.switch_ips.split(',')
if switch_ip
]
if not switch_ips:
raise Exception(
'there is no switches to poll')
switch_credential = dict([
credential.split('=', 1)
for credential in flags.OPTIONS.switch_credential.split(',')
@ -206,6 +263,15 @@ def _poll_switches(client):
remain_retries = flags.OPTIONS.switch_max_retries
while True:
for switch_ip, switch in all_switches.items():
status, resp = client.poll_switch(switch['id'])
logging.info(
'get switch %s status %s: %s',
switch_ip, status, resp)
if status >= 400:
msg = 'failed to update switch %s' % switch_ip
raise Exception(msg)
remain_retries -= 1
time.sleep(flags.OPTIONS.switch_retry_interval)
for switch_ip, switch in all_switches.items():
switch_id = switch['id']
@ -237,15 +303,7 @@ def _poll_switches(client):
except Exception:
logging.error('failed to get all machines')
if remain_retries > 0:
for switch_ip, switch in all_switches.items():
status, resp = client.poll_switch(switch['id'])
if status >= 400:
msg = 'failed to update switch %s' % switch_ip
raise Exception(msg)
remain_retries -= 1
else:
if remain_retries <= 0:
msg = 'max retries reached'
raise Exception(msg)
@ -261,17 +319,19 @@ def _get_adapter(client):
msg = 'failed to get adapters'
raise Exception(msg)
os_name_pattern = flags.OPTIONS.adapter_os_name
os_name_re = re.compile(os_name_pattern)
target_system_pattern = flags.OPTIONS.adapter_target_system
os_pattern = flags.OPTIONS.adapter_os_pattern
os_re = re.compile(os_pattern)
target_system_pattern = flags.OPTIONS.adapter_target_system_pattern
target_system_re = re.compile(target_system_pattern)
flavor_name_pattern = flags.OPTIONS.adapter_flavor
flavor_re = re.compile(flavor_name_pattern)
flavor_pattern = flags.OPTIONS.adapter_flavor_pattern
flavor_re = re.compile(flavor_pattern)
adapter_id = None
os_id = None
flavor_id = None
adapter = None
for item in resp:
if 'distributed_system_name' not in item:
continue
if target_system_re.match(item['distributed_system_name']):
adapter = item
adapter_id = adapter['id']
@ -282,12 +342,12 @@ def _get_adapter(client):
raise Exception(msg)
for supported_os in adapter['supported_oses']:
if os_name_re.match(supported_os['name']):
if os_re.match(supported_os['name']):
os_id = supported_os['os_id']
break
if not os_id:
msg = 'no os found for %s' % os_name_pattern
msg = 'no os found for %s' % os_pattern
raise Exception(msg)
for flavor in adapter['flavors']:
@ -296,20 +356,39 @@ def _get_adapter(client):
break
if not flavor_id:
msg = 'no flavor found for %s' % flavor_name_pattern
msg = 'no flavor found for %s' % flavor_pattern
raise Exception(msg)
logging.info('adpater for deploying a cluster: %s', adapter_id)
return (adapter_id, os_id, flavor_id)
def _add_subnet(client):
pass
def _add_subnets(client):
subnets = [
subnet for subnet in flags.OPTIONS.subnets.split(',')
if subnet
]
if not subnets:
raise Exception(
'there is no subnets added')
subnet_mapping = {}
for subnet in subnets:
status, resp = client.add_subnet(subnet)
logging.info('add subnet %s status %s response %s',
subnet, status, resp)
if status >= 400:
msg = 'failed to add subnet %s' % subnet
raise Exception(msg)
subnet_mapping[resp['subnet']] = resp['id']
return subnet_mapping
def _add_cluster(client, adapter_id, os_id, flavor_id, machines):
"""add a cluster."""
cluster_name = flags.OPTIONS.cluster_name
if not cluster_name:
raise Exception(
'no cluster name set')
status, resp = client.add_cluster(
cluster_name, adapter_id,
os_id, flavor_id)
@ -322,321 +401,417 @@ def _add_cluster(client, adapter_id, os_id, flavor_id, machines):
cluster = resp
cluster_id = cluster['id']
hostnames = [
hostname for hostname in flags.OPTIONS.hostnames.split(',')
if hostname
]
if len(machines) != len(hostnames):
msg = 'hostname %s length does not match machines mac %s length' % (
hostnames, machines)
raise Exception(msg)
machines_dict = []
for machine_id in machines:
for machine_id, hostname in map(None, machines, hostnames):
machines_dict.append({
'machine_id': machine_id
'machine_id': machine_id,
'name': hostname
})
# add hosts to the cluster.
status, resp = client.add_hosts_to_cluster(
cluster_id,
machines_dict)
logging.info('add hosts to cluster %s status: %s, resp: %s',
cluster_id, status, resp)
{'machines': machines_dict})
logging.info('add machines %s to cluster %s status: %s, resp: %s',
machines_dict, cluster_id, status, resp)
if status >= 400:
msg = 'failed to add machines %s to cluster %s' % (
machines, cluster_name)
raise Exception(msg)
host_ids = []
for host in resp['cluster_hosts']:
host_ids.append(host['id'])
logging.info('added hosts in cluster %s: %s', cluster_id, host_ids)
if len(host_ids) != len(machines):
host_mapping = {}
for host in resp['hosts']:
host_mapping[host['hostname']] = host['id']
logging.info('added hosts in cluster %s: %s', cluster_id, host_mapping)
if len(host_mapping) != len(machines):
msg = 'machines %s to add to the cluster %s while hosts %s' % (
machines, cluster_name, host_ids)
machines, cluster_name, host_mapping)
raise Exception(msg)
return {cluster_id: host_ids}
return (cluster_id, host_mapping)
def _set_cluster_security(client, cluster_hosts):
"""set cluster security."""
credentials = [
credential for credential in flags.OPTIONS.credentials.split(',')
if ':' in credential
def _set_cluster_os_config(client, cluster_id, host_ips):
"""set cluster os config."""
os_config = {}
language = flags.OPTIONS.language
timezone = flags.OPTIONS.timezone
http_proxy = flags.OPTIONS.http_proxy
https_proxy = flags.OPTIONS.https_proxy
if not https_proxy and http_proxy:
https_proxy = http_proxy
no_proxy = [
no_proxy for no_proxy in flags.OPTIONS.no_proxy.split(',')
if no_proxy
]
logging.info('set cluster security: %s', credentials)
credential_mapping = {}
for credential in credentials:
credential_name, username_and_password = credential.split(':', 1)
if not credential_name:
raise Exception('there is no credential name in %s' % credential)
if not username_and_password:
raise Exception('there is no username/password in %s' % credential)
if '=' not in username_and_password:
raise Exception('there is no = in %s' % username_and_password)
username, password = username_and_password.split('=', 1)
if not username or not password:
raise Exception(
'there is no username or password in %s' % (
username_and_password))
credential_mapping['%s_username' % credential_name] = username
credential_mapping['%s_password' % credential_name] = password
for cluster_id, host_ids in cluster_hosts.items():
status, resp = client.set_security(
cluster_id, **credential_mapping)
logging.info(
'set security config to cluster %s status: %s, resp: %s',
cluster_id, status, resp)
if status >= 400:
msg = 'failed to set security %s for cluster %s' % (
credential_mapping, cluster_id)
raise Exception(msg)
def _set_cluster_networking(client, cluster_hosts):
"""set cluster networking."""
networking_map = {}
networkings = [
network for network in flags.OPTIONS.networking.split(';')
if '=' in network
compass_name = socket.gethostname()
compass_ip = socket.gethostbyname(compass_name)
if http_proxy and not no_proxy:
no_proxy = ['127.0.0.1', compass_name, compass_ip]
for hostname, ips in host_ips.items():
no_proxy.append(hostname)
no_proxy.extend(ips)
ntp_server = flags.OPTIONS.ntp_server
if not ntp_server:
ntp_server = compass_ip
dns_servers = [
dns_server for dns_server in flags.OPTIONS.dns_servers.split(',')
if dns_server
]
logging.info('set cluster networking: %s', networkings)
for networking in networkings:
networking_name, networking_value = networking.split('=', 1)
if not networking_name:
raise Exception(
'there is no networking name in %s' % networking)
if networking_name.endswith('_promisc'):
networking_map[networking_name] = int(networking_value)
else:
networking_map[networking_name] = networking_value
for cluster_id, host_ids in cluster_hosts.items():
status, resp = client.set_networking(
cluster_id, **networking_map)
logging.info(
'set networking config %s to cluster %s status: %s, resp: %s',
networking_map, cluster_id, status, resp)
if status >= 400:
msg = 'failed to set networking config %s to cluster %s' % (
networking_map, cluster_id)
raise Exception(msg)
def _set_cluster_partition(client, cluster_hosts):
"""set partiton of each host in cluster."""
if not dns_servers:
dns_servers = [compass_ip]
domain = flags.OPTIONS.domain
if not domain:
raise Exception('domain is not defined')
search_path = [
search_path for search_path in flags.OPTIONS.search_path.split(',')
if search_path
]
if not search_path:
search_path = [domain]
default_gateway = flags.OPTIONS.default_gateway
if not default_gateway:
raise Exception('default gateway is not defined')
os_config['general'] = {
'language': language,
'timezone': timezone,
'ntp_server': ntp_server,
'dns_servers': dns_servers,
'default_gateway': default_gateway
}
if http_proxy:
os_config['general']['http_proxy'] = http_proxy
if https_proxy:
os_config['general']['https_proxy'] = https_proxy
if no_proxy:
os_config['general']['no_proxy'] = no_proxy
if domain:
os_config['general']['domain'] = domain
if search_path:
os_config['general']['search_path'] = search_path
server_credential = flags.OPTIONS.server_credential
if '=' in server_credential:
server_username, server_password = server_credential.split('=', 1)
elif server_credential:
server_username = server_credential
server_password = server_username
else:
server_username = 'root'
server_password = 'root'
os_config['server_credentials'] = {
'username': server_username,
'password': server_password
}
partitions = [
partition for partition in flags.OPTIONS.partitions.split(',')
if ':' in partition
]
logging.info('set cluster partition: %s', partitions)
partiton_mapping = {}
os_config['partition'] = {}
for partition in partitions:
partition_name, partition_pair = partition.split(':', 1)
partition_name, partition_value = partition.split('=', 1)
if not partition_name:
raise Exception(
'there is no partition name in %s' % partition)
if not partition_pair:
if not partition_value:
raise Exception(
'there is no partition pair in %s' % partition)
'there is no partition value in %s' % partition)
if '=' not in partition_pair:
raise Exception(
'there is no = in %s' % partition_pair)
partition_type, partition_value = partition_pair.split('=', 1)
if partition_type == 'percentage':
partition_value = int(partition_value)
elif partition_type == 'mbytes':
partition_value = int(partition_value)
if partition_value.endswith('%'):
partition_type = 'percentage'
partition_value = int(partition_value[:-1])
else:
raise Exception(
'unsupported partition type %s' % partition_type)
partiton_mapping[
'%s_%s' % (partition_name, partition_type)
] = partition_value
for cluster_id, host_ids in cluster_hosts.items():
status, resp = client.set_partition(
cluster_id, **partiton_mapping)
logging.info(
'set partition config %s to cluster %s status: %s, resp: %s',
partiton_mapping, cluster_id, status, resp)
if status >= 400:
msg = 'failed to set partition %s to cluster %s' % (
partiton_mapping, cluster_id)
raise Exception(msg)
def _set_host_config(client, cluster_hosts):
host_configs = []
for host in flags.OPTIONS.host_roles.split(';'):
if not host:
continue
hostname, roles = host.split('=', 1)
if hostname:
roles = [role for role in roles.split(',') if role]
host_configs.append({
'hostname': hostname,
'roles': roles
})
total_hosts = 0
for cluster_id, host_ids in cluster_hosts.items():
total_hosts += len(host_ids)
if total_hosts != len(host_configs):
msg = '%s host to assign but got %s host configs' % (
total_hosts, len(host_configs))
partition_type = 'size'
os_config['partition'][partition_name] = {
partition_type: partition_value
}
status, resp = client.update_cluster_config(
cluster_id, os_config=os_config)
logging.info(
'set os config %s to cluster %s status: %s, resp: %s',
os_config, cluster_id, status, resp)
if status >= 400:
msg = 'failed to set os config %s to cluster %s' % (
os_config, cluster_id)
raise Exception(msg)
for cluster_id, host_ids in cluster_hosts.items():
for hostid in host_ids:
host_config = host_configs.pop(0)
status, resp = client.update_host_config(
hostid, **host_config)
def _set_host_networking(client, host_mapping, subnet_mapping):
"""set cluster hosts networking."""
host_ips = {}
for host_network in flags.OPTIONS.host_networks.split(';'):
hostname, networks_str = host_network.split(':', 1)
if hostname not in host_mapping:
msg = 'hostname %s does not exist in host mapping %s' % (
hostname, host_mapping
)
raise Exception(msg)
host_id = host_mapping[hostname]
networks = networks_str.split(',')
for network in networks:
interface, network_properties_str = network.split('=', 1)
network_properties = network_properties_str.split('|')
ip_addr = network_properties[0]
ip = netaddr.IPAddress(ip_addr)
subnet_id = None
for subnet_addr, subnetid in subnet_mapping.items():
subnet = netaddr.IPNetwork(subnet_addr)
if ip in subnet:
subnet_id = subnetid
break
if not subnet_id:
msg = 'no subnet found for ip %s' % ip_addr
raise Exception(msg)
properties = dict([
(network_property, True)
for network_property in network_properties[1:]
])
logging.info(
'set host %s config %s status: %s, resp: %s',
hostid, host_config, status, resp
'add host %s interface %s ip %s network proprties %s',
hostname, interface, ip_addr, properties)
status, response = client.add_host_network(
host_id, interface, ip=ip_addr, subnet_id=subnet_id,
**properties
)
logging.info(
'add host %s interface %s ip %s network properties %s '
'status %s: %s',
hostname, interface, ip_addr, properties,
status, response
)
if status >= 400:
msg = 'failed to set host %s config %s' % (
hostid, host_config)
msg = 'failed to set host %s interface %s network' % (
hostname, interface
)
raise Exception(msg)
host_ips.setdefault(hostname, []).append(ip_addr)
return host_ips
def _deploy_clusters(client, cluster_hosts):
"""deploy cluster."""
for cluster_id, host_ids in cluster_hosts.items():
status, resp = client.deploy_hosts(cluster_id)
def _set_cluster_package_config(client, cluster_id):
"""set cluster package config."""
package_config = {
'security': {
'service_credentials': {
},
'console_credentials': {
}
}
}
service_credentials = [
service_credential
for service_credential in flags.OPTIONS.service_credentials.split(',')
if service_credential
]
for service_credential in service_credentials:
if ':' not in service_credential:
raise Exception(
'there is no : in service credential %s' % service_credential
)
service_name, service_pair = service_credential.split(':', 1)
if '=' not in service_pair:
raise Exception(
'there is no = in service %s security' % service_name
)
username, password = service_pair.split('=', 1)
package_config['security']['service_credentials'][service_name] = {
'username': username,
'password': password
}
console_credentials = [
console_credential
for console_credential in flags.OPTIONS.console_credentials.split(',')
if console_credential
]
for console_credential in console_credentials:
if ':' not in console_credential:
raise Exception(
'there is no : in console credential %s' % console_credential
)
console_name, console_pair = console_credential.split(':', 1)
if '=' not in console_pair:
raise Exception(
'there is no = in console %s security' % console_name
)
username, password = console_pair.split('=', 1)
package_config['security']['console_credentials'][service_name] = {
'username': username,
'password': password
}
package_config['network_mapping'] = dict([
network_pair.split('=', 1)
for network_pair in flags.OPTIONS.network_mapping.split(',')
if '=' in network_pair
])
status, resp = client.update_cluster_config(
cluster_id, package_config=package_config)
logging.info(
'set package config %s to cluster %s status: %s, resp: %s',
package_config, cluster_id, status, resp)
if status >= 400:
msg = 'failed to set package config %s to cluster %s' % (
package_config, cluster_id)
raise Exception(msg)
def _set_host_roles(client, cluster_id, host_mapping):
host_roles = {}
for host_str in flags.OPTIONS.host_roles.split(';'):
if not host_str:
continue
hostname, roles_str = host_str.split('=', 1)
if hostname not in host_mapping:
raise Exception(
'hostname %s not found in host mapping %s' % (
hostname, host_mapping
)
)
host_id = host_mapping[hostname]
roles = [role for role in roles_str.split(',') if role]
status, response = client.update_cluster_host(
cluster_id, host_id, roles=roles)
logging.info(
'deploy cluster %s status: %s, resp: %s',
cluster_id, status, resp)
'set cluster %s host %s roles %s status %s: %s',
cluster_id, hostname, roles, status, response
)
if status >= 400:
msg = 'failed to deploy cluster %s' % cluster_id
raise Exception(msg)
raise Exception(
'failed to set cluster %s host %s roles %s' % (
cluster_id, host_id, roles
)
)
host_roles[hostname] = roles
return host_roles
def _get_installing_progress(client, cluster_hosts):
def _deploy_clusters(client, cluster_id, host_mapping):
"""deploy cluster."""
host_ids = [host_id for _, host_id in host_mapping.items()]
status, response = client.review_cluster(
cluster_id, review={'hosts': host_ids}
)
logging.info(
'review cluster %s hosts %s, status %s: %s',
cluster_id, host_ids, status, response
)
if status >= 400:
raise Exception(
'review cluster %s fails' % cluster_id
)
status, response = client.deploy_cluster(
cluster_id, deploy={'hosts': host_ids}
)
logging.info(
'deploy cluster %s hosts %s status %s: %s',
cluster_id, host_ids, status, response
)
if status >= 400:
raise Exception(
'deploy cluster %s fails' % cluster_id
)
def _get_installing_progress(client, cluster_id, host_mapping):
"""get intalling progress."""
timeout = time.time() + 60 * float(flags.OPTIONS.deployment_timeout)
clusters_progress = {}
hosts_progress = {}
cluster_installed = False
cluster_failed = False
hosts_installed = {}
hosts_failed = {}
install_finished = False
failed_hosts = {}
failed_clusters = {}
while time.time() < timeout:
found_installing_clusters = False
found_installing_hosts = False
for cluster_id, host_ids in cluster_hosts.items():
for hostid in host_ids:
if hostid in hosts_progress:
continue
status, resp = client.get_host_installing_progress(hostid)
logging.info(
'get host %s installing progress status: %s, resp: %s',
hostid, status, resp)
if status >= 400:
msg = 'failed to get host %s progress' % hostid
raise Exception(msg)
progress = resp['progress']
if (
progress['state'] not in ['UNINITIALIZED', 'INSTALLING'] or
progress['percentage'] >= 1.0
):
hosts_progress[hostid] = progress
if progress['state'] in ['ERROR']:
failed_hosts[hostid] = progress
else:
found_installing_hosts = True
if cluster_id in clusters_progress:
continue
status, resp = client.get_cluster_installing_progress(cluster_id)
status, cluster_state = client.get_cluster_state(cluster_id)
logging.info(
'get cluster %s state status %s: %s',
cluster_id, status, cluster_state
)
if status >= 400:
raise Exception(
'failed to acquire cluster %s state' % cluster_id
)
if cluster_state['state'] == 'SUCCESSFUL':
cluster_installed = True
if cluster_state['state'] == 'ERROR':
cluster_failed = True
for hostname, host_id in host_mapping.items():
status, host_state = client.get_cluster_host_state(
cluster_id, host_id
)
logging.info(
'get cluster %s installing progress status: %s, resp: %s',
cluster_id, status, resp)
'get cluster %s host %s state status %s: %s',
cluster_id, host_id, status, host_state
)
if status >= 400:
msg = 'failed to get cluster %s intsalling progress' % (
cluster_id)
raise Exception(msg)
progress = resp['progress']
if (
progress['state'] not in ['UNINITIALIZED', 'INSTALLING'] or
progress['percentage'] >= 1.0
):
clusters_progress[cluster_id] = progress
if progress['state'] in ['ERROR']:
failed_clusters[cluster_id] = progress
raise Exception(
'failed to acquire cluster %s host %s state' % (
cluster_id, host_id
)
)
if host_state['state'] == 'SUCCESSFUL':
hosts_installed[host_id] = True
else:
found_installing_clusters = True
hosts_installed[host_id] = False
if host_state['state'] == 'ERROR':
hosts_failed[host_id] = True
else:
hosts_failed[host_id] = False
if found_installing_clusters and found_installing_hosts:
cluster_finished = cluster_installed or cluster_failed
hosts_finished = {}
for _, host_id in host_mapping.items():
hosts_finished[host_id] = (
hosts_installed.get(host_id, False) or
hosts_failed.get(host_id, False)
)
if cluster_finished and all(hosts_finished.values()):
logging.info('all clusters/hosts are installed.')
install_finished = True
break
else:
logging.info(
'there are some clusters/hosts in installing.'
'sleep %s seconds and retry',
flags.OPTIONS.progress_update_check_interval)
time.sleep(float(flags.OPTIONS.progress_update_check_interval))
else:
install_finished = True
logging.info('all clusters/hosts are installed.')
break
if not install_finished:
msg = 'installing %s is not all finished: hosts %s clusters %s' % (
cluster_hosts, hosts_progress, clusters_progress)
raise Exception(msg)
if failed_hosts:
msg = 'installing hosts failed: %s' % failed_hosts
raise Exception(msg)
if failed_clusters:
msg = 'installing clusters failed: %s' % failed_clusters
raise Exception(
'cluster %s installation not finished: '
'installed %s, failed: %s' % (
cluster_id, hosts_installed, hosts_failed
)
)
if cluster_failed or any(hosts_failed.values()):
msg = 'cluster %s hosts %s is not all finished. failed hosts %s' % (
cluster_id, host_mapping.values(), hosts_failed.keys()
)
raise Exception(msg)
def _check_dashboard_links(client, cluster_hosts):
dashboard_role = flags.OPTIONS.dashboard_role
def _check_dashboard_links(client, cluster_id):
dashboard_url = flags.OPTIONS.dashboard_url
if not dashboard_url:
raise Exception(
'no dashboard url set')
dashboard_link_pattern = re.compile(
flags.OPTIONS.dashboard_link_pattern)
for cluster_id, host_ids in cluster_hosts.items():
status, resp = client.get_dashboard_links(cluster_id)
r = requests.get(dashboard_url, verify=False)
r.raise_for_status()
match = dashboard_link_pattern.search(r.text)
if match:
logging.info(
'get cluster %s dashboard links status: %s, resp: %s',
cluster_id, status, resp)
if status >= 400:
msg = 'failed to get cluster %s dashboard links' % cluster_id
raise Exception(msg)
dashboardlinks = resp['dashboardlinks']
if dashboard_role not in dashboardlinks:
msg = 'no dashboard role %s found in %s' % (
dashboard_role, dashboardlinks)
raise Exception(msg)
r = requests.get(dashboardlinks[dashboard_role], verify=False)
r.raise_for_status()
match = dashboard_link_pattern.search(r.text)
if match:
logging.info(
'dashboard login page for cluster %s can be downloaded',
cluster_id)
else:
msg = (
'%s dashboard login page failed to be downloaded\n'
'the context is:\n%s\n'
) % (dashboard_role, r.text)
raise Exception(msg)
'dashboard login page for cluster %s can be downloaded',
cluster_id)
else:
msg = (
'%s failed to be downloaded\n'
'the context is:\n%s\n'
) % (dashboard_url, r.text)
raise Exception(msg)
def main():
@ -648,16 +823,19 @@ def main():
machines = _poll_switches(client)
else:
machines = _get_machines(client)
subnet_mapping = _add_subnets(client)
adapter_id, os_id, flavor_id = _get_adapter(client)
cluster_hosts = _add_cluster(
cluster_id, host_mapping = _add_cluster(
client, adapter_id, os_id, flavor_id, machines)
_set_cluster_security(client, cluster_hosts)
_set_cluster_networking(client, cluster_hosts)
_set_cluster_partition(client, cluster_hosts)
_set_host_config(client, cluster_hosts)
_deploy_clusters(client, cluster_hosts)
_get_installing_progress(client, cluster_hosts)
_check_dashboard_links(client, cluster_hosts)
host_ips = _set_host_networking(
client, host_mapping, subnet_mapping
)
_set_cluster_os_config(client, cluster_id, host_ips)
_set_cluster_package_config(client, cluster_id)
_set_host_roles(client, cluster_id, host_mapping)
_deploy_clusters(client, cluster_id, host_mapping)
_get_installing_progress(client, cluster_id, host_mapping)
_check_dashboard_links(client, cluster_id)
if __name__ == "__main__":

2
bin/client.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
/opt/compass/bin/client.py --switch_ips=172.29.8.40 --machines=00:0c:29:a7:ea:4b --subnets=10.145.88.0/23,172.16.0.0/16 --cluster_name=cluster1 --domain=ods.com --default_gateway=10.145.88.1 --service_credentials=image:service=service,compute:service=service,dashboard:service=service,identity:service=service,metering:service=service,rabbitmq:service=service,volume:service=service,mysql:service=service --console_credentials=admin:console=console,compute:console=console,dashboard:console=console,image:console=console,metering:console=console,network:console=console,object-store:console=console,volume:console=console --hostnames=host1 --host_networks="host1:eth0=10.145.89.201|is_mgmt,eth1=172.16.100.201|is_promiscuous" --partitions="/var=50%,/home=30%" --network_mapping=management=eth0,tenant=eth0,storage=eth0,public=eth1 --host_roles=host1=allinone-compute --dashboard_url=http://10.145.89.201

View File

@ -16,34 +16,25 @@
"""Example code to deploy a cluster by compass client api."""
import os
import re
import requests
import sys
import time
# from compass.apiclient.restful import Client
from restful import Client
COMPASS_SERVER_URL = 'http://10.145.89.100/api'
COMPASS_SERVER_URL = 'http://localhost/api'
COMPASS_LOGIN_EMAIL = 'admin@huawei.com'
COMPASS_LOGIN_PASSWORD = 'admin'
SWITCH_IP = '172.29.8.40'
SWITCH_SNMP_VERSION = '2c'
SWITCH_SNMP_COMMUNITY = 'public'
#MACHINES_TO_ADD = ['00:0c:29:05:bd:eb']
CLUSTER_NAME = 'test_cluster'
HOST_NAME_PREFIX = 'host'
SERVER_USERNAME = 'root'
SERVER_PASSWORD = 'root'
SERVICE_USERNAME = 'service'
SERVICE_PASSWORD = 'service'
DASHBOARD_USERNAME = 'console'
DASHBOARD_PASSWORD = 'console'
CONSOLE_USERNAME = 'console'
CONSOLE_PASSWORD = 'console'
HA_VIP = ''
#NAMESERVERS = '10.145.88.211'
SEARCH_PATH = ['ods.com']
#GATEWAY = '10.145.88.1'
#PROXY = 'http://192.168.10.6:3128'
#NTP_SERVER = '10.145.88.211'
MANAGEMENT_IP_START = '10.145.88.130'
MANAGEMENT_IP_END = '10.145.88.254'
@ -72,25 +63,28 @@ STORAGE_PROMISC = 0
HOME_PERCENTAGE = 5
TMP_PERCENTAGE = 5
VAR_PERCENTAGE = 10
#ROLES_LIST = [['os-dashboard']]
HOST_OS = 'CentOS-6.5-x86_64'
LANGUAGE = 'EN'
TIMEZONE = 'GMT -7:00'
HTTPS_PROXY = 'https://10.145.89.100:3128'
NO_PROXY = ['127.0.0.1']
DNS_SERVER = '10.145.89.100'
DOMAIN = 'ods.com'
PRESET_VALUES = {
'LANGUAGE': 'EN',
'TIMEZONE': 'GMT',
'HTTPS_PROXY': 'http://10.145.89.100:3128',
'NO_PROXY': ['127.0.0.1'],
'DOMAIN': 'ods.com',
'NAMESERVERS': ['10.145.89.100'],
'NTP_SERVER': '10.145.89.100',
'GATEWAY': '10.145.88.1',
'PROXY': 'http://10.145.89.100:3128',
'FLAVOR': 'allinone',
'OS_NAME_PATTERN': 'CentOS.*',
'DISTRIBUTED_SYSTEM_NAME_PATTERN': 'openstack.*',
'FLAVOR_PATTERN': 'allinone.*',
'ROLES_LIST': ['allinone-compute'],
'MACHINES_TO_ADD': ['00:0c:29:a7:ea:4b'],
'BUILD_TIMEOUT': 60
'BUILD_TIMEOUT': 60,
'SEARCH_PATH': ['ods.com'],
'SERVER_USERNAME': 'root',
'SERVER_PASSWORD': 'root'
}
for v in PRESET_VALUES:
if v in os.environ.keys():
@ -104,6 +98,10 @@ client = Client(COMPASS_SERVER_URL)
# login
status, token = client.login(COMPASS_LOGIN_EMAIL, COMPASS_LOGIN_PASSWORD)
print '============================================================'
print 'login status: %s token: %s' % (status, token)
if status >= 400:
sys.exit(1)
# list all switches
status, response = client.list_switches()
@ -125,6 +123,10 @@ if status < 400:
switch = response
else:
status, response = client.list_switches()
print '========================================='
print 'list switches status %s response %s' % (status, response)
if status >= 400:
sys.exit(1)
for switch_ in response:
if switch_['ip'] == SWITCH_IP:
switch = switch_
@ -140,10 +142,12 @@ while switch['state'] != 'under_monitoring':
print 'waiting for state to become under_monitoring'
client.poll_switch(switch_id)
status, resp = client.get_switch(switch_id)
print '====================================='
print 'poll switch status %s response %s' % (status, resp)
switch = resp
print 'switch is in state: %s' % switch['state']
time.sleep(5)
status, response = client.poll_switch(switch_id)
print '========================================='
print 'switch state now is %s' % (switch['state'])
@ -152,63 +156,59 @@ machine_macs = {}
machines = {}
for machine in PRESET_VALUES['MACHINES_TO_ADD']:
status, response = client.list_machines(mac=machine)
print '============================================'
print 'list machines status %s response %s' % (status, response)
if status >= 400:
sys.exit(1)
if status == 200 and response != []:
id = response[0]['id']
machine_macs[id] = response[0]['mac']
machine_id = response[0]['id']
machine_macs[machine_id] = response[0]['mac']
machines = response
print '================================='
print 'found machines are : %s' % machines
MACHINES_TO_ADD = PRESET_VALUES['MACHINES_TO_ADD']
if set(machine_macs.values()) != set(MACHINES_TO_ADD):
machines_to_add = PRESET_VALUES['MACHINES_TO_ADD']
if set(machine_macs.values()) != set(machines_to_add):
print 'only found macs %s while expected are %s' % (
machine_macs.values(), MACHINES_TO_ADD)
machine_macs.values(), machines_to_add)
sys.exit(1)
# list all adapters
status, response = client.list_adapters()
print '==============================='
print 'all adapters are: %s' % response
if status >= 400:
sys.exit(1)
adapters = response
adapter_ids = []
for adapter in adapters:
adapter_ids.append(adapter['id'])
adapter_id = adapter_ids[0]
adapter = adapters[adapter_id]
print '=========================='
print 'using adapter %s to deploy cluster' % adapter_id
# get all supported oses
supported_oses = adapter['supported_oses']
# get os_id
adapter_id = None
os_id = None
os_name = None
for supported_os in supported_oses:
if HOST_OS in supported_os.values():
os_id = supported_os['os_id']
os_name = supported_os['name']
break
print '===================================='
print 'use %s as host os, the os_id is %s' % (os_name, os_id)
# get flavor_id
flavor_id = None
flavors = adapter['flavors']
print '=============================='
print 'all flavors are: %s' % flavors
adapter_pattern = re.compile(PRESET_VALUES['DISTRIBUTED_SYSTEM_NAME_PATTERN'])
os_pattern = re.compile(PRESET_VALUES['OS_NAME_PATTERN'])
flavor_pattern = re.compile(PRESET_VALUES['FLAVOR_PATTERN'])
for adapter in adapters:
if (
'distributed_system_name' in adapter and
adapter_pattern.match(adapter['distributed_system_name'])
):
adapter_id = adapter['id']
for supported_os in adapter['supported_oses']:
if os_pattern.match(supported_os['name']):
os_id = supported_os['id']
break
for flavor in adapter['flavors']:
if flavor_pattern.match(flavor['name']):
flavor_id = flavor['id']
for flavor in flavors:
if flavor['name'] == PRESET_VALUES['FLAVOR']:
flavor_id = flavor['id']
if adapter_id and os_id and flavor_id:
break
print '===================================='
print 'cluster info: adapter_id: %s, os_id: %s, flavor_id: %s' % (
adapter_id, os_id, flavor_id)
print '======================================================='
print 'using adapter %s os %s flavor %s to deploy cluster' % (
adapter_id, os_id, flavor_id
)
# add a cluster
status, response = client.add_cluster(
@ -217,14 +217,18 @@ status, response = client.add_cluster(
os_id,
flavor_id
)
print '==============================================================='
print 'add cluster %s status %s: %s' % (CLUSTER_NAME, status, response)
if status < 400:
cluster = response
else:
status, response = client.list_clusters(name=CLUSTER_NAME)
print 'list clusters status %s: %s' % (status, response)
cluster = response[0]
print 'cluster already exists, fetching it'
if status >= 400:
sys.exit(1)
status, response = client.list_clusters(name=CLUSTER_NAME)
print '================================================================'
print 'list clusters %s status %s: %s' % (CLUSTER_NAME, status, response)
if status >= 400:
sys.exit(1)
cluster = response[0]
cluster_id = cluster['id']
print '=================='
@ -244,7 +248,10 @@ status, response = client.add_hosts_to_cluster(
cluster_id, machines_dict
)
print '==================================='
print 'add hosts %s to cluster: %s' % (machines_dict, response)
print 'add hosts %s to cluster status %s response %s' % (
machines_dict, status, response)
if status >= 400:
sys.exit(1)
# Add two subnets
subnet_1 = '10.145.89.0/24'
@ -252,14 +259,28 @@ subnet_2 = '192.168.100.0/24'
status, response = client.add_subnet(subnet_1)
print '=================='
print 'add subnet %s' % response
print 'add subnet %s status %s: %s' % (subnet_1, status, response)
if status >= 400:
sys.exit(1)
status, response = client.add_subnet(subnet_2)
print '=================='
print 'add subnet %s' % response
print 'add subnet %s status %s: %s' % (subnet_2, status, response)
if status >= 400:
sys.exit(1)
status, subnet1 = client.list_subnets(subnet=subnet_1)
print '==========================================================='
print 'list subnet %s status %s: %s' % (subnet_1, status, subnet1)
if status >= 400:
sys.exit(1)
status, subnet2 = client.list_subnets(subnet=subnet_2)
print '==========================================================='
print 'list subnet %s status %s: %s' % (subnet_2, status, subnet2)
if status >= 400:
sys.exit(1)
subnet1_id = subnet1[0]['id']
subnet2_id = subnet2[0]['id']
print '========================'
@ -268,6 +289,11 @@ print 'subnet2 has id: %s, subnet is %s' % (subnet2_id, subnet2)
# Add host network
status, response = client.list_cluster_hosts(cluster_id)
print '================================================'
print 'list cluster hosts status %s: %s' % (status, response)
if status >= 400:
sys.exit(1)
host = response[0]
host_id = host['id']
print '=================='
@ -281,7 +307,9 @@ status, response = client.add_host_network(
is_mgmt=True
)
print '======================='
print 'add eth0 network: %s' % response
print 'add eth0 network status %s: %s' % (status, response)
if status >= 400:
sys.exit(1)
status, response = client.add_host_network(
host_id,
@ -291,25 +319,27 @@ status, response = client.add_host_network(
is_promiscuous=True
)
print '======================='
print 'add eth1 network: %s' % response
print 'add eth1 network status %s: %s' % (status, response)
if status >= 400:
sys.exit(1)
# Update os config to cluster
cluster_os_config = {
'general': {
'language': LANGUAGE,
'timezone': TIMEZONE,
'language': PRESET_VALUES['LANGUAGE'],
'timezone': PRESET_VALUES['TIMEZONE'],
'http_proxy': PRESET_VALUES['PROXY'],
'https_proxy': HTTPS_PROXY,
'no_proxy': NO_PROXY,
'https_proxy': PRESET_VALUES['HTTPS_PROXY'],
'no_proxy': PRESET_VALUES['NO_PROXY'],
'ntp_server': PRESET_VALUES['NTP_SERVER'],
'dns_servers': PRESET_VALUES['NAMESERVERS'],
'domain': DOMAIN,
'search_path': SEARCH_PATH,
'domain': PRESET_VALUES['DOMAIN'],
'search_path': PRESET_VALUES['SEARCH_PATH'],
'default_gateway': PRESET_VALUES['GATEWAY']
},
'server_credentials': {
'username': SERVER_USERNAME,
'password': SERVER_PASSWORD
'username': PRESET_VALUES['SERVER_USERNAME'],
'password': PRESET_VALUES['SERVER_PASSWORD']
},
'partition': {
'/var': {
@ -323,9 +353,8 @@ cluster_os_config = {
cluster_package_config = {
'roles': PRESET_VALUES['ROLES_LIST'],
'security': {
'service_credential': {
'service_credentials': {
'image': {
'username': SERVICE_USERNAME,
'password': SERVICE_PASSWORD
@ -359,9 +388,39 @@ cluster_package_config = {
'password': SERVICE_PASSWORD
}
},
'dashboard_credential': {
'username': DASHBOARD_USERNAME,
'password': DASHBOARD_PASSWORD
'console_credentials': {
'admin': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
},
'compute': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
},
'dashboard': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
},
'image': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
},
'metering': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
},
'network': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
},
'object-store': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
},
'volume': {
'username': CONSOLE_USERNAME,
'password': CONSOLE_PASSWORD
}
}
},
'network_mapping': {
@ -379,15 +438,30 @@ status, response = client.update_cluster_config(
)
print '======================================='
print 'cluster %s has been updated to: %s' % (cluster_id, response)
print 'cluster %s update status %s: %s' % (
cluster_id, status, response)
if status >= 400:
sys.exit(1)
status, response = client.update_cluster_host(
cluster_id, host_id, roles=PRESET_VALUES['ROLES_LIST'])
print '================================================='
print 'update cluster host %s/%s status %s: %s' % (
cluster_id, host_id, status, response)
if status >= 400:
sys.exit(1)
# Review and deploy
status, response = client.review_cluster(
cluster_id, review={'hosts': [host_id]})
print '======================================='
print 'reviewing cluster status %s: %s' % (status, response)
if status >= 400:
sys.exit(1)
status, response = client.deploy_cluster(
cluster_id, deploy={'hosts': [host_id]})
print '======================================='
print 'deploy cluster status %s: %s' % (status, response)
if status >= 400:
sys.exit(1)

View File

@ -592,36 +592,36 @@ class Client(object):
def get_cluster_metadata(self, cluster_id):
return self._get('/clusters/%s/metadata' % cluster_id)
def update_cluster_config(self, cluster_id, put_os_config=None,
put_package_config=None, config_step=None,
def update_cluster_config(self, cluster_id, os_config=None,
package_config=None, config_step=None,
raw_data=None):
data = {}
if raw_data:
data = raw_data
if put_os_config:
data['put_os_config'] = put_os_config
if os_config:
data['os_config'] = os_config
if put_package_config:
data['put_package_config'] = put_package_config
if package_config:
data['package_config'] = package_config
if config_step:
data['config_step'] = config_step
return self._put('/clusters/%s/config' % cluster_id, data=data)
def patch_cluster_config(self, cluster_id, patched_os_config=None,
patched_package_config=None, config_step=None,
def patch_cluster_config(self, cluster_id, os_config=None,
package_config=None, config_step=None,
raw_data=None):
data = {}
if raw_data:
data = raw_data
if patched_os_config:
data['patched_os_config'] = patched_os_config
if os_config:
data['os_config'] = os_config
if patched_package_config:
data['patched_package_config'] = patched_package_config
if package_config:
data['package_config'] = package_config
if config_step:
data['config_step'] = config_step
@ -702,68 +702,68 @@ class Client(object):
return self._get('/clusterhosts/%s/config' % clusterhost_id)
def update_cluster_host_config(self, cluster_id, host_id,
put_os_config=None,
put_package_config=None,
os_config=None,
package_config=None,
raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if put_os_config:
data['put_os_config'] = put_os_config
if os_config:
data['os_config'] = os_config
if put_package_config:
data['put_package_config'] = put_package_config
if package_config:
data['package_config'] = package_config
return self._put('/clusters/%s/hosts/%s/config' %
(cluster_id, host_id), data=data)
def update_clusterhost_config(self, clusterhost_id, put_os_config=None,
put_package_config=None, raw_data=None):
def update_clusterhost_config(self, clusterhost_id, os_config=None,
package_config=None, raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if put_os_config:
data['put_os_config'] = put_os_config
if os_config:
data['os_config'] = os_config
if put_package_config:
data['put_package_config'] = put_package_config
if package_config:
data['package_config'] = package_config
return self._put('/clusterhosts/%s/config' % clusterhost_id,
data=data)
def patch_cluster_host_config(self, cluster_id, host_id,
patched_os_config=None,
patched_package_config=None,
os_config=None,
package_config=None,
raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if patched_os_config:
data['patched_os_config'] = patched_os_config
if os_config:
data['os_config'] = os_config
if patched_package_config:
data['patched_package_config'] = patched_package_config
if package_config:
data['package_config'] = package_config
return self._patch('/clusters/%s/hosts/%s/config' %
(cluster_id, host_id), data=data)
def patch_clusterhost_config(self, clusterhost_id, patched_os_config=None,
patched_package_config=None, raw_data=None):
def patch_clusterhost_config(self, clusterhost_id, os_config=None,
package_config=None, raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if patched_os_config:
data['patched_os_config'] = patched_os_config
if os_config:
data['os_config'] = os_config
if patched_package_config:
data['patched_package_config'] = patched_package_config
if package_config:
data['package_config'] = package_config
return self._patch('/clusterhosts/%s' % clusterhost_id, data=data)
@ -778,6 +778,52 @@ class Client(object):
return self._get('/clusters/%s/hosts/%s/state' %
(cluster_id, host_id))
def update_cluster_host(self, cluster_id, host_id,
roles=None, raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if roles:
data['roles'] = roles
return self._put('/clusters/%s/hosts/%s' %
(cluster_id, host_id), data=data)
def update_clusterhost(self, clusterhost_id,
roles=None, raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if roles:
data['roles'] = roles
return self._put('/clusterhosts/%s' % clusterhost_id, data=data)
def patch_cluster_host(self, cluster_id, host_id,
roles=None, raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if roles:
data['roles'] = roles
return self._patch('/clusters/%s/hosts/%s' %
(cluster_id, host_id), data=data)
def patch_clusterhost(self, clusterhost_id,
roles=None, raw_data=None):
data = {}
if raw_data:
data = raw_data
else:
if roles:
data['roles'] = roles
return self._patch('/clusterhosts/%s' % clusterhost_id, data=data)
def get_clusterhost_state(self, clusterhost_id):
return self._get('/clusterhosts/%s/state' % clusterhost_id)
@ -884,17 +930,17 @@ class Client(object):
def get_host_config(self, host_id):
return self._get('/hosts/%s/config' % host_id)
def update_host_config(self, host_id, put_os_config, raw_data=None):
def update_host_config(self, host_id, os_config, raw_data=None):
data = {}
data['put_os_config'] = put_os_config
data['os_config'] = os_config
if raw_data:
data.update(raw_data)
return self._put('/hosts/%s/config' % host_id, data=data)
def patch_host_config(self, host_id, patched_os_config, raw_data=None):
def patch_host_config(self, host_id, os_config, raw_data=None):
data = {}
data['patched_os_config'] = patched_os_config
data['os_config'] = os_config
if raw_data:
data.update(raw_data)