pax_global_header 0000666 0000000 0000000 00000000064 13444400517 0014514 g ustar 00root root 0000000 0000000 52 comment=73a2600993a12576c45a9bb8de0e3bbdf9418e8c
cc-server-master-bin/ 0000775 0000000 0000000 00000000000 13444400517 0015010 5 ustar 00root root 0000000 0000000 cc-server-master-bin/bin/ 0000775 0000000 0000000 00000000000 13444400517 0015560 5 ustar 00root root 0000000 0000000 cc-server-master-bin/bin/cc-addaccount 0000775 0000000 0000000 00000006150 13444400517 0020200 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
#coding=utf8
# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl. If not, see .
'''
Script used to create an account on cc-server account directory.
'''
import logging
import logging.handlers
import os
from getpass import getpass
from pwd import getpwnam
from grp import getgrnam
from optparse import OptionParser
from cloudcontrol.server.conf import CCConf
DEFAULT_ACCOUNT_DIRECTORY = '/var/lib/cc-server/'
DEFAULT_ROLE = 'cli'
UMASK = 0o0177
DEFAULT_CHOWN_USER = 'cc-server'
DEFAULT_CHOWN_GROUP = 'cc-server'
if __name__ == '__main__':
op = OptionParser(usage='%prog [options] login')
op.add_option('-d', '--directory', default=DEFAULT_ACCOUNT_DIRECTORY,
help='account directory')
op.add_option('-p', '--password', action='store_true',
help='ask for the password')
op.add_option('-c', '--copy', default=None,
help='copy this already existing account')
op.add_option('-r', '--role', default=None, choices=('cli', 'hv', 'host'),
help='specify the role (default %default)')
op.add_option('-u', '--user', default=DEFAULT_CHOWN_USER,
help='User running cc-server (default %default)')
op.add_option('-g', '--group', default=DEFAULT_CHOWN_GROUP,
help='Group running cc-server (default %default)')
options, args = op.parse_args()
if len(args) != 1:
op.error('a login must be provided')
if options.role is not None and options.copy is not None:
op.error('you can\'t specify a role for a copy')
if options.role is None:
role = DEFAULT_ROLE
else:
role = options.role
logger = logging.getLogger()
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
logger.addHandler(handler)
conf = CCConf(logger, options.directory)
if options.password:
password = getpass('Password: ')
password_again = getpass('Password (again): ')
if password != password_again:
op.error('password mismatch')
elif not password:
op.error('no password provided')
else:
password = None
os.umask(UMASK)
if options.copy is None:
conf.create_account(args[0], role, password)
else:
conf.copy_account(options.copy, args[0], password)
# Chown the files:
uid = getpwnam(options.user).pw_uid
gid = getgrnam(options.group).gr_gid
filename = os.path.join(options.directory, '%s.json' % args[0])
os.chown(filename, uid, gid)
cc-server-master-bin/bin/cc-server 0000775 0000000 0000000 00000016457 13444400517 0017414 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
#coding=utf8
# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl. If not, see .
from cloudcontrol.common.helpers.logger import patch_logging; patch_logging()
import os
import sys
import atexit
import logging
import logging.handlers
import ConfigParser
import signal
from optparse import OptionParser
from pwd import getpwnam
from grp import getgrnam
from daemon import DaemonContext
from cloudcontrol.server.server import CCServer
from cloudcontrol.server import __version__
DEFAULT_CONFIG_FILE = '/etc/cc-server.conf'
DEFAULT_UMASK = 0o0177
DEFAULT_CONFIGURATION = {
'daemonize': False,
'user': '',
'group': '',
'pidfile': '',
'umask': '077',
'port': 1984,
'debug': False,
'account_db': None, # None = mandatory option
'interface': '127.0.0.1',
'ssl_cert': None,
'ssl_key': None,
'maxcon': 600,
'maxidle': 120,
}
# WORKAROUND ENCODING LOOKUP
import codecs
codecs.lookup('string-escape')
codecs.lookup('raw-unicode-escape')
# END OF WORKAROUND
class EncodingFormatter(logging.Formatter, object):
def __init__(self, fmt=None, datefmt=None, encoding='utf-8'):
super(EncodingFormatter, self).__init__(fmt, datefmt)
self._encoding = encoding
def formatException(self, ei):
expt = super(EncodingFormatter, self).formatException( ei)
if isinstance(expt, str):
expt = expt.decode(self._encoding, 'replace')
return expt
def format(self, record):
msg = super(EncodingFormatter, self).format(record)
if isinstance(msg, unicode):
msg = msg.encode(self._encoding, 'replace')
return msg
def run_server(options):
# Setup logging facility:
level = logging.INFO
if options['debug'] in (True, 'yes', 'true'):
level = logging.DEBUG
logger = logging.getLogger()
logger.setLevel(level)
if options['stdout']:
handler = logging.StreamHandler()
fmt = EncodingFormatter('[%(asctime)s] '
'\x1B[30;47m%(name)s\x1B[0m '
'\x1B[30;42m%(levelname)s\x1B[0m: '
'%(message)s')
else:
facility = logging.handlers.SysLogHandler.LOG_DAEMON
handler = logging.handlers.SysLogHandler(address='/dev/log',
facility=facility)
fmt = EncodingFormatter('%(name)s: %(levelname)s %(message)s')
handler.setFormatter(fmt)
logger.addHandler(handler)
server = CCServer(logger.getChild('cc-server'),
conf_dir=options['account_db'],
maxcon=int(options['maxcon']),
maxidle=int(options['maxidle']),
port=int(options['port']),
address=options['interface'],
keyfile=options['ssl_key'],
certfile=options['ssl_cert'])
def shutdown_handler(signum, frame):
'''
Handler called when SIGINT is emitted.
'''
server.rpc.shutdown()
logging.info('Server properly exited by SIGINT')
watcher_sigint = server.rpc.loop.signal(signal.SIGINT, shutdown_handler)
watcher_sigstop = server.rpc.loop.signal(signal.SIGTERM, shutdown_handler)
watcher_sigint.start()
watcher_sigstop.start()
try:
server.run()
except Exception as err:
logging.critical('Server failed: %s', err)
import traceback
traceback.print_exc(file=sys.stdout)
sys.exit(3)
if __name__ == '__main__':
op = OptionParser(version='%%prog v%s' % __version__)
op.add_option('-c', '--config', default=DEFAULT_CONFIG_FILE,
help='configuration file (default: %default)')
op.add_option('-d', '--daemonize', action='store_true',
help='run as a daemon')
op.add_option('-f', '--foreground', action='store_false', dest='daemonize',
help='don\'t run as a daemon')
op.add_option('-p', '--pidfile', help='write pidfile to the path')
op.add_option('-k', '--umask', help='set the umask of the process')
op.add_option('-u', '--user', help='run as user')
op.add_option('-g', '--group', help='run as group')
op.add_option('-s', '--stdout', action='store_true', default=False,
help='log in stdout instead of syslog')
cliopts, args = op.parse_args()
# Reading the config file:
config = ConfigParser.SafeConfigParser()
config.read(cliopts.config)
try:
options = dict(config.items('server'))
except ConfigParser.NoSectionError:
sys.stderr.write("Configuration error: 'server' section must exist "
"in '%s'\n" % cliopts.config)
sys.exit(1)
# Applying default config file options:
for opt, default in DEFAULT_CONFIGURATION.iteritems():
if opt not in options or not options[opt]:
if default is None:
sys.stderr.write("Configuration error: you must specify '%s' "
"option in '%s' !\n" % (opt, cliopts.config))
sys.exit(1)
else:
options[opt] = default
# Merge cli options and .conf file options:
for opt in ('daemonize', 'pidfile', 'umask', 'user', 'group', 'stdout'):
if getattr(cliopts, opt) is not None:
options[opt] = getattr(cliopts, opt)
# Create option set for the daemonization process:
daemon_opts = {}
daemonize = options['daemonize']
if isinstance(daemonize, str):
daemonize = daemonize in ('yes', 'true')
daemon_opts['detach_process'] = daemonize
daemon_opts['umask'] = int(options['umask'], 8)
if options['user']:
if options['user'].isdigit():
daemon_opts['uid'] = int(options['user'])
else:
daemon_opts['uid'] = getpwnam(options['user']).pw_uid
if options['group']:
if options['group'].isdigit():
daemon_opts['gid'] = int(options['group'])
else:
daemon_opts['gid'] = getgrnam(options['group']).gr_gid
if not daemonize:
daemon_opts['stderr'] = sys.stderr
daemon_opts['stdout'] = sys.stderr
# I've to write myself the pidfile because the daemon library write it
# after the privilege downgrade:
if options['pidfile']:
pidfile = open(cliopts.pidfile, 'w')
daemon_opts['files_preserve'] = [pidfile]
else:
pidfile = None
with DaemonContext(**daemon_opts):
if pidfile is not None:
pidfile.write('%s' % os.getpid())
pidfile.flush()
@atexit.register
def clean_pidfile():
pidfile.seek(0)
pidfile.truncate()
pidfile.flush()
run_server(options)