mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
This is a plugin that puts in ovm3 support ranging from 3.3.1 to 3.3.2. Basic functionality is in here, advanced networking etc.. Snapshots only work when a VM is stopped now due to the semantics of OVM's raw image implementation (so snapshots should work on a storage level underneath the hypervisor shrug) This closes #113 Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
589 lines
19 KiB
Python
589 lines
19 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# 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.
|
|
#
|
|
# TODO: Needs cleaning and sanitazation.
|
|
#
|
|
import logging
|
|
import time
|
|
import re
|
|
import os.path
|
|
import paramiko
|
|
import subprocess
|
|
import socket
|
|
import tempfile
|
|
import logging
|
|
import logging.handlers
|
|
|
|
from xen.util.xmlrpcclient import ServerProxy
|
|
from xmlrpclib import Error
|
|
from xen.xend import XendClient
|
|
from agent.api.base import Agent
|
|
from agent.lib.settings import get_api_version
|
|
from xen.xend import sxp
|
|
|
|
class CloudStack(Agent):
|
|
"""
|
|
Cloudstack plugin for OVM3.2.x.
|
|
"""
|
|
|
|
# exposed services
|
|
def get_services(self, version=None):
|
|
return {
|
|
'call': call,
|
|
'get_vncport': getVncPort,
|
|
'exec_domr': domrExec,
|
|
'check_domr_port': domrCheckPort,
|
|
'check_dom0_port': dom0CheckPort,
|
|
'check_domr_ssh': domrCheckSsh,
|
|
'check_dom0_ip': dom0CheckIp,
|
|
# rename to dom0StorageStatusCheck
|
|
'check_dom0_storage_health_check': dom0CheckStorageHealthCheck,
|
|
# dom0StorageStatus
|
|
'check_dom0_storage_health': dom0CheckStorageHealth,
|
|
'ovs_domr_upload_file': ovsDomrUploadFile,
|
|
'ovs_control_interface': ovsControlInterface,
|
|
'ovs_mkdirs': ovsMkdirs,
|
|
'ovs_check_file': ovsCheckFile,
|
|
'ovs_upload_ssh_key': ovsUploadSshKey,
|
|
'ovs_upload_file': ovsUploadFile,
|
|
'ovs_dom0_stats': ovsDom0Stats,
|
|
'ovs_domU_stats': ovsDomUStats,
|
|
'get_module_version': getModuleVersion,
|
|
'get_ovs_version': ovmVersion,
|
|
'ping': ping,
|
|
# 'patch': ovmCsPatch,
|
|
# 'ovs_agent_set_ssl': ovsAgentSetSsl,
|
|
# 'ovs_agent_set_port': ovsAgentSetPort,
|
|
# 'ovs_restart_agent': ovsRestartAgent,
|
|
}
|
|
|
|
def getName(self):
|
|
return self.__class__.__name__
|
|
|
|
domrPort = 3922
|
|
domrKeyFile = os.path.expanduser("~/.ssh/id_rsa.cloud")
|
|
domrRoot = "root"
|
|
domrTimeout = 10
|
|
|
|
""" The logger is here """
|
|
def Logger(level=logging.DEBUG):
|
|
logger = logging.getLogger('cloudstack-agent')
|
|
logger.setLevel(level)
|
|
handler = logging.handlers.SysLogHandler(address = '/dev/log')
|
|
logger.addHandler(handler)
|
|
return logger
|
|
|
|
# which version are we intended for?
|
|
def getModuleVersion():
|
|
return "0.1"
|
|
|
|
# call test
|
|
def call(msg):
|
|
return msg
|
|
|
|
def paramikoOpts(con, keyfile=domrKeyFile):
|
|
con.load_system_host_keys()
|
|
con.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
privatekeyfile = os.path.expanduser(keyfile)
|
|
key = paramiko.RSAKey.from_private_key_file(privatekeyfile)
|
|
return key
|
|
|
|
# execute something on domr
|
|
def domrExec(host, cmd, timeout=10, username=domrRoot, port=domrPort, keyfile=domrKeyFile):
|
|
ssh = paramiko.SSHClient()
|
|
pkey = paramikoOpts(ssh, keyfile)
|
|
ssh.connect(host, port, username, pkey=pkey, timeout=timeout)
|
|
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmd)
|
|
exit_status = ssh_stdout.channel.recv_exit_status()
|
|
ssh.close()
|
|
return { "rc": exit_status,
|
|
"out": ''.join(ssh_stdout.readlines()),
|
|
"err": ''.join(ssh_stderr.readlines()) };
|
|
|
|
# too bad sftp is missing.... Oh no it isn't it's just wrong in the svm config...
|
|
# root@s-1-VM:/var/cache/cloud# grep sftp /etc/ssh/sshd_config
|
|
# Subsystem sftp /usr/libexec/openssh/sftp-server
|
|
# root@s-1-VM:/var/cache/cloud# find / -name sftp-server -type f
|
|
# /usr/lib/openssh/sftp-server
|
|
#
|
|
def domrSftp(host, localfile, remotefile, timeout=10, username=domrRoot, port=domrPort, keyfile=domrKeyFile):
|
|
try:
|
|
paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG)
|
|
ssh = paramiko.SSHClient()
|
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
pkey = paramikoOpts(ssh, keyfile)
|
|
ssh.connect(host, port, username, pkey=pkey, timeout=timeout)
|
|
sftp = ssh.open_sftp()
|
|
# either:
|
|
sftp.put(localfile, remotefile)
|
|
# or:
|
|
# rf = sftp.open(remotefile, 'w')
|
|
# rf.write(content)
|
|
# rf.close()
|
|
sftp.close()
|
|
ssh.close()
|
|
except Exception, e:
|
|
raise e
|
|
return True
|
|
|
|
def domrScp(host, localfile, remotefile, timeout=10, username=domrRoot, port=domrPort, keyfile=domrKeyFile):
|
|
try:
|
|
target = "%s@%s:%s" % (username, host, remotefile)
|
|
cmd = ['scp', '-P', str(port), '-q', '-o', 'StrictHostKeyChecking=no', '-i', os.path.expanduser(keyfile), localfile, target]
|
|
rc = subprocess.call(cmd, shell=False)
|
|
if rc == 0:
|
|
return True
|
|
except Exception, e:
|
|
raise e
|
|
return False
|
|
|
|
# check a port on dom0
|
|
def dom0CheckPort(ip, port=domrPort, timeout=3):
|
|
return domrCheckPort(ip, port, timeout=timeout)
|
|
|
|
# check a port on domr
|
|
def domrCheckPort(ip, port=domrPort, timeout=3):
|
|
try:
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
s.settimeout(timeout)
|
|
s.connect((ip, port))
|
|
s.close()
|
|
except:
|
|
return False
|
|
return True
|
|
|
|
# check ssh
|
|
def domrCheckSsh(ip, port=domrPort, timeout=10):
|
|
x = domrExec(ip, "", port=port, timeout=timeout)
|
|
if (x.get("rc") == 0):
|
|
return True
|
|
return False
|
|
|
|
def grep(file, string):
|
|
c = 0
|
|
for line in open(file):
|
|
if string in line:
|
|
c = c + 1
|
|
return c
|
|
|
|
def ovmVersion():
|
|
path = "/etc/ovs-release"
|
|
return re.findall("[\d\.]+$", open(path).readline())[0]
|
|
|
|
# fix known bugs....
|
|
def ovmCsPatch(version="3.2.1"):
|
|
path = "/etc/xen/scripts"
|
|
netcom = "%s/xen-network-common.sh" % path
|
|
netbr = "%s/linuxbridge/ovs-vlan-bridge" % path
|
|
func = "setup_bridge_port"
|
|
# on 3.3.1 this moved to python2.6, but the restart time is already good
|
|
xendConst = "/usr/lib64/python2.4/site-packages/xen/xend/XendConstants.py"
|
|
xendRtime = "MINIMUM_RESTART_TIME"
|
|
netconf = "/etc/sysconfig/network"
|
|
netzero = "NOZEROCONF"
|
|
version = ovmVersion()
|
|
|
|
# this bug is present from 3.2.1 till 3.3.2
|
|
if grep(netcom, "_%s" % func) == 3 and grep(netbr, "_%s" % func) < 1:
|
|
_replaceInFile(netbr, func, "_%s" % func, True)
|
|
|
|
# zeroconf is in the way for local loopback, as it introduces a route
|
|
# on every interface that conflicts with what we want
|
|
if grep(netconf, "%s" % netzero) == 0:
|
|
text_file = open("%s" % netconf, "a")
|
|
text_file.write("%s=no\n" % netzero)
|
|
text_file.close()
|
|
else:
|
|
_replaceInFile(netconf,
|
|
netzero,
|
|
"no",
|
|
False)
|
|
|
|
# this is fixed in 3.3.1 and onwards
|
|
if version == "3.2.1":
|
|
if grep(xendConst, "%s = %s" % (xendRtime, 60)) == 1:
|
|
_replaceInFile(xendConst,
|
|
"%s = %s" % (xendRtime, 60),
|
|
"%s = %s" % (xendRtime, 10),
|
|
True)
|
|
ovsRestartXend()
|
|
|
|
return True
|
|
|
|
def _replaceInFile(file, orig, set, full=False):
|
|
replaced = False
|
|
if os.path.isfile(file):
|
|
import fileinput
|
|
for line in fileinput.FileInput(file, inplace=1):
|
|
line = line.rstrip('\n')
|
|
if full == False:
|
|
if re.search("%s=" % orig, line):
|
|
line = "%s=%s" % (orig, set)
|
|
replaced = True
|
|
else:
|
|
if re.search(orig, line):
|
|
line = line.replace(orig, set)
|
|
replaced = True
|
|
print line
|
|
return replaced
|
|
|
|
def _ovsIni(setting, change):
|
|
ini = "/etc/ovs-agent/agent.ini"
|
|
return _replaceInFile(ini, setting, change)
|
|
|
|
# enable/disable ssl for the agent
|
|
def ovsAgentSetSsl(state):
|
|
ena = "disable"
|
|
if state and state != "disable" and state.lower() != "false":
|
|
ena = "enable"
|
|
return _ovsIni("ssl", ena)
|
|
|
|
def ovsAgentSetPort(port):
|
|
return _ovsIni("port", port)
|
|
|
|
def ovsRestartAgent():
|
|
return restartService("ovs-agent")
|
|
|
|
def ovsRestartXend():
|
|
return restartService("xend")
|
|
|
|
# replace with popen
|
|
def restartService(service):
|
|
command = ['service', service, 'restart']
|
|
subprocess.call(command, shell=False)
|
|
return True
|
|
|
|
# sets the control interface and removes the route net entry
|
|
def ovsControlInterface(dev, cidr):
|
|
controlRoute = False
|
|
command = ['ip route show'];
|
|
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
|
|
while True:
|
|
line = p.stdout.readline()
|
|
if line == '' and p.poll() != None:
|
|
break
|
|
if line != '':
|
|
if re.search("%s" % (cidr), line) and not re.search("%s" % (dev), line):
|
|
command = ['ip', 'route', 'del', cidr]
|
|
subprocess.call(command, shell=False)
|
|
print "removed: %s" % (line)
|
|
elif re.search("%s" % (cidr), line) and re.search("%s" % (dev), line):
|
|
controlRoute = True
|
|
|
|
if controlRoute == False:
|
|
command = ['ip', 'route', 'add', cidr, 'dev', dev];
|
|
subprocess.call(command, shell=False)
|
|
|
|
command = ['ifconfig', dev, 'arp']
|
|
subprocess.call(command, shell=False)
|
|
# because OVM creates this and it breaks stuff if we're rebooted sometimes...
|
|
control = "/etc/sysconfig/network-scripts/ifcfg-%s" % (dev)
|
|
command = ['rm', control]
|
|
subprocess.call(command, shell=False)
|
|
return True
|
|
|
|
def dom0CheckIp(ip):
|
|
command = ['ip addr show']
|
|
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
|
|
while True:
|
|
line = p.stdout.readline()
|
|
if line != '':
|
|
if re.search("%s/" % (ip), line):
|
|
return True
|
|
else:
|
|
break
|
|
return False
|
|
|
|
def dom0CheckStorageHealthCheck(path, script, guid, timeout, interval):
|
|
storagehealth="storagehealth.py"
|
|
path="/opt/cloudstack/bin"
|
|
running = False
|
|
started = False
|
|
c = 0
|
|
log = Logger()
|
|
command = ["pgrep -fl %s | grep -v cloudstack.py" % (storagehealth)]
|
|
|
|
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
|
|
for x in p.stdout:
|
|
if x:
|
|
log.debug("%s is running %s" % (storagehealth, x.rstrip('\n')))
|
|
running = True
|
|
c = c + 1
|
|
if c < 1:
|
|
started = True
|
|
command = ["%s/%s -g %s -t %d -i %d" % (path, storagehealth, guid, timeout, interval)]
|
|
log.warning("%s started: %s/%s for %s with timeout %d and interval %d"
|
|
% (storagehealth, path, storagehealth, guid, timeout, interval))
|
|
subprocess.call(command, shell=True, close_fds=True)
|
|
|
|
return [running, started]
|
|
|
|
def dom0CheckStorageHealth(path, script, guid, timeout):
|
|
response = None
|
|
delay = timeout
|
|
log = Logger()
|
|
command = ["%s/%s -g %s -t %s -s" % (path, script, guid, timeout)]
|
|
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
|
|
p.wait()
|
|
if p.returncode == 0:
|
|
log.warning("primary storage is accessible for %s" % (guid))
|
|
return True
|
|
else:
|
|
log.warning("primary storage NOT is accessible for %s" % (guid))
|
|
return False
|
|
# while True:
|
|
# line = p.stdout.readline()
|
|
# if line != '':
|
|
# if re.search("False", line):
|
|
# log.debug("primary storage NOT is accessible for %s, %s" % (guid, line))
|
|
# return False
|
|
# else:
|
|
# break
|
|
# return True
|
|
|
|
# create a dir if we need it
|
|
def ovsMkdirs(dir, mode=0700):
|
|
if not os.path.exists(dir):
|
|
return os.makedirs(dir, mode)
|
|
return True
|
|
|
|
# if a file exists, easy
|
|
def ovsCheckFile(file):
|
|
if os.path.isfile(file):
|
|
return True
|
|
return False
|
|
|
|
def ovsUploadFile(path, filename, content):
|
|
file = "%s/%s" % (path, filename)
|
|
try:
|
|
ovsMkdirs(os.path.expanduser(path))
|
|
except Error, v:
|
|
print "path was already there %s" % path
|
|
|
|
try:
|
|
text_file = open("%s" % file, "w")
|
|
text_file.write("%s" % content)
|
|
text_file.close()
|
|
except Error, v:
|
|
print "something went wrong creating %s: %s" % (file, v)
|
|
return False
|
|
return True
|
|
|
|
def ovsDomrUploadFile(domr, path, file, content):
|
|
remotefile = "%s/%s" % (path, file)
|
|
try:
|
|
temp = tempfile.NamedTemporaryFile()
|
|
temp.write(content)
|
|
temp.flush()
|
|
# domrSftp(domr, temp.name, remotefile)
|
|
domrScp(domr, temp.name, remotefile)
|
|
temp.close
|
|
except Exception, e:
|
|
print "problem uploading file %s/%s to %s, %s" % (path, file, domr, e)
|
|
raise e
|
|
return True
|
|
|
|
# upload keys
|
|
def ovsUploadSshKey(keyfile, content):
|
|
keydir = os.path.expanduser("~/.ssh")
|
|
return ovsUploadFile(keydir, keyfile, content)
|
|
|
|
# older python,
|
|
def ovsDom0Stats(bridge):
|
|
stats = {}
|
|
stats['cpu'] = "%s" % (100 - float(os.popen("top -b -n 1 | grep Cpu\(s\): | cut -d% -f4|cut -d, -f2").read()))
|
|
stats['free'] = "%s" % (1048576 * int(os.popen("xm info | grep free_memory | awk '{ print $3 }'").read()))
|
|
stats['total'] = "%s" % (1048576 * int(os.popen("xm info | grep total_memory | awk '{ print $3 }'").read()))
|
|
stats['tx'] = os.popen("netstat -in | grep %s | head -1 | awk '{print $4 }'" % bridge).read()
|
|
stats['rx'] = os.popen("netstat -in | grep %s | head -1 | awk '{print $8 }'" % bridge).read()
|
|
return stats
|
|
|
|
def getVncPort(domain):
|
|
port = "0"
|
|
if re.search("\w-(\d+-)?\d+-VM", domain):
|
|
server = ServerProxy(XendClient.uri)
|
|
dom = server.xend.domain(domain, 1)
|
|
devices = [child for child in sxp.children(dom)
|
|
if len(child) > 0 and child[0] == "device"]
|
|
vfbs_sxp = map(lambda x: x[1], [device for device in devices
|
|
if device[1][0] == "vfb"])[0]
|
|
loc = [child for child in vfbs_sxp
|
|
if child[0] == "location"][0][1]
|
|
listner, port = loc.split(":")
|
|
else:
|
|
print "no valid domain: %s" % domain
|
|
return port
|
|
|
|
def get_child_by_name(exp, childname, default=None):
|
|
try:
|
|
return [child for child in sxp.children(exp)
|
|
if child[0] == childname][0][1]
|
|
except:
|
|
return default
|
|
|
|
def ovsDomUStats(domain):
|
|
_rd_bytes = 0
|
|
_wr_bytes = 0
|
|
_rd_ops = 0
|
|
_wr_ops = 0
|
|
_tx_bytes = 0
|
|
_rx_bytes = 0
|
|
stats = {}
|
|
server = ServerProxy(XendClient.uri)
|
|
dominfo = server.xend.domain(domain, 1)
|
|
domid = get_child_by_name(dominfo, "domid")
|
|
|
|
# vbds
|
|
devs = server.xend.domain.getDeviceSxprs(domain, 'vbd')
|
|
devids = [dev[0] for dev in devs]
|
|
for dev in devids:
|
|
sys_path = "/sys/devices/%s-%s-%s/statistics" % ("vbd", domid, dev)
|
|
_rd_bytes += long(open("%s/rd_sect" % sys_path).readline().strip())
|
|
_wr_bytes += long(open("%s/wr_sect" % sys_path).readline().strip())
|
|
_rd_ops += long(open("%s/rd_req" % sys_path).readline().strip())
|
|
_wr_ops += long(open("%s/wr_req" % sys_path).readline().strip())
|
|
|
|
# vifs
|
|
devs = server.xend.domain.getDeviceSxprs(domain, 'vif')
|
|
devids = [dev[0] for dev in devs]
|
|
for dev in devids:
|
|
vif = "vif%s.%s" % (domid, dev)
|
|
sys_path = "/sys/devices/%s-%s-%s/net/%s/statistics" % ("vif", domid, dev, vif)
|
|
_tx_bytes += long(open("%s/tx_bytes" % sys_path).readline().strip())
|
|
_rx_bytes += long(open("%s/rx_bytes" % sys_path).readline().strip())
|
|
|
|
epoch = time.time()
|
|
stats['rd_bytes'] = "%s" % (_rd_bytes * 512)
|
|
stats['wr_bytes'] = "%s" % (_wr_bytes * 512)
|
|
stats['rd_ops'] = "%s" % (_rd_ops)
|
|
stats['wr_ops'] = "%s" % (_wr_ops)
|
|
stats['tx_bytes'] = "%s" % (_tx_bytes)
|
|
stats['rx_bytes'] = "%s" % (_rx_bytes)
|
|
stats['cputime'] = "%s" % get_child_by_name(dominfo, "cpu_time")
|
|
stats['uptime'] = "%s" % (epoch - get_child_by_name(dominfo, "start_time"))
|
|
stats['vcpus'] = "%s" % get_child_by_name(dominfo, "online_vcpus")
|
|
return stats
|
|
|
|
def ping(host, count=3):
|
|
if os.system("ping -c %s %s " % (count, host)) == 0:
|
|
return True
|
|
return False
|
|
|
|
# add SystemVM stuff here....
|
|
#
|
|
|
|
#
|
|
# Self deploy and integration, not de-integration
|
|
# should return False if fails
|
|
#
|
|
# install us if we are missing in:
|
|
# /usr/lib64/python2.4/site-packages/agent/api
|
|
# and add our hooks in:
|
|
# /usr/lib64/python2.4/site-packages/agent/target/api.py
|
|
if __name__ == '__main__':
|
|
from distutils.sysconfig import get_python_lib
|
|
from agent.target.api import MODULES
|
|
from shutil import copyfile
|
|
import inspect, os, hashlib, getopt, sys
|
|
|
|
# default vars
|
|
exist = False
|
|
agentpath = "%s/agent" % (get_python_lib(1))
|
|
api = "%s/target/api.py" % (agentpath)
|
|
modpath = "%s/api" % (agentpath)
|
|
ssl = "disable"
|
|
port = 0
|
|
exec_sub = ""
|
|
exec_opts = ""
|
|
|
|
# get options
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:], "eosp::",
|
|
[ 'port=', 'ssl=', 'exec=', 'opts='])
|
|
except getopt.GetoptError:
|
|
print "Available Options: --port=<number>, --ssl=<true|false>, --exec=<method>, --opts=<arg1,arg2..>"
|
|
sys.exit()
|
|
|
|
for o, a in opts:
|
|
if o in ('-s', '--ssl'):
|
|
ssl = a
|
|
if o in ('-p', '--port'):
|
|
port = int(a)
|
|
if o in ('-e', '--exec'):
|
|
exec_sub = a
|
|
if o in ('-o', '--opts'):
|
|
exec_opts = a
|
|
|
|
if exec_sub != "":
|
|
func = "%s(%s)" % (exec_sub, exec_opts)
|
|
print "exec: %s" % (func)
|
|
if exec_opts:
|
|
opts = exec_opts.split(',')
|
|
else:
|
|
opts = ""
|
|
print locals()[exec_sub](*opts)
|
|
sys.exit()
|
|
|
|
# check if we're in the modules already
|
|
cs = CloudStack()
|
|
for mod in MODULES:
|
|
if re.search(cs.getName(), "%s" % (mod)):
|
|
exist = True
|
|
|
|
# if we're not:
|
|
if not exist:
|
|
if os.path.isfile(api):
|
|
import fileinput
|
|
for line in fileinput.FileInput(api, inplace=1):
|
|
line = line.rstrip('\n')
|
|
if re.search("import common", line):
|
|
line = "%s, cloudstack" % (line)
|
|
if re.search("MODULES", line):
|
|
n = cs.getName()
|
|
line = "%s\n\t%s.%s," % (line, n.lower(), n)
|
|
print line
|
|
print "Api inserted, %s in %s" % (cs.getName(), api)
|
|
else:
|
|
print "Api missing, %s" % (api)
|
|
else:
|
|
print "Api present, %s in %s" % (cs.getName(), api)
|
|
|
|
# either way check our version and install if checksum differs
|
|
modfile = "%s/%s.py" % (modpath, cs.getName().lower())
|
|
me = os.path.abspath(__file__)
|
|
if os.path.isfile(modfile):
|
|
if hashlib.md5(open(me).read()).hexdigest() != hashlib.md5(open(modfile).read()).hexdigest():
|
|
print "Module copy, %s" % (modfile)
|
|
copyfile(me, modfile)
|
|
else:
|
|
print "Module correct, %s" % (modfile)
|
|
else:
|
|
print "Module copy, %s" % (modfile)
|
|
copyfile(me, modfile)
|
|
|
|
# setup ssl and port
|
|
if ssl:
|
|
ovsAgentSetSsl(ssl)
|
|
if port > 1024:
|
|
ovsAgentSetPort(port)
|
|
|
|
# restart either way
|
|
ovmCsPatch()
|
|
ovsRestartAgent()
|