mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
* DB : Add support for MySQL 8
- Splits commands to create user and grant access on database, the old
statement is no longer supported by MySQL 8.x
- `NO_AUTO_CREATE_USER` is no longer supported by MySQL 8.x so remove
that from db.properties conn parameters
For mysql-server 8.x setup the following changes were added/tested to
make it work with CloudStack in /etc/mysql/mysql.conf.d/mysqld.cnf and
then restart the mysql-server process:
server_id = 1
sql-mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_ENGINE_SUBSTITUTION"
innodb_rollback_on_timeout=1
innodb_lock_wait_timeout=600
max_connections=1000
log-bin=mysql-bin
binlog-format = 'ROW'
default-authentication-plugin=mysql_native_password
Notice the last line above, this is to reset the old password based
authentication used by MySQL 5.x.
Developers can set empty password as follows:
> sudo mysql -u root
ALTER USER 'root'@'localhost' IDENTIFIED BY '';
In libvirt repository, there are two related commits
2019-08-23 13:13 Daniel P. Berrangé ● rpm: don't enable socket activation in upgrade if --listen present
2019-08-22 14:52 Daniel P. Berrangé ● remote: forbid the --listen arg when systemd socket activation
In libvirt.spec.in
/bin/systemctl mask libvirtd.socket >/dev/null 2>&1 || :
/bin/systemctl mask libvirtd-ro.socket >/dev/null 2>&1 || :
/bin/systemctl mask libvirtd-admin.socket >/dev/null 2>&1 || :
/bin/systemctl mask libvirtd-tls.socket >/dev/null 2>&1 || :
/bin/systemctl mask libvirtd-tcp.socket >/dev/null 2>&1 || :
Co-authored-by: Wei Zhou <w.zhou@global.leaseweb.com>
Co-authored-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
183 lines
5.9 KiB
Python
Executable File
183 lines
5.9 KiB
Python
Executable File
#!/usr/bin/python3 -W ignore::DeprecationWarning
|
|
# -*- coding: utf-8 -*-
|
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you 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 os
|
|
import sys
|
|
import glob
|
|
from random import choice
|
|
import string
|
|
from optparse import OptionParser
|
|
import mysql.connector
|
|
import paramiko
|
|
from threading import Thread
|
|
|
|
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
|
|
# ---- We do this so cloud_utils can be looked up in the following order:
|
|
# ---- 1) Sources directory
|
|
# ---- 2) waf configured PYTHONDIR
|
|
# ---- 3) System Python path
|
|
for pythonpath in (
|
|
"@PYTHONDIR@",
|
|
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
|
|
):
|
|
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
|
|
# ---- End snippet of code ----
|
|
from cloud_utils import check_call, CalledProcessError, read_properties
|
|
|
|
cfg = "@MSCONF@/db.properties"
|
|
|
|
#---------------------- option parsing and command line checks ------------------------
|
|
|
|
|
|
usage = """%prog <license file> <-a | host names / IP addresses...>
|
|
|
|
This command deploys the license file specified in the command line into a specific XenServer host or all XenServer hosts known to the management server."""
|
|
|
|
parser = OptionParser(usage=usage)
|
|
parser.add_option("-a", "--all", action="store_true", dest="all", default=False,
|
|
help="deploy to all known hosts rather that a single host")
|
|
|
|
#------------------ functions --------------------
|
|
|
|
def e(msg): parser.error(msg)
|
|
|
|
def getknownhosts(host,username,password):
|
|
conn = mysql.connector.connect(host=host, user=username, password=password)
|
|
cur = conn.cursor()
|
|
cur.execute("SELECT h.private_ip_address,d.value FROM cloud.host h inner join cloud.host_details d on (h.id = d.host_id) where d.name = 'username' and setup = 1")
|
|
usernames = dict(cur.fetchall())
|
|
cur.execute("SELECT h.private_ip_address,d.value FROM cloud.host h inner join cloud.host_details d on (h.id = d.host_id) where d.name = 'password' and setup = 1")
|
|
passwords = dict(cur.fetchall())
|
|
creds = dict( [ [x,(usernames[x],passwords[x])] for x in list(usernames.keys()) ] )
|
|
cur.close()
|
|
conn.close()
|
|
return creds
|
|
|
|
def splitlast(string,splitter):
|
|
splitted = string.split(splitter)
|
|
first,last = splitter.join(splitted[:-1]),splitted[-1]
|
|
return first,last
|
|
|
|
def parseuserpwfromhosts(hosts):
|
|
creds = {}
|
|
for host in hosts:
|
|
user = "root"
|
|
password = ""
|
|
if "@" in host:
|
|
user,host = splitlast(host,"@")
|
|
if ":" in user:
|
|
user,password = splitlast(user,":")
|
|
creds[host] = (user,password)
|
|
return creds
|
|
|
|
class XenServerConfigurator(Thread):
|
|
|
|
def __init__(self,host,user,password,keyfiledata):
|
|
Thread.__init__(self)
|
|
self.host = host
|
|
self.user = user
|
|
self.password = password
|
|
self.keyfiledata = keyfiledata
|
|
self.retval = None # means all's good
|
|
self.stdout = ""
|
|
self.stderr = ""
|
|
self.state = 'initialized'
|
|
|
|
def run(self):
|
|
try:
|
|
self.state = 'running'
|
|
c = paramiko.SSHClient()
|
|
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
c.connect(self.host,username=self.user,password=self.password)
|
|
sftp = c.open_sftp()
|
|
sftp.chdir("/tmp")
|
|
f = sftp.open("xen-license","w")
|
|
f.write(self.keyfiledata)
|
|
f.close()
|
|
sftp.close()
|
|
stdin,stdout,stderr = c.exec_command("xe host-license-add license-file=/tmp/xen-license")
|
|
c.exec_command("false")
|
|
self.stdout = stdout.read(-1)
|
|
self.stderr = stderr.read(-1)
|
|
self.retval = stdin.channel.recv_exit_status()
|
|
c.close()
|
|
if self.retval != 0: self.state = 'failed'
|
|
else: self.state = 'finished'
|
|
|
|
except Exception as e:
|
|
self.state = 'failed'
|
|
self.retval = e
|
|
#raise
|
|
|
|
def __str__(self):
|
|
if self.state == 'failed':
|
|
return "<%s XenServerConfigurator on %s@%s: %s>"%(self.state,self.user,self.host,str(self.retval))
|
|
else:
|
|
return "<%s XenServerConfigurator on %s@%s>"%(self.state,self.user,self.host)
|
|
|
|
#------------- actual code --------------------
|
|
|
|
(options, args) = parser.parse_args()
|
|
|
|
try:
|
|
licensefile,args = args[0],args[1:]
|
|
except IndexError: e("The first argument must be the license file to use")
|
|
|
|
if options.all:
|
|
if len(args) != 0: e("IP addresses cannot be specified if -a is specified")
|
|
config = read_properties(cfg)
|
|
creds = getknownhosts(config["db.cloud.host"],config["db.cloud.username"],config["db.cloud.password"])
|
|
hosts = list(creds.keys())
|
|
else:
|
|
if not args: e("You must specify at least one IP address, or -a")
|
|
hosts = args
|
|
creds = parseuserpwfromhosts(hosts)
|
|
|
|
try:
|
|
keyfiledata = file(licensefile).read(-1)
|
|
except OSError as e:
|
|
sys.stderr.write("The file %s cannot be opened"%licensefile)
|
|
sys.exit(1)
|
|
|
|
configurators = []
|
|
for host,(user,password) in list(creds.items()):
|
|
configurators.append ( XenServerConfigurator(host,user,password,keyfiledata ) )
|
|
|
|
|
|
for c in configurators: c.start()
|
|
|
|
for c in configurators:
|
|
print(c.host + "...", end=' ')
|
|
c.join()
|
|
if c.state == 'failed':
|
|
if c.retval:
|
|
msg = "failed with return code %s: %s%s"%(c.retval,c.stdout,c.stderr)
|
|
msg = msg.strip()
|
|
print(msg)
|
|
else: print("failed: %s"%c.retval)
|
|
else:
|
|
print("done")
|
|
|
|
successes = len( [ a for a in configurators if not a.state == 'failed' ] )
|
|
failures = len( [ a for a in configurators if a.state == 'failed' ] )
|
|
|
|
print("%3s successes"%successes)
|
|
print("%3s failures"%failures)
|