Commit 4e4f2f86 authored by Łukasz Nowak's avatar Łukasz Nowak

Merge branch 'master' into networkcache_signature

parents 83712063 710ef80e
......@@ -26,7 +26,9 @@
</item>
<item>
<key> <string>after_script_id</string> </key>
<value> <string>BusinessConfiguration_displayVifibDownload</string> </value>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string># Do Nothing!\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>configuration_save_url=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>BusinessConfiguration_displayVifibDownload</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>from Products.ERP5Type.Log import log\n
portal = context.getPortalObject()\n
portal_preferences = portal.portal_preferences\n
system_preference = None\n
clear_cache = 0\n
conversion_check = False\n
\n
log(conversion_server)\n
log(kumo)\n
log(memcached)\n
\n
\n
if conversion_server is not None:\n
conversion_server_address, conversion_server_port = conversion_server.split(":")\n
\n
def getActiveSystemPreference():\n
system_preference = portal_preferences.getActiveSystemPreference()\n
if system_preference is None:\n
system_preference = portal_preferences.newContent(\n
portal_type="System Preference", \n
title="Automatically Created.")\n
system_preference.enable()\n
return system_preference\n
\n
if portal_preferences.getPreferredOoodocServerAddress() != conversion_server_address:\n
system_preference = getActiveSystemPreference()\n
system_preference.setPreferredOoodocServerAddress(conversion_server_address)\n
clear_cache = 1\n
\n
if int(portal_preferences.getPreferredOoodocServerPortNumber("-1")) != int(conversion_server_port):\n
if system_preference is None:\n
system_preference = getActiveSystemPreference()\n
system_preference.setPreferredOoodocServerPortNumber(int(conversion_server_port))\n
clear_cache = 1\n
\n
if memcached is not None:\n
default_memcached_plugin = getattr(portal.portal_memcached, "default_memcached_plugin", None)\n
if default_memcached_plugin.getUrlString() != memcached:\n
default_memcached_plugin.setUrlString(memcached)\n
\n
if kumo is not None:\n
persistent_memcached_plugin = getattr(portal.portal_memcached, "persistent_memcached_plugin", None)\n
if persistent_memcached_plugin is not None:\n
if persistent_memcached_plugin.getUrlString() != kumo:\n
persistent_memcached_plugin.setUrlString(kumo)\n
\n
\n
if clear_cache:\n
portal.portal_caches.clearAllCache()\n
\n
if conversion_server is not None:\n
conversion_check = (portal_preferences.getPreferredOoodocServerAddress() == conversion_server_address) and \\\n
(int(portal_preferences.getPreferredOoodocServerPortNumber()) == int(conversion_server_port))\n
\n
return conversion_check and \\\n
default_memcached_plugin.getUrlString() == memcached and \\\n
persistent_memcached_plugin is not None and \\\n
persistent_memcached_plugin.getUrlString() == kumo\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>conversion_server=None, memcached=None, kumo=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_assertExternalServiceList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
12
\ No newline at end of file
13
\ No newline at end of file
298
\ No newline at end of file
299
\ No newline at end of file
......@@ -7623,6 +7623,145 @@ class TestVifibSlapWebService(testVifibMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def stepStoreCurrentComputerReferenceBufferA(self, sequence, **kw):
sequence['buffer_a_computer_reference'] = sequence['computer_reference']
def stepStoreCurrentComputerReferenceBufferB(self, sequence, **kw):
sequence['buffer_b_computer_reference'] = sequence['computer_reference']
def stepStoreCurrentComputerPartitionReferenceBufferA(self, sequence, **kw):
sequence['buffer_a_computer_partition_reference'] = sequence['computer_partition_reference']
def stepStoreCurrentComputerPartitionReferenceBufferB(self, sequence, **kw):
sequence['buffer_b_computer_partition_reference'] = sequence['computer_partition_reference']
def stepRestoreComputerReferenceFromBufferA(self, sequence, **kw):
sequence['computer_reference'] = sequence['buffer_a_computer_reference']
def stepRestoreComputerReferenceFromBufferB(self, sequence, **kw):
sequence['computer_reference'] = sequence['buffer_b_computer_reference']
def stepRestoreComputerPartitionReferenceFromBufferA(self, sequence, **kw):
sequence['computer_partition_reference'] = sequence['buffer_a_computer_partition_reference']
def stepRestoreComputerPartitionReferenceFromBufferB(self, sequence, **kw):
sequence['computer_partition_reference'] = sequence['buffer_b_computer_partition_reference']
def test_bug_destruction_of_partition_originated_from_another_computer(self):
"""Checks that computer is capable to destroy own Software Instance
If software instance originated on computer comes from another computer it
shall be possible to sucesfully destroy it.
"""
sequence_list = SequenceList()
sequence_string = self.prepare_install_requested_computer_partition_sequence_string + \
"""
StoreCurrentComputerReferenceBufferA
StoreCurrentComputerPartitionReferenceBufferA
""" + \
self.prepare_formated_computer + \
"""
StoreCurrentComputerReferenceBufferB
StoreCurrentComputerPartitionReferenceBufferB
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
RestoreComputerReferenceFromBufferA
RestoreComputerPartitionReferenceFromBufferA
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartition
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
RestoreComputerReferenceFromBufferB
RestoreComputerPartitionReferenceFromBufferB
SlapLoginCurrentComputer
SoftwareInstanceBuilding
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListStarted
Logout
SlapLoginCurrentComputer
SoftwareInstanceAvailable
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListStopped
CheckComputerPartitionInstanceHostingSalePackingListConfirmed
Logout
SlapLoginCurrentComputer
SoftwareInstanceStarted
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListStarted
SetCurrentSoftwareInstanceRequester
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
LoginTestVifibCustomer
RequestSoftwareInstanceDestroy
Tic
Logout
LoginDefaultUser
CheckComputerPartitionInstanceCleanupSalePackingListConfirmed
Logout
RestoreComputerReferenceFromBufferA
RestoreComputerPartitionReferenceFromBufferA
SlapLoginCurrentComputer
SoftwareInstanceDestroyed
Tic
SlapLogout
LoginDefaultUser
CheckComputerPartitionInstanceCleanupSalePackingListDelivered
CheckComputerPartitionIsFree
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
raise NotImplementedError
########################################
# Other tests
########################################
......
......@@ -57,4 +57,5 @@ setup(name=name,
'slapproxy = slapos.proxy:main',
]
},
test_suite="slapos.tests",
)
......@@ -42,5 +42,7 @@ alias =
mariadb http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.16:/software/mariadb/software.cfg
memcached http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.16:/software/memcached/software.cfg
kumofs http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.21:/software/kumofs/software.cfg
erp5 http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/erp5/software.cfg
erp5 http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.30:/software/erp5/software.cfg
erp5_branch http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/heads/erp5:/software/erp5/software.cfg
vifib http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.30:/software/vifib/software.cfg
......@@ -27,13 +27,13 @@
##############################################################################
from optparse import OptionParser, Option
from xml_marshaller import xml_marshaller
from pwd import getpwnam
import ConfigParser
import grp
import logging
import netaddr
import netifaces
import os
import pwd
import random
import slapos.slap as slap
import socket
......@@ -211,7 +211,7 @@ class Computer:
# all addresses on interface are for partition, so lets add new one
computer_tap = Tap('compdummy')
computer_tap.createWithOwner('root', attach_to_tap=True)
computer_tap.createWithOwner(User('root'), attach_to_tap=True)
self.bridge.addTap(computer_tap)
return self.bridge.addAddr()
......@@ -317,7 +317,7 @@ class Computer:
slapsoft.path = self.software_root
if alter_user:
slapsoft.create()
slapsoft_pw = getpwnam(slapsoft.name)
slapsoft_pw = pwd.getpwnam(slapsoft.name)
os.chown(self.software_root, slapsoft_pw.pw_uid, slapsoft_pw.pw_gid)
os.chmod(self.software_root, 0755)
......@@ -415,7 +415,7 @@ class Partition:
if not os.path.exists(self.path):
os.mkdir(self.path, 0750)
if alter_user:
owner_pw = getpwnam(owner.name)
owner_pw = pwd.getpwnam(owner.name)
os.chown(self.path, owner_pw.pw_uid, owner_pw.pw_gid)
os.chmod(self.path, 0750)
......@@ -457,7 +457,7 @@ class User:
user_parameter_list.extend(['-G', ','.join(self.additional_group_list)])
user_parameter_list.append(self.name)
try:
getpwnam(self.name)
pwd.getpwnam(self.name)
except KeyError:
callAndRead(['useradd'] + user_parameter_list)
else:
......@@ -475,7 +475,7 @@ class User:
"""
try:
getpwnam(self.name)
pwd.getpwnam(self.name)
return True
except KeyError:
......@@ -572,7 +572,7 @@ class Tap:
owner_id = int(open(check_file).read().strip())
except Exception:
pass
if (owner_id is None) or (owner_id != getpwnam(owner.name).pw_uid):
if (owner_id is None) or (owner_id != pwd.getpwnam(owner.name).pw_uid):
callAndRead(['tunctl', '-t', self.name, '-u', owner.name])
callAndRead(['ip', 'link', 'set', self.name, 'up'])
......@@ -584,7 +584,7 @@ class Tap:
class Bridge:
"Bridge represent a bridge on the system"
def __init__(self, name, ipv4_local_network, ipv6_interface):
def __init__(self, name, ipv4_local_network, ipv6_interface=None):
"""
Attributes:
name: String, the name of the bridge
......@@ -846,11 +846,14 @@ class Parser(OptionParser):
help="Shall slapformat alter network configuration [default: True]"),
])
def check_args(self):
def check_args(self, args):
"""
Check arguments
"""
(options, args) = self.parse_args()
if args:
(options, args) = self.parse_args(list(args))
else:
(options, args) = self.parse_args()
if len(args) != 1:
self.error("Incorrect number of arguments")
return options, args[0]
......@@ -1093,17 +1096,17 @@ class Config:
self.computer_xml = os.path.abspath(self.computer_xml)
def main():
def main(*args):
"Run default configuration."
global os
global callAndRead
global getpwnam
global pwd
real_callAndRead = callAndRead
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try:
# Parse arguments
options, configuration_file_path = Parser(usage=usage).check_args()
options, configuration_file_path = Parser(usage=usage).check_args(args)
config = Config()
config.setConfig(options, configuration_file_path)
os = OS(config)
......@@ -1125,7 +1128,7 @@ def main():
pw_uid = 12345
pw_gid = 54321
return result
getpwnam = fake_getpwnam
pwd.getpwnam = fake_getpwnam
else:
dry_callAndRead = real_callAndRead
if config.verbose:
......
......@@ -352,7 +352,7 @@ class Slapgrid(object):
computer_partition_list = self.computer.getComputerPartitionList()
except socket.error as error:
self.logger.fatal(error)
sys.exit(1)
raise
return computer_partition_list
def processSoftwareReleaseList(self):
......
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""Mocked httplib
"""
from urlparse import urlparse
__all__ = []
def log(message):
"""Need to be overridden to get a proper logger
"""
pass
class HTTPConnection(object):
scheme = 'http'
def _callback(self, path, method, body, headers):
"""To get it works properly, you need to override
HTTPConnection._callback. This method received the instance, the path,
method and request body as parameter, and it has to return a tuple with
headers dictionary and body response string.
@param self object instance reference
@param URL the parsed URL
@param method the http method
@param body the request body
@param headers the request headers
@return tuple containing status integer, headers dictionary and body
response"""
return (0, {}, '', )
def __init__(self, host, port=None, strict=None,
timeout=None, source_address=None):
self.host = host
self.port = port
self.strict = strict
self.timeout = timeout
self.source_address = source_address
self.__response = None
def request(self, method, url, body=None, headers=None):
status, headers, body = self._callback(url, method, body, headers)
self.__response = HTTPResponse('HTTP/1.1', 200, 'OK', body, headers)
def getresponse(self):
response = self.__response
self.__response = None
return response
def set_debuglevel(self, level):
pass
def set_tunnel(self, host, port=None, headers=None):
pass
def connect(self):
pass
def close(self):
pass
def putrequest(self, request, selector, skip_host=None,
skip_accept_encoding=None):
pass
def putheader(self, *args):
pass
def endheaders(self):
pass
def send(self, data):
pass
class HTTPSConnection(HTTPConnection):
def __init__(self, host, port=None, key_file=None,
cert_file=None, strict=None, timeout=None,
source_address=None):
super().__init__(self, host, port, strict, timeout,
source_address)
pass
class HTTPResponse(object):
def __init__(self, version, status, reason, content, headers=()):
self.version = version
self.status = status
self.reason = reason
self.__headers = headers
self.__content = content
def read(self, amt=None):
result = None
if amt is None:
result = self.__content
self.__content = ''
else:
end = max(amt, len(self.__content))
result = self.__content[:end]
del self.__content[:end]
return result
def getheader(self, name, default=None):
pass
def getheaders(self):
pass
This diff is collapsed.
from slapos.grid import slapgrid
import httplib
import logging
import os
import shutil
import signal
import slapos.slap.slap
import socket
import tempfile
import unittest
import urlparse
import xml_marshaller
class BasicMixin:
def assertSortedListEqual(self, list1, list2, msg=None):
self.assertListEqual(sorted(list1), sorted(list2), msg)
def setUp(self):
self._tempdir = tempfile.mkdtemp()
self.software_root = os.path.join(self._tempdir, 'software')
self.instance_root = os.path.join(self._tempdir, 'instance')
if getattr(self, 'master_url', None) is None:
self.master_url = 'http://127.0.0.1:0/'
self.computer_id = 'computer'
self.supervisord_socket = os.path.join(self._tempdir, 'supervisord.sock')
self.supervisord_configuration_path = os.path.join(self._tempdir,
'supervisord')
self.usage_report_periodicity = 1
self.buildout = None
logging.basicConfig(level=logging.DEBUG)
self.grid = slapgrid.Slapgrid(self.software_root, self.instance_root,
self.master_url, self.computer_id, self.supervisord_socket,
self.supervisord_configuration_path, self.usage_report_periodicity,
self.buildout)
def tearDown(self):
shutil.rmtree(self._tempdir, True)
class TestBasicSlapgridCP(BasicMixin, unittest.TestCase):
def test_no_software_root(self):
self.assertRaises(OSError, self.grid.processComputerPartitionList)
def test_no_instance_root(self):
os.mkdir(self.software_root)
self.assertRaises(OSError, self.grid.processComputerPartitionList)
def test_no_master(self):
os.mkdir(self.software_root)
os.mkdir(self.instance_root)
self.assertRaises(socket.error, self.grid.processComputerPartitionList)
class MasterMixin(BasicMixin):
def _patchHttplib(self):
"""Overrides httplib"""
import mock.httplib
self.saved_httplib = dict()
for fake in vars(mock.httplib):
self.saved_httplib[fake] = getattr(httplib, fake, None)
setattr(httplib, fake, getattr(mock.httplib, fake))
def _unpatchHttplib(self):
"""Restores httplib overriding"""
import httplib
for name, original_value in self.saved_httplib.items():
setattr(httplib, name, original_value)
del self.saved_httplib
def setUp(self):
self._patchHttplib()
BasicMixin.setUp(self)
def tearDown(self):
self._unpatchHttplib()
# XXX: Hardcoded pid, as it is not configurable in slapos
svc = os.path.join(self.instance_root, 'var', 'run', 'supervisord.pid')
if os.path.exists(svc):
try:
pid = int(open(svc).read().strip())
except ValueError:
pass
else:
os.kill(pid, signal.SIGTERM)
BasicMixin.tearDown(self)
class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
def test_nothing_to_do(self):
def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse(path.lstrip('/'))
parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == 'getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = []
slap_computer._computer_partition_list = []
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
os.mkdir(self.software_root)
os.mkdir(self.instance_root)
self.assertTrue(self.grid.processComputerPartitionList())
self.assertSortedListEqual(os.listdir(self.instance_root), ['etc', 'var'])
self.assertSortedListEqual(os.listdir(self.software_root), [])
def test_one_partition(self):
def server_response(self, path, method, body, header):
parsed_url = urlparse.urlparse('/' + path)
parsed_qs = urlparse.parse_qs(parsed_url.query)
if parsed_url.path == '/getComputerInformation' and \
'computer_id' in parsed_qs:
slap_computer = slapos.slap.Computer(parsed_qs['computer_id'])
slap_computer._software_release_list = []
partition = slapos.slap.ComputerPartition(parsed_qs['computer_id'],
'0')
partition._need_modification = True
sr = slapos.slap.SoftwareRelease()
sr._software_release = 'http://sr/'
partition._software_release_document = sr
partition._requested_state = 'stopped'
slap_computer._computer_partition_list = [partition]
return (200, {}, xml_marshaller.xml_marshaller.dumps(slap_computer))
else:
return (404, {}, '')
httplib.HTTPConnection._callback = server_response
os.mkdir(self.software_root)
os.mkdir(self.instance_root)
partition_path = os.path.join(self.instance_root, '0')
os.mkdir(partition_path, 0750)
software_hash = slapos.grid.utils.getSoftwareUrlHash('http://sr/')
srdir = os.path.join(self.software_root, software_hash)
os.mkdir(srdir)
open(os.path.join(srdir, 'template.cfg'), 'w').write(
"""[buildout]""")
srbindir = os.path.join(srdir, 'bin')
os.mkdir(srbindir)
open(os.path.join(srbindir, 'buildout'), 'w').write("""#!/bin/sh
touch worked""")
os.chmod(os.path.join(srbindir, 'buildout'), 0755)
self.assertTrue(self.grid.processComputerPartitionList())
self.assertSortedListEqual(os.listdir(self.instance_root), ['0', 'etc',
'var'])
self.assertSortedListEqual(os.listdir(self.software_root),
[software_hash])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment