| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
| |
There was a type update to our configErrors state from a list of errors
to a dict containing a list of errors and a ready state flag. This broke
the map() call on configErrors in the dedicated config errors page
because you can't map an object only an Array. We fix this by mapping
the objects errors attribute into the page as the config errors allowing
us to keep mapping over it.
Change-Id: Ib84ca9241fb456f9493a07d1c7e1220f5fa925c8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The change to automatically filter out skipped builds inadvertently
affected the buildsets tab as well since they share the query builder.
This caused the buildsets tab to automatically append a filter which
is invalid for buildsets and therefore return a 404.
This change adds an argument to the query builder to indicate whether
it should include the automatic filter.
Additionally, the query builder had an error which caused it to
append the query in all cases (which affects the otherwise working
builds tab). This change corrects that as well.
Change-Id: Id03eee51b3551c4b32ae3c6b784b0993c4a3779c
|
|\ |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
When specifying job.override-checkout, we apply job variants from
that match the specified branch. The mechanism we use to do that
is to create a synthetic Ref object to pass to the branch matcher
instead of the real branch of the Change (since the real branch
is likely different -- that's why override-checkout was specified).
However, branch matching behavior has gottes slightly more
sophisticated and Ref objects don't match in the same way that
Change objects do.
In particular, implied branch matchers match Ref subclasses that
have a branch attribute iff the match is exact.
This means that if a user constructed two branches:
* testbranch
* testbranch2
and used override-checkout to favor a job definition from testbranch2,
the implied branch matcher for the variant in testbranch would match
since the matcher behaved as if it were matching a Ref not a Change
or Branch.
To correct this, we update the simulated change object used in the
override-checkout variant matching routine to be a Branch (which
unsurprisingly has a branch attribute) instead of a Ref.
The test test_implied_branch_matcher_similar_override_checkout is added
to cover this test case. Additionally, the test
test_implied_branch_matcher_similar is added for good measure (it tests
implied branch matchers in the same way but without specifying
override-checkout), though its behavior is already correct.
A release note is included since this may have an effect on job behavior.
Change-Id: I1104eaf02f752e8a73e9b04939f03a4888763b27
|
|\ \ |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
GitHub supports a "rebase" merge mode where it will rebase the PR
onto the target branch and fast-forward the target branch to the
result of the rebase.
Add support for this process to the merger so that it can prepare
an effective simulated repo, and map the merge-mode to the merge
operation in the reporter so that gating behavior matches.
This change also makes a few tweaks to the merger to improve
consistency (including renaming a variable ref->base), and corrects
some typos in the similar squash merge test methods.
Change-Id: I9db1d163bafda38204360648bb6781800d2a09b4
|
|\ \ \
| |/ / |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
The default merge mode is 'merge-resolve' because it has been observed
that it more closely matches the behavior of jgit in Gerrit (or, at
least it did the last time we looked into this). The other drivers
are unlikely to use jgit and more likely to use the default git
merge strategy.
This change allows the default to differ based on the driver, and
changes the default for all non-gerrit drivers to 'merge'.
The implementation anticipates that we may want to add more granularity
in the future, so the API accepts a project as an argument, and in
the future, drivers could provide a per-project default (which they
may obtain from the remote code review system). That is not implemented
yet.
This adds some extra data to the /projects endpoint in the REST api.
It is currently not easy (and perhaps not possible) to determine what a
project's merge mode is through the api. This change adds a metadata
field to the output which will show the resulting value computed from
all of the project stanzas. The project stanzas themselves may have
null values for the merge modes now, so the web app now protects against
that.
Change-Id: I9ddb79988ca08aba4662cd82124bd91e49fd053c
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
This updates the web UI to support the requirement for authn/z
for read-only access.
If authz is required for read access, we will automatically redirect.
If we return and still aren't authorized, we will display an
"Authorization required" page (rather than continuing and popping up
API error notifications).
The API methods are updated to send an authorization token whenever
one is present.
Change-Id: I31c13c943d05819b4122fcbcf2eaf41515c5b1d9
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Since we check authorization in every method except info now,
set the headers in the check_auth tool instead of the individual
methods; that way they are set even in the case of a 401.
Change-Id: I397180122e03915694ba6e59b4bd3a743120ee6e
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
This allows configuration of read-only access rules, and corresponding
documentation. It wraps every API method in an auth check (other than
info endpoints).
It exposes information in the info endpoints that the web UI can use
to decide whether it should send authentication information for all
requests. A later change will update the web UI to use that.
Change-Id: I3985c3d0b9f831fd004b2bb010ab621c00486e05
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
We currently only show the login button when in the context of a
tenant. Now that we have an auth context for the "root" level of
a multi-tenant zuul, show the login button there as well.
Change-Id: Ic1d39951a0cf481c6fac4700ba9bb9338478cd7c
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Currently we only set the auth redux property within the tenant
scope. But we're going to extend authentication to outside the
tenant scope (to optionally restrict access to the tenant list).
To accommodate that, we will always update the auth property in
redux any time our tenant changes (including when it changes to
undefined), and we will wait until we have finished auth configuration
before rendering any pages in the app.
This is effectively a no-op change from the end-user point of view,
except that we may wait just a bit longer (for the /api/tenant/info
endpoint to return) before showing an initial page for a tenant.
Change-Id: I18e74fa205f75a7b020bf23c8652226e5170d88b
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Verifying the auth token and obtaining user metadata involves some
async HTTP requests in the background. If we remove the auth callback
information from the window location too soon, then the UserManager
will not complete the login process. This currently generally works
because this process tends to complete before the /info and /tenant/info
calls to Zuul. However, future changes to support a read-only
authentication requirement will need to alter this sequence.
This approach is more robust and easier to follow. Essentially the
sequence is:
* Return from IdP to /auth_callback
* If /auth_callback is in our location, short-circuit normal rendering
and render only the AuthCallbackPage
* When background processing is complete, onSignIn will be called and
we will set the user.redirect property in redux.
* AuthCallbackPage has an effect callback on user.redirect which will
cause it to perform the redirect away from auth_callback once
signin is complete.
This process leaves the AuthCallbackPage on the screen a little longer,
so this change updates it to use the newer EmptyPage and Spinner elements
that we have been using elsewhere, so if users see it, it appears more
intentional.
Change-Id: I206c020626c7fd73e58efc29dd50376203679721
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
In order to allow for authenticated read-only access to zuul-web,
we need to be able to control the authz of the API root. Currently,
we can only specify auth info for tenants. But if we want to control
access to the tenant list itself, we need to be able to specify auth
rules.
To that end, add a new "api-root" tenant configuration object which,
like tenants themselves, will allow attaching authz rules to it.
We don't have any admin-level API endpoints at the root, so this change
does not add "admin-rules" to the api-root object, but if we do develop
those in the future, it could be added.
A later change will add "access-rules" to the api-root in order to
allow configuration of authenticated read-only access.
This change does add an "authentication-realm" to the api-root object
since that already exists for tenants and it will make sense to have
that in the future as well. Currently the /info endpoint uses the
system default authentication realm, but this will override it if
set.
In general, the approach here is that the "api-root" object should
mirror the "tenant" object for all attributes that make sense.
Change-Id: I4efc6fbd64f266e7a10e101db3350837adce371f
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
There is no /api/tenant/$tenant/components URL, so hide the
"Components" link in the page header when the web ui is accessing
a whitelabel tenant.
Change-Id: I707bf03489016264ce6a37b4eb005e9680de90a2
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Authentication checking in the admin methods of zuul-web is very
duplicative. Consolidate all of the auth checks into a cherrypy
tool that we can use to decorate methods.
This tool also anticipates that we will have read-only checks in
the future, but for now, it is still only used for admin checks.
This tool also populates some additional parameters (like tenant
and auth info) so that we don't need to call "getTenantOrRaise"
multiple times in a request.
Several methods performed HTTP method checks inside the method
which inhibits our ability to wrap an entire method with an
auth_check. To resolve this, we now use method conditions on
the routes dispatcher. As a convention, I have put the
options handling on the "GET" methods since they are most likely
to be universal.
Change-Id: Id815efd9337cbed621509bb0f914bdb552379bc7
|
|\ \ \ |
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
This method iterates over all tenants but only needs to return
information about a single tenant. Simplify the calculation for
efficiency.
This includes a change in behavior for unknown tenants. Currently,
a request to /api/tenant/{name}/authorizations will always succeed
even if the tenant does not exist (it will return an authorization
entry indicating the user is not an admin of the unknown tenant).
This is unnecessary and confusing. It will now return a 404 for
the unknown tenant.
In the updated unit test, tenant-two was an unknown tenant; its name
has been updated to 'unknown' to make that clear.
(Since the test asserted that data were returned either way, it is
unclear whether the original author of the unit test expected
tenant-two to be unknown or known.)
Change-Id: I545575fb73ef555b34c207f8a5f2e70935c049aa
|
|\ \ \ \
| |/ / / |
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
This has not beeen used for a while and can be removed. This will
simplify the authorization code in zuul-web.
Change-Id: I0fa6c4fb87672c44d3f97db0be558737b4f102bc
|
|\ \ \ \
| |/ / / |
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
This is a preparatory step to add access-control for read-level
access to the API and web UI. Because we will likely end up with
tenant config that looks like:
- tenant:
name: example
admin-rules: ['my-admin-rule']
access-rules: ['my-read-only-rule']
It does not make sense for 'my-read-only-rule' to be defined as:
- admin-rule:
name: read-only-rule
In other words, the current nomenclature conflates (new word:
nomenconflature) the idea of an abstract authorization rule and
what it authorizes. The new name makes it more clear than an
authorization-rule can be used to authorize more than just admin
access.
Change-Id: I44da8060a804bc789720bd207c34d802a52b6975
|
|\ \ \ \ |
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
In the recent change to omit skipped jobs when reporting, we may
have swung the pendulum too far. While it seems that users may
not want to see a list of hundreds of skipped child_jobs, they may
want to see a list of a small number of skipped jobs due to failed
dependencies.
To try to thread the needle, we omit skipped jobs from the report
iff they were skipped due to zuul_return child_jobs; otherwise
we include them.
Change-Id: I66a223da344a93b4691a969876e887b5eec0e67c
|
|\ \ \ \ \
| |/ / / / |
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
This will make available in the web ui and through the API the
reason for skipped builds.
This will also include more detail on the job line itself in
the report, like this:
- compile: SUCCESS in 3s
- pre-test: FAILURE in 3s
- test: SKIPPED Skipped due to failed job pre-test
Change-Id: Id5dd0c47cd524912fd3d2d0ecc659811f3ec01cb
|
|\ \ \ \ \
| |/ / / / |
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
We have had an on-and-off relationship with skipped builds in the
database. Generally we have attempted to exclude them from the db,
but we have occasionally (accidentally?) included them. The status
quo is that builds with a result of SKIPPED (as well as several
other results which don't come from the executor) are not recorded
in the database.
With a greater interest in being able to determine which jobs ran
or did not run for a change after the fact, this job deliberately
adds all builds (whether they touch an executor or not, whether
real or not) to the database. This means than anything that could
potentially show up on the status page or in a code-review report
will be in the database, and can therefore be seen in the web UI.
It is still the case that we are not actually interested in seeing
a page full of SKIPPED builds when we visit the "Builds" tab in
the web ui (which is the principal reason we have not included them
in the database so far). To address this, we set the default query
in the builds tab to exclude skipped builds (it is easy to add other
types of builds to exclude in the future if we wish). If a user
then specifies a query filter to *include* specific results, we drop
the exclusion from the query string. This allows for the expected
behavior of not showing SKIPPED by default, then as specific results
are added to the filter, we show only those, and if the user selects
that they want to see SKIPPED, they will then be included.
On the buildset page, we add a switch similar to the current "show
retried jobs" switch that selects whether skipped builds in a buildset
should be displayed (again, it hides them by default).
Change-Id: I1835965101299bc7a95c952e99f6b0b095def085
|
|\ \ \ \ \ |
|
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
Change-Id: Icd8c33dfe1c8ffd21a717a1a94f1783c244a6b82
|
|\ \ \ \ \ \ |
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
It is not currently possible for JobData.hash to be None, but in
case that ever happens in the future, handle it in the most defensive
way possible (refresh from ZK) and log the occurence.
Change-Id: I360dd5c4a90a43f261598820b2cfeef863a79013
|
|\ \ \ \ \ \ \
| |/ / / / / / |
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
We try to avoid refreshing JobData from ZK when it is not necessary
(because these objects rarely change). However, a bug in the avoidance
was recently discovered and in fact we have been refreshing them more
than necessary.
This adds a test to catch that case, along with fixing an identical
bug (the same process is used in FrozenJobs and Builds).
The fallout from these bugs may not be exceptionally large, however,
since we generally avoid refreshing FrozenJobs once a build has
started, and avoid refreshing Builds once they have completed,
meaning these bugs may have had little opportunity to show themselves.
Change-Id: I41c3451cf2b59ec18a20f49c6daf716de7f6542e
|
|\ \ \ \ \ \ \
| |/ / / / / /
| | | | | | /
| |_|_|_|_|/
|/| | | | | |
|
| | |_|_|/
| |/| | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
When restoring the jobs from Zookeeper we did not check for the correct
job data attribute on the FrozenJob instance. Instead, we always
restored the job data from Zookeeper.
Change-Id: Ic1561ea4e17b9da7b02e4c613b13bfbbdb70073c
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
This is two changes in one since they both fix breakage due to
external dep changes:
Git no longer allows file urls in submodules by default, but one
of our unit tests relied on that behavior (in order to verify that
we can clone repos with submodules). Run the submodule add command
in the test with a flag which allows file urls.
Pin PyJWT <2.6.0
2.6.0 causes the following error:
2022-10-20 15:58:04,800 cherrypy.error.140001002710128 ERROR [req: 86efa7775e88473a9e9d5e54f0c83050] [20/Oct/2022:15:58:04] HTTP
Traceback (most recent call last):
File "/home/corvus/git/zuul/zuul/.tox/py310/lib/python3.10/site-packages/cherrypy/_cprequest.py", line 638, in respond
self._do_respond(path_info)
File "/home/corvus/git/zuul/zuul/.tox/py310/lib/python3.10/site-packages/cherrypy/_cprequest.py", line 702, in _do_respond
response.finalize()
File "/home/corvus/git/zuul/zuul/.tox/py310/lib/python3.10/site-packages/cherrypy/_cprequest.py", line 901, in finalize
content = self.collapse_body()
File "/home/corvus/git/zuul/zuul/.tox/py310/lib/python3.10/site-packages/cherrypy/_cprequest.py", line 859, in collapse_body
new_body = b''.join(self.body)
File "/home/corvus/git/zuul/zuul/.tox/py310/lib/python3.10/site-packages/cherrypy/_json.py", line 24, in encode
for chunk in _encode(value):
File "/usr/lib/python3.10/json/encoder.py", line 431, in _iterencode
yield from _iterencode_dict(o, _current_indent_level)
File "/usr/lib/python3.10/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/usr/lib/python3.10/json/encoder.py", line 438, in _iterencode
o = _default(o)
File "/usr/lib/python3.10/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type ImmatureSignatureError is not JSON serializable
Change-Id: I2e345f24ea0a62ce8d9dbe1c066438f194e7075c
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
The test_web_labels_allowed_list test has been failing occasionally
due to a timeout waiting to settle. The test ends with an unprocessed
PipelinePostConfig event in the tenant-one.check pipeline management
queue.
In these cases, the scheduler skips processing the tenant-one.check
pipeline because it is locked. We can't see exactly why it's locked,
but based on log messages, it seems likely that one of the periodic
cleanup routines may be responsible. These should finish quickly,
which means the starvation is likely due to a race. I suspect the
sequence is (numbers indicate threads):
1] PipelinePostConfig event emitted
2] Cleanup routine (eg node cleanup) locks the pipeline
1] Main loop wakes up due to the event notification
1] Main loop fails to lock pipeline
1] Main loop sleeps
2] Cleanup routine completes and unlocks pipeline
At this point, the system is idle, and no more events are emitted, so
the main loop never wakes up again.
To address this, we could set the wake flag each time we encounter a
locked pipeline (we do something similiar in other cases), but on a busy
system with two schedulers, that would probably just always set the flag.
The cases where we do that also have other constraints that make the
infinite-wakeup situation less likely.
Instead, whenever we encounter a locked pipeline, let's check to see if
there are any events for that pipeline, and if so, set the wake flag
so that we run through the loop again. This may (probably will) add
an extra loop iteration in many cases (where a second scheduler will
essentially double check that the first scheduler did finish processing
all the events while the first scheduler had the pipeline locked). But
that shouldn't be a huge cost, and it will avoid the starvation
seen in the test, which could really happen on a nearly-idle production
system.
Change-Id: I05536389377b7753fb2430d052d188c7f2a37bff
|
|\ \ \ \ \ |
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
The github pipeline reject docs mimic the Gerrit reject docs which
have an asymmetric require/reject setup. GitHub requirements are
symmetrical, which leaves the docs incomplete.
Correct that by copying the `require` section to `reject` with
a few tweaks.
Change-Id: If0ac228b9246817e71d9038039fcc1eead1c8571
|
|\ \ \ \ \ \
| |/ / / / / |
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
This adds the "draft" PR status as a pipeline requirement to the
GitHub driver. It is already used implicitly in dependent pipelines,
but this will allow it to be added explicitly to other pipelines
(for example, check).
This also fixes some minor copy/pasta errors in debug messages related
to github pipeline requirements.
Change-Id: I05f8f61aee251af24c1479274904b429baedb29d
|
|\ \ \ \ \ \ |
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
Some test failures originate due to an apscheduler thread that is
still running. Add some debugging to the timer driver to try to
help identify if there is a problem with the start/stop sequence.
Change-Id: Idcaf7ac0adfff737d88d2f42fcc4e1305bfea607
|
|\ \ \ \ \ \ \
| |/ / / / / / |
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
Some tests are failing to settle because the ZK queues are not
empty, but it is not clear which queue, and that makes the trouble
hard to track down. Add debugging around this to try to understand
the problem more.
Change-Id: I5012dec9f80e5413c5303698325d510554d22d3a
|
|\ \ \ \ \ \ \
| |/ / / / / / |
|
| | |/ / / /
| |/| | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
If a reconfiguration happens after the timer connection is stopped,
we should not restart the apscheduler; that can lead to zombie
threads.
We should not perferm a reconfiguration after stopping the connection
anyway, so to correct that, change the shutdown sequence so that we
stop the layout update thread before we stop the connections.
Change-Id: If9c387dfc42fcba7de3969d81cf2c7917d7e4fa3
|
|\ \ \ \ \ \ |
|