Merge branch 'master' into conductor-openstack-style

Conflicts:
	conductor/bin/app.py
	conductor/conductor/app.py
	conductor/conductor/commands/cloud_formation.py
	conductor/conductor/commands/windows_agent.py
	conductor/conductor/rabbitmq.py
	conductor/conductor/windows_agent.py
This commit is contained in:
Stan Lagun 2013-03-26 14:46:09 +04:00
commit ad0e834457
45 changed files with 723 additions and 311 deletions

View File

@ -8,3 +8,4 @@ config_drive_cdrom=false
verbose=true
logdir=C:\Program Files (x86)\Cloudbase Solutions\Cloudbase-Init\log\
logfile=cloudbase-init.log
plugins=cloudbaseinit.plugins.windows.userdata.UserDataPlugin

View File

@ -16,6 +16,7 @@ RABBIT_PASSWORD=$lab_password
SERVICE_PASSWORD=$lab_password
SERVICE_TOKEN=tokentoken
ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng
ENABLED_SERVICES+=,conductor,portas
LOGFILE=/opt/stack/devstack/stack.sh.log
SCREEN_LOGDIR=/opt/stack/log/

View File

@ -1,6 +1,7 @@
#!/bin/bash
DEVSTACK_DIR=/home/stack/devstack
INSTALL_DIR=/opt/stack
MYSQL_DB_TMPFS=true
MYSQL_DB_TMPFS_SIZE=128M
@ -8,7 +9,6 @@ MYSQL_DB_TMPFS_SIZE=128M
NOVA_CACHE_TMPFS=true
NOVA_CACHE_TMPFS_SIZE=24G
#======================================
source $DEVSTACK_DIR/openrc admin admin
source ./functions.sh

View File

@ -20,6 +20,7 @@ $DEVSTACK_DIR/stack.sh
# Executing post-stack actions
#===============================================================================
source ./post-stack.sh no-localrc
source ./start-keero.sh no-localrc
#===============================================================================

View File

@ -0,0 +1,25 @@
#!/bin/bash
if [[ -z "$1" ]] ; then
source ./localrc
fi
die_if_not_set INSTALL_DIR
# Starting Portas
#================
if [[ ! -d "$INSTALL_DIR/portas" ]] ; then
mkdir -p "$INSTALL_DIR/portas"
fi
cp "$INSTALL_DIR/keero/portas/etc" "$INSTALL_DIR/portas/etc"
screen_it portas "cd $INSTALL_DIR/portas && portas-api --config-file=$INSTALL_DIR/portas/etc/portas-api.conf"
#================
# Starting Conductor
#===================
screen_it conductor "cd $INSTALL_DIR/keero/conductor && bash ./tools/with_venv.sh ./bin/app.py"
#===================

View File

@ -18,5 +18,6 @@ $DEVSTACK_DIR/unstack.sh
# Executing post-unstack actions
#===============================================================================
source ./post-unstack.sh no-localrc
source ./stop-keero.sh no-localrc
#===============================================================================

View File

@ -0,0 +1,12 @@
#!/bin/bash
if [[ -z "$1" ]] ; then
source ./localrc
fi
# Stopping Keero components
#==========================
for serv in conductor portas ; do
screen -S $SCREEN_NAME -p $serv -X kill
done
#==========================

View File

@ -40,4 +40,3 @@ xml_code_engine.XmlCodeEngine.register_function(
xml_code_engine.XmlCodeEngine.register_function(
prepare_user_data, "prepare_user_data")

View File

@ -21,7 +21,6 @@ class CommandDispatcher(command.CommandBase):
return result
def has_pending_commands(self):
result = False
for command in self._command_map.values():

View File

@ -48,4 +48,4 @@ class Context(object):
return str(self._data)
if self._parent:
return str(self._parent)
return str({})
return str({})

View File

@ -38,6 +38,7 @@ def merge_dicts(dict1, dict2, max_levels=0):
result[key] = value
return result
def find(f, seq):
"""Return first item in sequence where f(item) == True."""
index = 0

View File

@ -25,12 +25,9 @@ class Reporter(object):
message=msg,
key='task-reports')
def _report_func(context, id, entity, text, **kwargs):
reporter = context['/reporter']
return reporter._report_func(id, entity, text, **kwargs)
xml_code_engine.XmlCodeEngine.register_function(_report_func, "report")

View File

@ -5,6 +5,7 @@ import re
import xml_code_engine
import function_context
class Workflow(object):
def __init__(self, filename, data, command_dispatcher, config, reporter):
self._data = data
@ -84,7 +85,6 @@ class Workflow(object):
else:
return position + suffix.split('.')
@staticmethod
def _select_func(context, path='', source=None, **kwargs):
@ -102,7 +102,6 @@ class Workflow(object):
context['/dataSource'],
Workflow._correct_position(path, context))
@staticmethod
def _set_func(path, context, body, engine, target=None, **kwargs):
body_data = engine.evaluate_content(body, context)

View File

@ -61,7 +61,8 @@ class XmlCodeEngine(object):
return_value = result
if len(result) == 0:
return_value = ''.join(parts)
if do_strip: return_value = return_value.strip()
if do_strip:
return_value = return_value.strip()
elif len(result) == 1:
return_value = result[0]

View File

@ -3,12 +3,34 @@
$WindowsAgentConfigBase64 = '%WINDOWS_AGENT_CONFIG_BASE64%'
$WindowsAgentConfigFile = "C:\Keero\Agent\WindowsAgent.exe.config"
$NewComputerName = '%INTERNAL_HOSTNAME%'
$RestartRequired = $false
Import-Module CoreFunctions
Stop-Service "Keero Agent"
Backup-File $WindowsAgentConfigFile
Remove-Item $WindowsAgentConfigFile -Force
ConvertFrom-Base64String -Base64String $WindowsAgentConfigBase64 -Path $WindowsAgentConfigFile
Exec sc.exe 'config','"Keero Agent"','start=','delayed-auto'
Start-Service 'Keero Agent'
Write-Log 'All done!'
if ( $WindowsAgentConfigBase64 -ne '%WINDOWS_AGENT_CONFIG_BASE64%' ) {
Write-Log "Updating Keero Windows Agent."
Stop-Service "Keero Agent"
Backup-File $WindowsAgentConfigFile
Remove-Item $WindowsAgentConfigFile -Force
ConvertFrom-Base64String -Base64String $WindowsAgentConfigBase64 -Path $WindowsAgentConfigFile
Exec sc.exe 'config','"Keero Agent"','start=','delayed-auto'
Write-Log "Service has been updated."
}
if ( $NewComputerName -ne '%INTERNAL_HOSTNAME%' ) {
Write-Log "Renaming computer ..."
Rename-Computer -NewName $NewComputerName | Out-Null
Write-Log "New name assigned, restart required."
$RestartRequired = $true
}
Write-Log 'All done!'
if ( $RestartRequired ) {
Write-Log "Restarting computer ..."
Restart-Computer -Force
}
else {
Start-Service 'Keero Agent'
}

0
conductor/tools/with_venv.sh Normal file → Executable file
View File

View File

@ -75,7 +75,7 @@ class ContextMiddleware(BaseContextMiddleware):
'auth_tok': req.headers.get('X-Auth-Token', deprecated_token),
'service_catalog': service_catalog,
'session': req.headers.get('X-Configuration-Session')
}
}
req.context = portas.context.RequestContext(**kwargs)
else:
raise webob.exc.HTTPUnauthorized()
@ -84,4 +84,4 @@ class ContextMiddleware(BaseContextMiddleware):
def factory(cls, global_conf, **local_conf):
def filter(app):
return cls(app)
return filter
return filter

View File

@ -27,15 +27,19 @@ def get_env_status(environment_id, session_id):
unit = get_session()
if not session_id:
session = unit.query(Session).filter(
Session.environment_id == environment_id and Session.state.in_(['open', 'deploying'])).first()
variants = ['open', 'deploying']
session = unit.query(Session).filter(Session.environment_id ==
environment_id and
Session.state.in_(variants)
).first()
if session:
session_id = session.id
else:
return status
session_state = unit.query(Session).get(session_id).state
reports_count = unit.query(Status).filter_by(environment_id=environment_id, session_id=session_id).count()
reports_count = unit.query(Status).filter_by(environment_id=environment_id,
session_id=session_id).count()
if session_state == 'deployed':
status = 'finished'
@ -50,13 +54,16 @@ def get_env_status(environment_id, session_id):
def get_statuses(type):
if type in draft['services']:
return [get_service_status(environment_id, session_id, service) for service in
draft['services'][type]]
services = draft['services'][type]
return [get_service_status(environment_id,
session_id,
service) for service in services]
else:
return []
is_inprogress = filter(lambda item: item == 'inprogress',
get_statuses('activeDirectories') + get_statuses('webServers'))
get_statuses('activeDirectories') +
get_statuses('webServers'))
if session_state == 'deploying' and is_inprogress > 1:
status = 'inprogress'
@ -71,10 +78,11 @@ def get_service_status(environment_id, session_id, service):
session_state = unit.query(Session).get(session_id).state
entities = [u['id'] for u in service['units']]
reports_count = unit.query(Status).filter(Status.environment_id == environment_id
and Status.session_id == session_id
and Status.entity_id.in_(entities)) \
.count()
reports_count = unit.query(Status).filter(
Status.environment_id == environment_id
and Status.session_id == session_id
and Status.entity_id.in_(entities)
).count()
if session_state == 'deployed':
status = 'finished'

View File

@ -9,18 +9,23 @@ log = logging.getLogger(__name__)
class Controller(object):
def index(self, request, environment_id):
log.debug(_('ActiveDirectory:Index <EnvId: {0}>'.format(environment_id)))
log.debug(_('ActiveDirectory:Index <EnvId: {0}>'.
format(environment_id)))
draft = prepare_draft(get_draft(environment_id, request.context.session))
draft = prepare_draft(get_draft(environment_id,
request.context.session))
for dc in draft['services']['activeDirectories']:
dc['status'] = get_service_status(environment_id, request.context.session, dc)
dc['status'] = get_service_status(environment_id,
request.context.session,
dc)
return {'activeDirectories': draft['services']['activeDirectories']}
@utils.verify_session
def create(self, request, environment_id, body):
log.debug(_('ActiveDirectory:Create <EnvId: {0}, Body: {1}>'.format(environment_id, body)))
log.debug(_('ActiveDirectory:Create <EnvId: {0}, Body: {1}>'.
format(environment_id, body)))
draft = get_draft(session_id=request.context.session)
@ -33,7 +38,7 @@ class Controller(object):
for unit in active_directory['units']:
unit_count += 1
unit['id'] = uuidutils.generate_uuid()
unit['name'] = 'dc{0}{1}'.format(unit_count, active_directory['id'][:4])
unit['name'] = 'dc{0}'.format(unit_count)
draft = prepare_draft(draft)
draft['services']['activeDirectories'].append(active_directory)
@ -42,23 +47,25 @@ class Controller(object):
return active_directory
def delete(self, request, environment_id, active_directory_id):
log.debug(_('ActiveDirectory:Delete <EnvId: {0}, Id: {1}>'.format(environment_id, active_directory_id)))
log.debug(_('ActiveDirectory:Delete <EnvId: {0}, Id: {1}>'.
format(environment_id, active_directory_id)))
draft = get_draft(request.context.session)
draft['services']['activeDirectories'] = [service for service in draft['services']['activeDirectories'] if
service['id'] != active_directory_id]
items = [service for service in draft['services']['activeDirectories']
if service['id'] != active_directory_id]
draft['services']['activeDirectories'] = items
save_draft(request.context.session, draft)
def prepare_draft(draft):
if not draft.has_key('services'):
if not 'services' in draft:
draft['services'] = {}
if not draft['services'].has_key('activeDirectories'):
if not 'activeDirectories' in draft['services']:
draft['services']['activeDirectories'] = []
return draft
def create_resource():
return wsgi.Resource(Controller())
return wsgi.Resource(Controller())

View File

@ -1,10 +1,16 @@
from amqplib.client_0_8 import Message
import anyjson
import eventlet
from webob import exc
from portas.common import config
from portas.api.v1 import get_env_status
from portas.db.session import get_session
from portas.db.models import Environment
from portas.openstack.common import wsgi
from portas.openstack.common import log as logging
amqp = eventlet.patcher.import_patched('amqplib.client_0_8')
rabbitmq = config.CONF.rabbitmq
log = logging.getLogger(__name__)
@ -61,7 +67,8 @@ class Controller(object):
return env
def update(self, request, environment_id, body):
log.debug(_('Environments:Update <Id: {0}, Body: {1}>'.format(environment_id, body)))
log.debug(_('Environments:Update <Id: {0}, Body: {1}>'.
format(environment_id, body)))
session = get_session()
environment = session.query(Environment).get(environment_id)
@ -84,8 +91,26 @@ class Controller(object):
with session.begin():
session.delete(environment)
#preparing data for removal from conductor
env = environment.description
env['services'] = []
env['deleted'] = True
connection = amqp.Connection('{0}:{1}'.
format(rabbitmq.host, rabbitmq.port),
virtual_host=rabbitmq.virtual_host,
userid=rabbitmq.userid,
password=rabbitmq.password,
ssl=rabbitmq.use_ssl, insist=True)
channel = connection.channel()
channel.exchange_declare('tasks', 'direct', durable=True,
auto_delete=False)
channel.basic_publish(Message(body=anyjson.serialize(env)), 'tasks',
'tasks')
return None
def create_resource():
return wsgi.Resource(Controller())
return wsgi.Resource(Controller())

View File

@ -16,7 +16,8 @@
# under the License.
import routes
from portas.openstack.common import wsgi
from portas.api.v1 import environments, sessions, active_directories, webservers
from portas.api.v1 import (environments, sessions,
active_directories, webservers)
class API(wsgi.Router):
@ -64,11 +65,13 @@ class API(wsgi.Router):
controller=sessions_resource,
action='delete',
conditions={'method': ['DELETE']})
mapper.connect('/environments/{environment_id}/sessions/{session_id}/reports',
mapper.connect('/environments/{environment_id}/sessions/'
'{session_id}/reports',
controller=sessions_resource,
action='reports',
conditions={'method': ['GET']})
mapper.connect('/environments/{environment_id}/sessions/{session_id}/deploy',
mapper.connect('/environments/{environment_id}/sessions/'
'{session_id}/deploy',
controller=sessions_resource,
action='deploy',
conditions={'method': ['POST']})
@ -82,7 +85,8 @@ class API(wsgi.Router):
controller=activeDirectories_resource,
action='create',
conditions={'method': ['POST']})
mapper.connect('/environments/{environment_id}/activeDirectories/{active_directory_id}',
mapper.connect('/environments/{environment_id}/activeDirectories/'
'{active_directory_id}',
controller=activeDirectories_resource,
action='delete',
conditions={'method': ['DELETE']})
@ -96,8 +100,9 @@ class API(wsgi.Router):
controller=webServers_resource,
action='create',
conditions={'method': ['POST']})
mapper.connect('/environments/{environment_id}/webServers/{web_server_id}',
mapper.connect('/environments/{environment_id}/webServers/'
'{web_server_id}',
controller=webServers_resource,
action='delete',
conditions={'method': ['DELETE']})
super(API, self).__init__(mapper)
super(API, self).__init__(mapper)

View File

@ -1,7 +1,6 @@
from amqplib.client_0_8 import Message
import anyjson
import eventlet
from eventlet.semaphore import Semaphore
from webob import exc
from portas.common import config
from portas.db.models import Session, Status, Environment
@ -15,36 +14,34 @@ log = logging.getLogger(__name__)
class Controller(object):
def __init__(self):
self.write_lock = Semaphore(1)
connection = amqp.Connection('{0}:{1}'.format(rabbitmq.host, rabbitmq.port), virtual_host=rabbitmq.virtual_host,
userid=rabbitmq.userid, password=rabbitmq.password,
ssl=rabbitmq.use_ssl, insist=True)
self.ch = connection.channel()
self.ch.exchange_declare('tasks', 'direct', durable=True, auto_delete=False)
def index(self, request, environment_id):
log.debug(_('Session:List <EnvId: {0}>'.format(environment_id)))
filters = {'environment_id': environment_id, 'user_id': request.context.user}
filters = {'environment_id': environment_id,
'user_id': request.context.user}
unit = get_session()
configuration_sessions = unit.query(Session).filter_by(**filters)
return {"sessions": [session.to_dict() for session in configuration_sessions if
session.environment.tenant_id == request.context.tenant]}
sessions = [session.to_dict() for session in configuration_sessions if
session.environment.tenant_id == request.context.tenant]
return {"sessions": sessions}
def configure(self, request, environment_id):
log.debug(_('Session:Configure <EnvId: {0}>'.format(environment_id)))
params = {'environment_id': environment_id, 'user_id': request.context.user, 'state': 'open'}
params = {'environment_id': environment_id,
'user_id': request.context.user,
'state': 'open'}
session = Session()
session.update(params)
unit = get_session()
if unit.query(Session).filter(Session.environment_id == environment_id and Session.state.in_(
['open', 'deploing'])).first():
if unit.query(Session).filter(Session.environment_id == environment_id
and
Session.state.in_(['open', 'deploing'])
).first():
log.info('There is already open session for this environment')
raise exc.HTTPConflict
@ -58,7 +55,8 @@ class Controller(object):
return session.to_dict()
def show(self, request, environment_id, session_id):
log.debug(_('Session:Show <EnvId: {0}, SessionId: {1}>'.format(environment_id, session_id)))
log.debug(_('Session:Show <EnvId: {0}, SessionId: {1}>'.
format(environment_id, session_id)))
unit = get_session()
session = unit.query(Session).get(session_id)
@ -70,14 +68,16 @@ class Controller(object):
return session.to_dict()
def delete(self, request, environment_id, session_id):
log.debug(_('Session:Delete <EnvId: {0}, SessionId: {1}>'.format(environment_id, session_id)))
log.debug(_('Session:Delete <EnvId: {0}, SessionId: {1}>'.
format(environment_id, session_id)))
unit = get_session()
session = unit.query(Session).get(session_id)
comment = 'Session object in \'deploying\' state could not be deleted'
if session.state == 'deploying':
log.info('Session is in \'deploying\' state. Could not be deleted.')
raise exc.HTTPForbidden(comment='Session object in \'deploying\' state could not be deleted')
log.info(comment)
raise exc.HTTPForbidden(comment=comment)
with unit.begin():
unit.delete(session)
@ -85,7 +85,8 @@ class Controller(object):
return None
def reports(self, request, environment_id, session_id):
log.debug(_('Session:Reports <EnvId: {0}, SessionId: {1}>'.format(environment_id, session_id)))
log.debug(_('Session:Reports <EnvId: {0}, SessionId: {1}>'.
format(environment_id, session_id)))
unit = get_session()
statuses = unit.query(Status).filter_by(session_id=session_id)
@ -93,20 +94,37 @@ class Controller(object):
return {'reports': [status.to_dict() for status in statuses]}
def deploy(self, request, environment_id, session_id):
log.debug(_('Session:Deploy <EnvId: {0}, SessionId: {1}>'.format(environment_id, session_id)))
log.debug(_('Session:Deploy <EnvId: {0}, SessionId: {1}>'.
format(environment_id, session_id)))
unit = get_session()
session = unit.query(Session).get(session_id)
msg = _('Could not deploy session. Session is already '
'deployed or in deployment state')
if session.state != 'open':
log.warn(_('Could not deploy session. Session is already deployed or in deployment state'))
log.warn(msg)
session.state = 'deploying'
session.save(unit)
with self.write_lock:
self.ch.basic_publish(Message(body=anyjson.serialize(session.description)), 'tasks', 'tasks')
#Set X-Auth-Token for conductor
env = session.description
env['token'] = request.context.auth_token
connection = amqp.Connection('{0}:{1}'.
format(rabbitmq.host, rabbitmq.port),
virtual_host=rabbitmq.virtual_host,
userid=rabbitmq.userid,
password=rabbitmq.password,
ssl=rabbitmq.use_ssl, insist=True)
channel = connection.channel()
channel.exchange_declare('tasks', 'direct', durable=True,
auto_delete=False)
channel.basic_publish(Message(body=anyjson.serialize(env)), 'tasks',
'tasks')
def create_resource():
return wsgi.Resource(Controller())
return wsgi.Resource(Controller())

View File

@ -11,16 +11,19 @@ class Controller(object):
def index(self, request, environment_id):
log.debug(_('WebServer:List <EnvId: {0}>'.format(environment_id)))
draft = prepare_draft(get_draft(environment_id, request.context.session))
draft = prepare_draft(get_draft(environment_id,
request.context.session))
for dc in draft['services']['webServers']:
dc['status'] = get_service_status(environment_id, request.context.session, dc)
dc['status'] = get_service_status(environment_id,
request.context.session, dc)
return {'webServers': draft['services']['webServers']}
@utils.verify_session
def create(self, request, environment_id, body):
log.debug(_('WebServer:Create <EnvId: {0}, Body: {1}>'.format(environment_id, body)))
log.debug(_('WebServer:Create <EnvId: {0}, Body: {1}>'.
format(environment_id, body)))
draft = get_draft(session_id=request.context.session)
@ -33,7 +36,7 @@ class Controller(object):
for unit in webServer['units']:
unit_count += 1
unit['id'] = uuidutils.generate_uuid()
unit['name'] = 'iis{0}{1}'.format(unit_count, webServer['id'][:3])
unit['name'] = 'iis{0}'.format(unit_count)
draft = prepare_draft(draft)
draft['services']['webServers'].append(webServer)
@ -43,23 +46,26 @@ class Controller(object):
@utils.verify_session
def delete(self, request, environment_id, web_server_id):
log.debug(_('WebServer:Delete <EnvId: {0}, Id: {1}>'.format(environment_id, web_server_id)))
log.debug(_('WebServer:Delete <EnvId: {0}, Id: {1}>'.
format(environment_id, web_server_id)))
draft = get_draft(session_id=request.context.session)
draft['services']['webServers'] = [service for service in draft['services']['webServers'] if
service['id'] != web_server_id]
elements = [service for service in draft['services']['webServers'] if
service['id'] != web_server_id]
draft['services']['webServers'] = elements
save_draft(request.context.session, draft)
def prepare_draft(draft):
if not draft.has_key('services'):
if not 'services' in draft:
draft['services'] = {}
if not draft['services'].has_key('webServers'):
if not 'webServers' in draft['services']:
draft['services']['webServers'] = []
return draft
def create_resource():
return wsgi.Resource(Controller())
return wsgi.Resource(Controller())

View File

@ -82,6 +82,7 @@ def parse_args(args=None, usage=None, default_config_files=None):
usage=usage,
default_config_files=default_config_files)
def setup_logging():
"""
Sets up the logging options for a log with supplied name

View File

@ -45,6 +45,7 @@ class PortasException(Exception):
super(PortasException, self).__init__(message)
class SchemaLoadError(PortasException):
message = _("Unable to load schema: %(reason)s")
@ -52,5 +53,3 @@ class SchemaLoadError(PortasException):
class InvalidObject(PortasException):
message = _("Provided object does not match schema "
"'%(schema)s': %(reason)s")

View File

@ -27,14 +27,18 @@ class TaskResultHandlerService(service.Service):
super(TaskResultHandlerService, self).stop()
def _handle_results(self):
connection = amqp.Connection('{0}:{1}'.format(rabbitmq.host, rabbitmq.port), virtual_host=rabbitmq.virtual_host,
userid=rabbitmq.userid, password=rabbitmq.password,
connection = amqp.Connection('{0}:{1}'.
format(rabbitmq.host, rabbitmq.port),
virtual_host=rabbitmq.virtual_host,
userid=rabbitmq.userid,
password=rabbitmq.password,
ssl=rabbitmq.use_ssl, insist=True)
ch = connection.channel()
def bind(exchange, queue):
if not exchange:
ch.exchange_declare(exchange, 'direct', durable=True, auto_delete=False)
ch.exchange_declare(exchange, 'direct', durable=True,
auto_delete=False)
ch.queue_declare(queue, durable=True, auto_delete=False)
if not exchange:
ch.queue_bind(queue, exchange, queue)
@ -43,13 +47,15 @@ class TaskResultHandlerService(service.Service):
bind(conf.reports_exchange, conf.reports_queue)
ch.basic_consume(conf.results_exchange, callback=handle_result)
ch.basic_consume(conf.reports_exchange, callback=handle_report, no_ack=True)
ch.basic_consume(conf.reports_exchange, callback=handle_report,
no_ack=True)
while ch.callbacks:
ch.wait()
def handle_report(msg):
log.debug(_('Got report message from orchestration engine:\n{0}'.format(msg.body)))
log.debug(_('Got report message from orchestration engine:\n{0}'.
format(msg.body)))
params = anyjson.deserialize(msg.body)
params['entity_id'] = params['id']
@ -61,7 +67,8 @@ def handle_report(msg):
session = get_session()
#connect with session
conf_session = session.query(Session).filter_by(
**{'environment_id': status.environment_id, 'state': 'deploying'}).first()
**{'environment_id': status.environment_id,
'state': 'deploying'}).first()
status.session_id = conf_session.id
with session.begin():
@ -69,9 +76,16 @@ def handle_report(msg):
def handle_result(msg):
log.debug(_('Got result message from orchestration engine:\n{0}'.format(msg.body)))
log.debug(_('Got result message from '
'orchestration engine:\n{0}'.format(msg.body)))
environment_result = anyjson.deserialize(msg.body)
if environment_result['deleted']:
log.debug(_('Result for environment {0} is dropped. '
'Environment is deleted'.format(environment_result['id'])))
msg.channel.basic_ack(msg.delivery_tag)
return
session = get_session()
environment = session.query(Environment).get(environment_result['id'])

View File

@ -2,4 +2,4 @@ import uuid
def generate_uuid():
return str(uuid.uuid4()).replace('-', '')
return str(uuid.uuid4()).replace('-', '')

View File

@ -24,7 +24,9 @@ class RequestContext(object):
accesses the system, as well as additional request information.
"""
def __init__(self, auth_tok=None, user=None, tenant=None, roles=None, service_catalog=None, session=None):
def __init__(self, auth_tok=None, user=None, tenant=None,
roles=None, service_catalog=None, session=None):
self.auth_tok = auth_tok
self.user = user
self.tenant = tenant
@ -55,4 +57,4 @@ class RequestContext(object):
@classmethod
def from_dict(cls, values):
return cls(**values)
return cls(**values)

View File

@ -9,4 +9,4 @@ sql_connection_opt = cfg.StrOpt('sql_connection',
'Default: %(default)s')
CONF = cfg.CONF
CONF.register_opt(sql_connection_opt)
CONF.register_opt(sql_connection_opt)

View File

@ -11,7 +11,7 @@ Table('environment', meta,
Column('updated', DateTime(), nullable=False),
Column('tenant_id', String(32), nullable=False),
Column('description', Text(), nullable=False),
)
)
Table('service', meta,
Column('id', String(32), primary_key=True),
@ -21,7 +21,7 @@ Table('service', meta,
Column('created', DateTime, nullable=False),
Column('updated', DateTime, nullable=False),
Column('description', Text(), nullable=False),
)
)
def upgrade(migrate_engine):

View File

@ -5,12 +5,13 @@ meta = MetaData()
session = Table('session', meta,
Column('id', String(32), primary_key=True),
Column('environment_id', String(32), ForeignKey('environment.id')),
Column('environment_id', String(32),
ForeignKey('environment.id')),
Column('created', DateTime, nullable=False),
Column('updated', DateTime, nullable=False),
Column('user_id', String(32), nullable=False),
Column('state', Text(), nullable=False),
)
)
def upgrade(migrate_engine):

View File

@ -8,10 +8,11 @@ status = Table('status', meta,
Column('created', DateTime, nullable=False),
Column('updated', DateTime, nullable=False),
Column('entity', String(10), nullable=False),
Column('environment_id', String(32), ForeignKey('environment.id')),
Column('environment_id', String(32),
ForeignKey('environment.id')),
Column('session_id', String(32), ForeignKey('session.id')),
Column('text', Text(), nullable=False),
)
)
def upgrade(migrate_engine):

View File

@ -5,14 +5,15 @@ from sqlalchemy.types import String, Text, DateTime
meta = MetaData()
service = Table('service', meta,
Column('id', String(32), primary_key=True),
Column('name', String(255), nullable=False),
Column('type', String(40), nullable=False),
Column('environment_id', String(32), ForeignKey('environment.id')),
Column('created', DateTime, nullable=False),
Column('updated', DateTime, nullable=False),
Column('description', Text(), nullable=False),
)
Column('id', String(32), primary_key=True),
Column('name', String(255), nullable=False),
Column('type', String(40), nullable=False),
Column('environment_id', String(32),
ForeignKey('environment.id')),
Column('created', DateTime, nullable=False),
Column('updated', DateTime, nullable=False),
Column('description', Text(), nullable=False),
)
def upgrade(migrate_engine):

View File

@ -83,7 +83,8 @@ class ModelBase(object):
def to_dict(self):
dictionary = self.__dict__.copy()
return {k: v for k, v in dictionary.iteritems() if k != '_sa_instance_state'}
return {k: v for k, v in dictionary.iteritems()
if k != '_sa_instance_state'}
class JsonBlob(TypeDecorator):

View File

@ -0,0 +1,24 @@
import unittest2
from mock import MagicMock
import portas.api.v1.router as router
def my_mock(link, controller, action, conditions):
return [link, controller, action, conditions]
def func_mock():
return True
class SanityUnitTests(unittest2.TestCase):
def test_api(self):
router.webservers = MagicMock(create_resource=func_mock)
router.sessions = MagicMock(create_resource=func_mock)
router.active_directories = MagicMock(create_resource=func_mock)
router.environments = MagicMock(create_resource=func_mock)
mapper = MagicMock(connect=my_mock)
object = router.API(mapper)
assert object._router is not None

View File

@ -11,8 +11,8 @@ def verify_session(func):
@functools.wraps(func)
def __inner(self, request, *args, **kwargs):
if hasattr(request, 'context') and request.context.session:
uw = get_session()
configuration_session = uw.query(Session).get(request.context.session)
uw = get_session().query(Session)
configuration_session = uw.get(request.context.session)
if configuration_session.state != 'open':
log.info('Session is already deployed')
@ -22,5 +22,3 @@ def verify_session(func):
raise exc.HTTPUnauthorized
return func(self, request, *args, **kwargs)
return __inner

View File

@ -15,6 +15,6 @@
# under the License.
from portas.openstack.common import version as common_version
from portasclient.openstack.common import version as common_version
version_info = common_version.VersionInfo('python-portasclient')

View File

@ -1,19 +1,29 @@
import os
import unittest
import logging
from mock import MagicMock
from mock import patch
from portasclient.client import Client as CommonClient
from portasclient.v1 import Client
import portasclient.v1.environments as environments
import portasclient.v1.services as services
import portasclient.v1.sessions as sessions
import portasclient.shell as shell
import portasclient.common.http as http
LOG = logging.getLogger('Unit tests')
def my_mock(*a, **b):
return [a, b]
api = MagicMock(json_request=my_mock)
class SanityUnitTests(unittest.TestCase):
def test_create_client_instance(self):
@ -25,145 +35,121 @@ class SanityUnitTests(unittest.TestCase):
assert test_client.sessions is not None
assert test_client.activeDirectories is not None
assert test_client.webServers is not None
def test_common_client(self):
endpoint = 'http://localhost:8001'
test_client = CommonClient('1', endpoint=endpoint, token='1', timeout=10)
assert test_client.environments is not None
assert test_client.sessions is not None
assert test_client.activeDirectories is not None
assert test_client.webServers is not None
def test_env_manager_list(self):
manager = environments.EnvironmentManager(api)
result = manager.list()
assert result == []
def test_env_manager_create(self):
manager = environments.EnvironmentManager(api)
result = manager.create('test')
assert result.headers == {}
assert result.body == {'name': 'test'}
def test_env_manager_delete(self):
manager = environments.EnvironmentManager(api)
result = manager.delete('test')
assert result is None
def test_env_manager_update(self):
manager = environments.EnvironmentManager(api)
result = manager.update('1', 'test')
assert result.body == {'name': 'test'}
def test_env_manager_get(self):
manager = environments.EnvironmentManager(api)
result = manager.get('test')
## WTF?
assert result.manager is not None
def test_env(self):
environment = environments.Environment(api, api)
assert environment.data() is not None
def test_ad_manager_list(self):
manager = services.ActiveDirectoryManager(api)
result = manager.list('datacenter1')
assert result == []
result = manager.list('datacenter1', '1')
assert result == []
def test_ad_manager_create(self):
manager = services.ActiveDirectoryManager(api)
result = manager.create('datacenter1', 'session1', 'test')
assert result.headers == {'X-Configuration-Session': 'session1'}
assert result.body == 'test'
#@unittest.skip("https://mirantis.jira.com/browse/KEERO-218")
def test_ad_manager_delete(self):
manager = services.ActiveDirectoryManager(api)
result = manager.delete('datacenter1', 'session1', 'test')
assert result is None
def test_iis_manager_list(self):
manager = services.WebServerManager(api)
result = manager.list('datacenter1')
assert result == []
result = manager.list('datacenter1', '1')
assert result == []
def test_iis_manager_create(self):
manager = services.WebServerManager(api)
result = manager.create('datacenter1', 'session1', 'test')
assert result.headers == {'X-Configuration-Session': 'session1'}
assert result.body == 'test'
#@unittest.skip("https://mirantis.jira.com/browse/KEERO-218")
def test_iis_manager_delete(self):
manager = services.WebServerManager(api)
result = manager.delete('datacenter1', 'session1', 'test')
assert result is None
def test_service_ad(self):
service_ad = services.ActiveDirectory(api, api)
assert service_ad.data() is not None
def test_service_iis(self):
service_iis = services.ActiveDirectory(api, api)
assert service_iis.data() is not None
def test_session_manager_list(self):
manager = sessions.SessionManager(api)
result = manager.list('datacenter1')
assert result == []
def test_session_manager_delete(self):
manager = sessions.SessionManager(api)
result = manager.delete('datacenter1', 'session1')
assert result is None
def test_session_manager_get(self):
manager = sessions.SessionManager(api)
result = manager.get('datacenter1', 'session1')
# WTF?
assert result.manager is not None
def test_session_manager_configure(self):
manager = sessions.SessionManager(api)
result = manager.configure('datacenter1')
assert result.headers == {}
def test_session_manager_deploy(self):
manager = sessions.SessionManager(api)
result = manager.deploy('datacenter1', '1')
assert result is None
#@unittest.skip("https://mirantis.jira.com/browse/KEERO-219")
def test_session_manager_reports(self):
manager = sessions.SessionManager(api)
result = manager.reports('datacenter1', '1')
assert result == []

49
tests/deploy.sh Normal file → Executable file
View File

@ -24,10 +24,20 @@ expect "*$*"
send -- "./unstack.sh\n"
expect "*$*"
send -- "./stack.sh\n"
expect "*Would you like to start it now?*"
expect "*/usr/bin/service: 123: exec: status: not found*"
send -- "y\n"
expect "*stack.sh completed*"
send -- "sudo rabbitmq-plugins enable rabbitmq_management\n"
expect "*$*"
send -- "sudo service rabbitmq-server restart\n"
expect "*$*"
send -- "sudo rabbitmqctl add_user keero keero\n"
expect "*$*"
send -- "sudo rabbitmqctl set_user_tags keero administrator\n"
expect "*$*"
send -- "source openrc admin admin\n"
expect "*$*"
@ -37,7 +47,7 @@ expect "*$*"
send -- "nova keypair-add keero-linux-keys > heat_key.priv\n"
expect "*$*"
send -- "glance image-create --name 'ws-2012-full-agent' --is-public true --container-format ovf --disk-format qcow2 < ws-2012-full-agent.qcow2\n"
send -- "glance image-create --name 'ws-2012-full' --is-public true --container-format ovf --disk-format qcow2 < ws-2012-full.qcow2\n"
expect "*$*"
send -- "cd ~/keero\n"
@ -50,33 +60,22 @@ send -- "cp -Rf ~/keero/dashboard/windc /opt/stack/horizon/openstack_dashboard/d
expect "*$*"
send -- "cp -f ~/keero/dashboard/api/windc.py /opt/stack/horizon/openstack_dashboard/api/\n"
expect "*$*"
send -- "cp -Rf ~/keero/dashboard/windcclient /opt/stack/horizon/\n"
send -- "cd ~/keero/python-portasclient\n"
expect "*$*"
send -- "cd ~/keero/windc\n"
send -- "sudo python setup.py install\n"
expect "*$*"
send -- "rm -rf windc.sqlite\n"
send -- "cd ~/keero/portas\n"
expect "*$*"
send -- "./tools/with_venv.sh ./bin/windc-api --config-file=./etc/windc-api-paste.ini --dbsync\n"
send -- "./tools/with_venv.sh ./bin/portas-api --config-file=./etc/portas-api.conf & > ~/APIservice.log\n"
sleep 10
send -- "\n"
expect "*$*"
send -- "cd ~/keero/conductor\n"
expect "*$*"
send -- "./tools/with_venv.sh ./bin/app.py & > ~/conductor.log\n"
sleep 10
send -- "\n"
expect "*$*"
send -- "logout\n"
expect "*#*"
send -- "rabbitmq-plugins enable rabbitmq_management\n"
expect "*#*"
send -- "service rabbitmq-server restart\n"
expect "*#*"
send -- "rabbitmqctl add_user keero keero\n"
expect "*#*"
send -- "rabbitmqctl set_user_tags keero administrator\n"
expect "*#*"
send -- "su - stack\n"
expect "*$*"
send -- "cd /opt/stack/devstack\n"
expect "*$*"
send -- "source openrc admin admin\n"
expect "*$*"
send -- "cd /opt/stack/keero/windc\n"
expect "*$*"
send -- "sudo ./tools/with_venv.sh ./bin/windc-api --config-file=./etc/windc-api-paste.ini > /opt/stack/tests_windc_daemon.log &\n"
expect "*$*"

View File

@ -1,4 +1,4 @@
[server]
address=http://172.18.124.101
user=admin
password=AkvareL707
password=swordfish

View File

@ -1,56 +1,54 @@
import re
from login_page import LoginPage
from services_page import ServicesPage
import page
class DataCentersPage():
page = None
def __init__(self):
start_page = LoginPage()
self.page = start_page.login()
self.page.find_element_by_link_text('Project').click()
self.page.find_element_by_link_text('Windows Data Centers').click()
class DataCentersPage(page.Page):
def create_data_center(self, name):
button_text = 'Create Windows Data Center'
self.page.find_element_by_link_text(button_text).click()
self.Refresh()
name_field = self.page.find_element_by_id('id_name')
self.Button('Create Windows Data Center').Click()
self.EditBox('id_name').Set(name)
xpath = "//input[@value='Create']"
button = self.page.find_element_by_xpath(xpath)
name_field.clear()
name_field.send_keys(name)
button.click()
return self.page
def find_data_center(self, name):
return self.page.find_element_by_link_text(name)
self.Button(xpath).Click()
def delete_data_center(self, name):
datacenter = self.find_data_center(name)
link = datacenter.get_attribute('href')
self.Refresh()
link = self.Link(name).Address()
datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1]
xpath = ".//*[@id='windc__row__%s']/td[3]/div/a[2]" % datacenter_id
more_button = self.page.find_element_by_xpath(xpath)
xpath = ".//*[@id='windc__row__%s']/td[4]/div/a[2]" % datacenter_id
self.Button(xpath).Click()
more_button.click()
button_id = "windc__row_%s__action_delete" % datacenter_id
self.Button(button_id).Click()
delete_button_id = "windc__row_%s__action_delete" % datacenter_id
delete_button = self.page.find_element_by_id(delete_button_id)
delete_button.click()
self.page.find_element_by_link_text("Delete Data Center").click()
return self.page
self.Button("Delete Data Center").Click()
def select_data_center(self, name):
datacenter = self.page.find_data_center(name)
datacenter.click()
self.page = ServicesPage(self.page)
return self.page
self.Link(name).Click()
page = ServicesPage(self.driver)
return page
def deploy_data_center(self, name):
self.Refresh()
link = self.Link(name).Address()
datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1]
xpath = ".//*[@id='windc__row__%s']/td[4]/div/a[2]" % datacenter_id
self.Button(xpath).Click()
button_id = "windc__row_%s__action_deploy" % datacenter_id
self.Button(button_id).Click()
def get_datacenter_status(self, name):
self.Navigate('Windows Data Centers')
link = self.Link(name).Address()
datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1]
xpath = ".//*[@id='windc__row__%s']/td[3]" % datacenter_id
return self.TableCell(xpath).Text()

View File

@ -1,8 +1,8 @@
import ConfigParser
from selenium import webdriver
import page
class LoginPage():
class LoginPage(page.Page):
def login(self):
config = ConfigParser.RawConfigParser()
@ -11,20 +11,11 @@ class LoginPage():
user = config.get('server', 'user')
password = config.get('server', 'password')
page = webdriver.Firefox()
page.set_page_load_timeout(30)
page.implicitly_wait(30)
page.get(url)
name = page.find_element_by_name('username')
pwd = page.find_element_by_name('password')
self.Open(url)
self.EditBox('username').Set(user)
self.EditBox('password').Set(password)
xpath = "//button[@type='submit']"
button = page.find_element_by_xpath(xpath)
self.Button(xpath).Click()
name.clear()
name.send_keys(user)
pwd.clear()
pwd.send_keys(password)
button.click()
return page
return self

192
tests/selenium/page.py Normal file
View File

@ -0,0 +1,192 @@
import logging
from selenium.webdriver.support.ui import Select
logging.basicConfig()
LOG = logging.getLogger(' Page object: ')
class TableCellClass:
table = None
def __init__(self, obj):
if not obj:
LOG.error('TableCell does not found')
self.table = obj
def Text(self):
if self.table:
return self.table.text()
else:
return ''
class ButtonClass:
button = None
def __init__(self, obj):
if not obj:
LOG.error('Button does not found')
self.button = obj
def Click(self):
if self.button:
self.button.click()
def isPresented(self):
if self.button:
return True
return False
class LinkClass:
link = None
def __init__(self, obj):
if not obj:
LOG.error('Link does not found')
self.link = obj
def Click(self):
if self.link:
self.link.click()
def isPresented(self):
if self.link:
return True
return False
def Address(self):
if self.link:
return self.link.get_attribute('href')
else:
return ''
class EditBoxClass:
def __init__(self, obj):
if not obj:
LOG.error('EditBox does not found')
self.edit = obj
def isPresented(self):
if self.edit:
return True
return False
def Set(self, value):
if self.edit:
self.edit.clear()
self.edit.send_keys(value)
def Text(self):
if self.edit:
return self.edit.get_text()
else:
return ''
class DropDownListClass:
select = None
def __init__(self, obj):
if not obj:
LOG.error('DropDownList does not found')
self.select = obj
def isPresented(self):
if self.select is not None:
return True
return False
def Set(self, value):
if self.select:
Select(self.select).select_by_visible_text(value)
def Text(self):
if self.select:
return self.select.get_text()
else:
return ''
error_msg = """
Object with parameter: %s
does not found on page.
"""
class Page:
driver = None
timeout = 30
def __init__(self, driver):
driver.set_page_load_timeout(30)
driver.implicitly_wait(0.01)
self.driver = driver
def _find_element(self, parameter):
obj = None
k = 0
while (obj is None and k < self.timeout):
k += 1
try:
obj = self.driver.find_element_by_name(parameter)
return obj
except:
pass
try:
obj = self.driver.find_element_by_id(parameter)
return obj
except:
pass
try:
obj = self.driver.find_element_by_xpath(parameter)
return obj
except:
pass
try:
obj = self.driver.find_element_by_partial_link_text(parameter)
return obj
except:
pass
LOG.error(error_msg % parameter)
return None
def Open(self, url):
self.driver.get(url)
def Refresh(self):
self.driver.refresh()
def TableCell(self, name):
obj = self._find_element(name)
table = TableCellClass(obj)
return table
def Button(self, name):
obj = self._find_element(name)
button = ButtonClass(obj)
return button
def Link(self, name):
obj = self._find_element(name)
link = LinkClass(obj)
return link
def EditBox(self, name):
obj = self._find_element(name)
edit = EditBoxClass(obj)
return edit
def DropDownList(self, name):
obj = self._find_element(name)
select = DropDownListClass(obj)
return select
def Navigate(self, path):
steps = path.split(':')
for step in steps:
self.Button(step).Click()

View File

@ -1,57 +1,32 @@
import ConfigParser
from selenium import webdriver
import page
import re
class ServicesPage():
page = None
def __init__(self, page):
self.page = page
class ServicesPage(page.Page):
def create_service(self, service_type, parameters):
self.Refresh()
button_id = 'services__action_CreateService'
button = self.page.find_element_by_id(button_id)
button.click()
self.Button('services__action_CreateService').Click()
self.DropDownList('0-service').Set(service_type)
self.Button('wizard_goto_step').Click()
self.select_type_of_service(service_type)
for key in parameters:
self.EditBox(key).Set(parameters[key])
for parameter in parameters:
field = self.page.find_element_by_name(parameter.key)
field.clear()
field.send_keys(parameter.value)
xpath = "//input[@value='Deploy']"
deploy_button = self.page.find_element_by_xpath(xpath)
deploy_button.click()
return page
def select_type_of_service(self, service_type):
type_field = self.page.find_element_by_name('0-service')
type_field.select_by_visible_text(service_type)
next_button = self.page.find_element_by_name('wizard_goto_step')
next_button.click()
return self.page
def find_service(self, name):
return self.page.find_element_by_link_text(name)
self.Button("//input[@value='Create']").Click()
def delete_service(self, name):
service = self.find_data_center(name)
link = service.get_attribute('href')
self.Refresh()
link = self.Link(name).Address()
service_id = re.search('windc/(\S+)', link).group(0)[6:-1]
xpath = ".//*[@id='services__row__%s']/td[5]/div/a[2]" % service_id
more_button = self.page.find_element_by_xpath(xpath)
more_button.click()
self.Button(xpath).Click()
delete_button_id = "services__row_%s__action_delete" % datacenter_id
delete_button = self.page.find_element_by_id(delete_button_id)
button_id = "services__row_%s__action_delete" % service_id
self.Button(button_id).Click()
delete_button.click()
self.page.find_element_by_link_text("Delete Service").click()
return self.page
self.Button("Delete Service").Click()

View File

@ -1,54 +1,155 @@
# -*- coding: utf-8 -*-
import untitest2
import unittest2
from login_page import LoginPage
from datacenters_page import DataCentersPage
from selenium import webdriver
class SanityTests(unittest2.TestCase):
def setUp(self):
self.page = DataCentersPage()
@classmethod
def setUpClass(self):
driver = webdriver.Firefox()
self.page = LoginPage(driver)
self.page.login()
self.page.Navigate('Project:Windows Data Centers')
self.page = DataCentersPage(driver)
def tearDown(self):
self.page.close()
@classmethod
def tearDownClass(self):
self.page.driver.close()
def test_01_create_data_center(self):
self.page.create_data_center('dc1')
assert self.page.find_data_center('dc1') is not None
assert self.page.Link('dc1').isPresented()
def test_02_delete_data_center(self):
self.page.delete_data_center('dc1')
assert self.page.find_data_center('dc1') is None
assert not self.page.Link('dc1').isPresented()
def test_03_create_data_centers(self):
for i in range(1, 20):
for i in range(1, 10):
name = 'datacenter' + str(i)
self.page.create_data_center(name)
assert self.page.find_data_center(name) is not None
assert self.page.Link(name).isPresented()
def test_04_delete_data_centers(self):
self.page.delete_data_center('datacenter1')
self.page.delete_data_center('datacenter20')
assert self.page.find_data_center('datacenter1') is None
assert self.page.find_data_center('datacenter20') is None
self.page.delete_data_center('datacenter9')
assert not self.page.Link('datacenter1').isPresented()
assert not self.page.Link('datacenter9').isPresented()
for i in range(2, 19):
for i in range(2, 9):
name = 'datacenter' + str(i)
assert self.page.find_data_center(name) is not None
assert self.page.Link(name).isPresented()
def test_05_create_service_ad(self):
name = 'dc001.local'
self.page.create_data_center(name)
self.select_data_center(name)
self.page.Navigate('Windows Data Centers')
self.page.create_data_center('test05')
self.page = self.page.select_data_center('test05')
ad_parameters = {'1-dc_name': name,
'1-dc_count': 1,
'1-adm_password': 'AkvareL707!',
'1-recovery_password': 'AkvareL707!'}
self.page.create_service('Active Directory', ad_parameters)
assert self.page.find_service(name) is not None
assert self.page.Link(name).isPresented()
def test_06_create_service_ad_two_instances(self):
name = 'dc002.local'
self.page.Navigate('Windows Data Centers')
self.page.create_data_center('test06')
self.page = self.page.select_data_center('test06')
ad_parameters = {'1-dc_name': name,
'1-dc_count': 2,
'1-adm_password': 'P@ssw0rd2',
'1-recovery_password': 'P@ssw0rd'}
self.page.create_service('Active Directory', ad_parameters)
assert self.page.Link(name).isPresented()
def test_07_create_service_ad_with_iis(self):
ad_name = 'dc003.local'
self.page.Navigate('Windows Data Centers')
self.page.create_data_center('test07')
self.page = self.page.select_data_center('test07')
ad_parameters = {'1-dc_name': ad_name,
'1-dc_count': 3,
'1-adm_password': 'P@ssw0rd',
'1-recovery_password': 'P@ssw0rd2'}
self.page.create_service('Active Directory', ad_parameters)
assert self.page.Link(ad_name).isPresented()
iis_name = 'iis_server1'
iis_parameters = {'1-iis_name': iis_name,
'1-adm_password': 'P@ssw0rd',
'1-iis_domain': 'dc003.local',
'1-domain_user_name': 'Administrator',
'1-domain_user_password': 'P@ssw0rd'}
self.page.create_service('Internet Information Services',
iis_parameters)
assert self.page.Link(iis_name).isPresented()
iis_name = 'iis_server2'
iis_parameters = {'1-iis_name': iis_name,
'1-adm_password': 'P@ssw0rd',
'1-iis_domain': 'dc003.local',
'1-domain_user_name': 'Administrator',
'1-domain_user_password': 'P@ssw0rd'}
self.page.create_service('Internet Information Services',
iis_parameters)
assert self.page.Link(iis_name).isPresented()
iis_name = 'iis_server3'
iis_parameters = {'1-iis_name': iis_name,
'1-adm_password': 'P@ssw0rd',
'1-iis_domain': 'dc003.local',
'1-domain_user_name': 'Administrator',
'1-domain_user_password': 'P@ssw0rd'}
self.page.create_service('Internet Information Services',
iis_parameters)
assert self.page.Link(iis_name).isPresented()
def test_08_deploy_data_center(self):
ad_name = 'AD.net'
self.page.Navigate('Windows Data Centers')
self.page.create_data_center('test08')
self.page = self.page.select_data_center('test08')
ad_parameters = {'1-dc_name': ad_name,
'1-dc_count': 2,
'1-adm_password': 'P@ssw0rd',
'1-recovery_password': 'P@ssw0rd2'}
self.page.create_service('Active Directory', ad_parameters)
assert self.page.Link(ad_name).isPresented()
iis_parameters = {'1-iis_name': 'iis_server',
'1-adm_password': 'P@ssw0rd',
'1-iis_domain': 'AD.net',
'1-domain_user_name': 'Administrator',
'1-domain_user_password': 'P@ssw0rd'}
self.page.create_service('Internet Information Services',
iis_parameters)
assert self.page.Link('iis_server').isPresented()
self.page.Navigate('Windows Data Centers')
self.page = DataCentersPage(self.page.driver)
self.page.deploy_data_center('test08')
status = self.page.get_datacenter_status('test08')
assert 'Deploy in progress' in status
if __name__ == '__main__':
unittest2.main()
unittest2.main()