Commit Graph

392 Commits

Author SHA1 Message Date
Qi Luo
1239310e02 [docker-config-engine-stretch]: Add missing dependency PYTHON2_SWSSCOMMON (#6538)
Otherwise all the docker image derived from docker-config-engine-stretch will have broken SONIC_CONFIG_ENGINE_PY2
The bug is introduced in #6406
2021-01-23 21:05:45 -08:00
Qi Luo
28b62bee3f sonic-config-engine uses libswsscommon instead of swsssdk (#6406)
**- Why I did it**
swsssdk will be deprecated. Migrate sonic-config-engine to use libswsscommon library instead

**- How to verify it**
Unit test
2021-01-22 10:56:13 -08:00
Joe LeVeque
238ff9f289 [sonic-platform-common] Enable pytest during build for Python 3 package (#6442)
**- Why I did it**

To enable running Pytest unit tests before building the Python 3 sonic-platform-common package

**- How I did it**

- Add Python 3 sonic-config-engine package as a dependency of Python 3 sonic-platform-common package (needed for both runtime and unit tests)
- No longer disable unit tests when building Python 3 sonic-platform-common package
2021-01-15 08:19:58 -08:00
Joe LeVeque
bd5147bbed [swss] Depend on Python 3 version of swsscommon rather than Python 2 (#6432)
The only Python code in the SwSS package, restore_neighbors.py, was recently converted to Python 3 and most dependencies were updated as part of #6207. However, the SwSS makefile still listed the Python 2 version of the swsscommon package as a dependency. This caused Python 2-related packages to be installed in containers unnecessarily.
2021-01-15 08:18:43 -08:00
Kalimuthu-Velappan
e6de7d3286 [build]: Fix for missing dependencies in the DPKG framework (#6393)
1. Fixes the missing DPKG file for gbsyncd-vs package
2. Fixes the softlink issue on the Platform-common and ztp package
3. Fixes the PYTHNON_DEBS list is missing for DBG dockers.
2021-01-15 08:18:20 -08:00
lguohan
45b724fe76 [build]: fix dpkg admindir corruption issue in parallel build (#6408)
Fix #119

when parallel build is enable, multiple dpkg-buildpackage
instances are running at the same time. /var/lib/dpkg is shared
by all instances and the /var/lib/dpkg/updates could be corrupted
and cause the build failure.

the fix is to use overlay fs to mount separate /var/lib/dpkg
for each dpkg-buildpackage instance so that they are not affecting
each other.

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2021-01-12 06:22:51 -08:00
Junchao-Mellanox
d00dc06945 [xcvrd] Remove dependency on SONIC_PLATFORM_API_PY2 and SONIC_PLATFORM_API_PY3 (#6344)
Remove the build time dependency on SONIC_PLATFORM_API_PY2 and SONIC_PLATFORM_API_PY3 from xcvrd make rule
2021-01-06 06:19:32 -08:00
lguohan
711b7f8079 [frr]: change frr debug package to extra to avoid build break for dbg image (#6340)
build frr dbg image force to install frr in the build process
which breaks the current build and is uneccessary.

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2021-01-04 23:23:28 -08:00
Guohan Lu
9b2274a4f1 [build]: add artifical dependency between libyang and frr
frr build requires libyang 1.0.184 which conflicts with
libyang 1.0.73. Solution here is to compile frr and libyang 1.0.184
first, and then uninstall libyang 1.0.184 after frr build.
Then, compile libyang 1.0.73 and all packages depend on it later.

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2021-01-03 06:04:00 -08:00
Guohan Lu
91bf30422c [frr]: remove dependency betwee frr and frr-snmp
no instalation of frr during the build process

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2021-01-03 06:03:56 -08:00
Guohan Lu
83781b9459 [build]: fix dpkg uninstall bug
fix a bug when there are multiple debian packages to be uninstalled

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2021-01-03 06:03:47 -08:00
Joe LeVeque
566ea4f601
[system-health] Convert to Python 3 (#5886)
- Convert system-health scripts to Python 3
- Build and install system-health as a Python 3 wheel
- Also convert newlines from DOS to UNIX
2020-12-29 14:04:09 -08:00
Pavel Shirshov
a7b8f8914e Patch libyang1.0.184 so version and let frr 7.5 use the patched version 2020-12-29 03:44:49 -08:00
Ubuntu
273846a412 FRR 7.5
Build libyang1 which is required for frr 7.5
2020-12-29 03:44:49 -08:00
Junchao-Mellanox
51f896b33e
Add pmon daemons python3 build support (#6176)
**- Why I did it**

python2 is end of life and SONiC is going to support python3. This PR is going to support:

1. Build pmon daemons with python3
2. Install and run python3 version pmon daemons

**- How I did it**

1. Change pmon daemons make files to build bothe python2 and python3 whl
2. Change docker-platform-monitor make files to install both python2 and python3 whl
3. Change pmon docker startup files to start pmon daemons according to the supported platform API version
2020-12-28 10:19:24 -08:00
Guohan Lu
470ed18a6b [build]: disable unit tests for sonic-utilities
unit tests are running for sonic utilitie repo

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2020-12-27 20:06:18 -08:00
lguohan
a79fcb49d4
[build]: add option to pull sonic-slave docker from registry (#6300)
- add config option ENABLE_DOCKER_BASE_PULL to pull sonic-slave docker from registry
- use REGISTRY_PORT, REGISTRY_SERVER to specify docker registry

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2020-12-26 10:30:51 -08:00
Joe LeVeque
d40c9a1e8d
[docker-base-buster][docker-config-engine-buster] No longer install Python 2 (#6162)
**- Why I did it**

As part of migrating SONiC codebase from Python 2 to Python 3

**- How I did it**

- No longer install Python 2 in docker-base-buster or docker-config-engine-buster.
- Install Python 2 and pip2 in the following containers until we can completely eliminate it there:
    - docker-platform-monitor
    - docker-sonic-mgmt-framework
    - docker-sonic-vs
- Pin pip2 version <21 where it is still temporarily needed, as pip version 21 will drop support for Python 2
- Also preform some other cleanup, ensuring that pip3, setuptools and wheel packages are installed in docker-base-buster, and then removing any attempts to re-install them in derived containers
2020-12-25 21:29:25 -08:00
lguohan
aa1cc848e2
[sonic-yang-mgmt-py2]: remove sonic-yang-mgmt py2 (#6262)
No longer needed as sonic-utilties has been moved python3

Signed-off-by: Guohan Lu <lguohan@gmail.com>
2020-12-22 21:05:33 -08:00
Renuka Manavalan
ba02209141
First cut image update for kubernetes support. (#5421)
* First cut image update for kubernetes support.
With this,
    1)  dockers dhcp_relay, lldp, pmon, radv, snmp, telemetry are enabled
        for kube management
        init_cfg.json configure set_owner as kube for these

    2)  Each docker's start.sh updated to call container_startup.py to register going up
          As part of this call, it registers the current owner as local/kube and its version
          The images are built with its version ingrained into image during build

    3)  Update all docker's bash script to call 'container start/stop/wait' instead of 'docker start/stop/wait'.
         For all locally managed containers, it calls docker commands, hence no change for locally managed.
        
    4)  Introduced a new ctrmgrd service, that helps with transition between owners as  kube & local and carry over any labels update from STATE-DB to API server

    5)  hostcfgd updated to handle owner change

    6) Reboot scripts are updatd to tag kube running images as local, so upon reboot they run the same image.

   7) Added kube_commands.py to handle all updates with Kubernetes API serrver -- dedicated for k8s interaction only.
2020-12-22 08:01:33 -08:00
xumia
0a36de3a89
Recover "Support SONiC Reproduceable Build-debian/pip/web packages (#6255)
* Revert "Revert "Support SONiC Reproduceable Build-debian/pip/web packages (#5718)""

This reverts commit 17497a65e3.

* Revert "Revert "Remove unnecessary sudo authority in build Makefile (#6237)""

This reverts commit 163b7111b5.
2020-12-21 15:31:10 +08:00
Guohan Lu
17497a65e3 Revert "Support SONiC Reproduceable Build-debian/pip/web packages (#5718)"
This reverts commit 55a707586b.
2020-12-18 23:37:27 -08:00
xumia
55a707586b
Support SONiC Reproduceable Build-debian/pip/web packages (#5718)
* Support SONiC reproduceable build for deb/py2/py3/web

* Remove j2 files

* Fix bug

* Fix some issues

1. Change some code format issues
2. Fix curl calling wget command, pip2 calling pip3 issue
3. Fix wget/curl downloading multiple urls issue

* Fix some code format issue

* Fix bug

* Fix bug

* Fix command path hard code in build info scripts issue

* Add debian package sonic-build-tools

* Fix auto debian package removed issue

* Change build debian package name, and change the folder

* Collect the pre-versions and post-versions

* Change to use debian:buster

* Remove apt-mark and improve code

* Remove set_build_hooks

* Change docker trusted gpg files

* Fix docker build COPY directory name issue

* Move the trusted gpg files into the sonic-build-hooks package
2020-12-17 13:06:53 +08:00
mprabhu-nokia
00cea080af
Chassisd to monitor cards in a modular chassis (#5523)
HLD: Azure/SONiC#646

Introducing chassisd process to monitor status of the control, line and fabric cards in a modular chassis.

- Why I did it
Modular Chassis has control-cards, line-cards and fabric-cards along with other peripherals. Chassisd will be a central entity that has visibility of the entire chassis.

- How I did it
Chassisd process will monitor cards in the main thread. Another configuation_handling_task is created to listen to CONFIG_DB for admin_status up/down events. The monitored status is persisted in REDIS-DB.
2020-12-15 16:28:58 -08:00
Sabareesh-Kumar-Anandan
9f4ca01388
[sonic-config-engine] Adding dependent pkgs needed for arm compilation (#6186)
libxslt-dev and libz-dev are dependencies for lxml==4.6.1 which is required for pyangbind==0.8.1

lxml-4.6.2-cp37-cp37m-manylinux1_x86_64.whl is directly downloaded in amd64 whereas in arm this is built from lxml-4.6.2.tar.gz

Signed-off-by: Sabareesh Kumar Anandan <sanandan@marvell.com>
2020-12-15 08:44:46 -08:00
Junchao-Mellanox
51c77b179f
[Mellanox] Add python3 support for Mellanox platform API (#6175)
python2 is end of life and SONiC is going to support python3. This PR is going to support:

1. Mellanox SONiC platform API python3 support
2. Install both python2 and python3 verson of Mellanox SONiC platform API or pmon and host side
2020-12-11 10:51:31 -08:00
Qi Luo
0e554e09ce
[makefile] Remove python-netsnmp deb package from makefile (#6161)
Because no one is using it in buildimage repo
2020-12-09 17:40:07 -08:00
Joe LeVeque
83f0d8240e
[pmon]: Install vanilla 'thrift' Python 2 and 3 packages for Barefoot in host and PMon (#6080)
Barefoot platform vendors' sonic_platform packages import the Python 'thrift' library. Previously, our custom-built package was being installed in the PMon container and host OS. However, we are only building a Python 2 version of that package, which was only intended for use with saithrift.

Fixes #6077
2020-12-04 08:41:17 -08:00
Kalimuthu-Velappan
7bcb18fd92
[frr]: Fix for missing dependency in frr module (#6094)
The soinc-frr module has src/sonic-frr/frr submodule. The FRR sub module dependency files are not added to the DPKG file tracking. The patch includes the following.

- Included the submodule dependency files
- Removes the symbolic files.
2020-12-03 02:35:21 -08:00
lguohan
4812953468
[ntp]: build ntp with various fixes (#6037)
- NTP Bug 1970 (UNLINK_EXPR_SLIST empty list) Fix
- ENOBUFS log message level set to WARN
- Fix audit message seen on console apparmor
- add force-confold option when install ntp

Signed-off-by: Guohan Lu <lguohan@gmail.com>
Co-authored-by: Prabhu Sreenivasan <prabhu.sreenivasan@broadcom>
2020-12-02 15:02:50 -08:00
Kalimuthu-Velappan
61419f5468
[build]: Fixes: fatal: not a git repository error during build (#6090)
It fixes the following error during build.

>>> fatal: not a git repository (or any of the parent directories): .git
        "SONIC_DPKG_CACHE_METHOD"         : "cache"
        "DPKG_CACHE_PATH"                 : "/var/cache/sonic/artifacts"
2020-12-02 10:34:05 -08:00
abdosi
872c85d8e7
[lldp]: Lldp docker to use python3 version of sonic-db-syncd package. (#6046)
Made changes so that Lldp docker start using py3 of sonic-db-syncd

submodule update sonic-db-syncd
5cc29a1b32d8d1f4dfbc967bfea2727c50a49c76 (HEAD -> master, origin/master, origin/HEAD) Changes to convert sonic-dbsyncd from python 2 to 3

Signed-off-by: Abhishek Dosi <abdosi@microsoft.com>
2020-11-30 10:44:40 -08:00
Joe LeVeque
7f4ab8fbd8
[sonic-utilities] Update submodule; Build and install as a Python 3 wheel (#5926)
Submodule updates include the following commits:

* src/sonic-utilities 9dc58ea...f9eb739 (18):
  > Remove unnecessary calls to str.encode() now that the package is Python 3; Fix deprecation warning (#1260)
  > [generate_dump] Ignoring file/directory not found Errors (#1201)
  > Fixed porstat rate and util issues (#1140)
  > fix error: interface counters is mismatch after warm-reboot (#1099)
  > Remove unnecessary calls to str.decode() now that the package is Python 3 (#1255)
  > [acl-loader] Make list sorting compliant with Python 3 (#1257)
  > Replace hard-coded fast-reboot with variable. And some typo corrections (#1254)
  > [configlet][portconfig] Remove calls to dict.has_key() which is not available in Python 3 (#1247)
  > Remove unnecessary conversions to list() and calls to dict.keys() (#1243)
  > Clean up LGTM alerts (#1239)
  > Add 'requests' as install dependency in setup.py (#1240)
  > Convert to Python 3 (#1128)
  > Fix mock SonicV2Connector in python3: use decode_responses mode so caller code will be the same as python2 (#1238)
  > [tests] Do not trim from PATH if we did not append to it; Clean up/fix shebangs in scripts (#1233)
  > Updates to bgp config and show commands with BGP_INTERNAL_NEIGHBOR table (#1224)
  > [cli]: NAT show commands newline issue after migrated to Python3 (#1204)
  > [doc]: Update Command-Reference.md (#1231)
  > Added 'import sys' in feature.py file (#1232)

* src/sonic-py-swsssdk 9d9f0c6...1664be9 (2):
  > Fix: no need to decode() after redis client scan, so it will work for both python2 and python3 (#96)
  > FieldValueMap `contains`(`in`)  will also work when migrated to libswsscommon(C++ with SWIG wrapper) (#94)

- Also fix Python 3-related issues:
    - Use integer (floor) division in config_samples.py (sonic-config-engine)
    - Replace print statement with print function in eeprom.py plugin for x86_64-kvm_x86_64-r0 platform
    - Update all platform plugins to be compatible with both Python 2 and Python 3
    - Remove shebangs from plugins files which are not intended to be executable
    - Replace tabs with spaces in Python plugin files and fix alignment, because Python 3 is more strict
    - Remove trailing whitespace from plugins files
2020-11-25 10:28:36 -08:00
xumia
98d749128a
Fix docker images rebuilt issue when building each host image (#5925)
* Change back the mtime changed by applying patch

* Fix bug

* Fix bug

* Use the grep or pattern instead to call a new grep command
2020-11-24 21:45:06 +08:00
Sudharsan Dhamal Gopalarathnam
98a434e8c1
Copp Manager Changes (#4861)
*Introduce CoPP Manager infrastructure
Copp service to generate initial copp config template file

Co-authored-by: dgsudharsan <sudharsan_gopalarat@dell.com>
2020-11-23 09:31:42 -08:00
Joe LeVeque
7bf05f7f4f
[supervisor] Install vanilla package once again, install Python 3 version in Buster container (#5546)
**- Why I did it**

We were building a custom version of Supervisor because I had added patches to prevent hangs and crashes if the system clock ever rolled backward. Those changes were merged into the upstream Supervisor repo as of version 3.4.0 (http://supervisord.org/changes.html#id9), therefore, we should be able to simply install the vanilla package via pip. This will also allow us to easily move to Python 3, as Python 3 support was added in version 4.0.0.

**- How I did it**

- Remove Makefiles and patches for building supervisor package from source
- Install Python 3 supervisor package version 4.2.1 in Buster base container
    - Also install Python 3 version of supervisord-dependent-startup in Buster base container
- Debian package installed binary in `/usr/bin/`, but pip package installs in `/usr/local/bin/`, so rather than update all absolute paths, I changed all references to simply call `supervisord` and let the system PATH find the executable to prevent future need for changes just in case we ever need to switch back to build a Debian package, then we won't need to modify these again.
- Install Python 2 supervisor package >= 3.4.0 in Stretch and Jessie base containers
2020-11-19 23:41:32 -08:00
Joe LeVeque
67dbbb33bf
[build] SONiC platform daemons depend on swsscommon library (#5922)
Add dependencies in appropriate makefiles to ensure proper build/installation of SONiC platform daemons (ledd, psud, syseepromd, thermalctld, xcvrd).
2020-11-16 08:50:41 -08:00
Joe LeVeque
56fa3cf494
[sonic-bgpcfgd] Call Python 3 version of sonic-cfggen for testing (#5847)
sonic-bgpcfgd build fails in the absence of Python 2, as it attempts to explicitly call sonic-cfggen using `/usr/bin/python2.7`. Also, it attempts to call sonic-cfggen using a local, relative path. Since the sonic-config-engine package is not installed, neither are its dependencies.

Now, we configure the Python 3 sonic-config-engine as a dependency of sonic-bgpcfgd, which ensures the Python 3 sonic-config-engine package and its dependencies are installed before sonic-bgpcfgd is built/tested.
2020-11-13 11:39:16 -08:00
Joe LeVeque
d0c7bd8158
[sonic-py-swsssdk][sonic-snmpagent][sonic-utilities] Update submodules (#5849)
Submodule updates include the following commits. Also adding sonic-swsscommon build dependencies where necessary.

* src/sonic-py-swsssdk 1ea30d2...9d9f0c6 (1):
  > [SonicV2Connector] make decode_responses=True as default, so python2 application need no code change when migrated to python3(#93)

* src/sonic-snmpagent 6e4a796...57e54d9 (3):
  > Interact with Redis by str instead of bytes, migrate to SonicV2Connector with `decode_responses=True` (#171)
  > Add a test case for LLDP_LOC_CHASSIS.lldp_loc_man_addr has only one IPv6 address (#167)
  > [LLDP]: Update init_db to load global database config (#166)

* src/sonic-utilities acfa824...b693cf6 (11):
  > Remove SKU create pytest output directory before execution of the script (#1226)
  > [show][techsupport][multi-ASIC] Add support to collect tech support on multi ASIC platform (#1193)
  > [show] Fix `show ip bgp sum` (#1194)
  > [sonic_sku_create] Move tests from sonic-utilities-tests/ folder to tests/ folder (#1222)
  > Replace swsssdk.SonicV2Connector with swsscommon.SonicV2Connector (SWIG wrapper of C++ implementation) in production code (#1217)
  > Copy missing values from INIT_CFG to config_db as part of db_migration task (#1209)
  > [connect][clear] Support --devicename option for connect/clear line commands (#1214)
  > [consutil][show] Remove root need from show line command (#1218)
  > [Mellanox] SKU creator Tool (#1163)
  > SONiC installer - fix string formatting during image type check (#1197)
  > [show/fgnhg.py] Fix whitespace issues (#1211)
2020-11-12 17:58:56 -08:00
fk410167
a3dd3f55f9
Platform Driver Developement Framework (PDDF) (#4756)
This change introduces PDDF which is described here: https://github.com/Azure/SONiC/pull/536

Most of the platform bring up effort goes in developing the platform device drivers, SONiC platform APIs and validating them. Typically each platform vendor writes their own drivers and platform APIs which is very tailor made to that platform. This involves writing code, building, installing it on the target platform devices and testing. Many of the details of the platform are hard coded into these drivers, from the HW spec. They go through this cycle repetitively till everything works fine, and is validated before upstreaming the code.
PDDF aims to make this platform driver and platform APIs development process much simpler by providing a data driven development framework. This is enabled by:

JSON descriptor files for platform data
Generic data-driven drivers for various devices
Generic SONiC platform APIs
Vendor specific extensions for customisation and extensibility

Signed-off-by: Fuzail Khan <fuzail.khan@broadcom.com>
2020-11-12 10:22:38 -08:00
Garrick He
8d8ed89778
[sflow] Add mVRF support (#5904)
* Bump hsFlowD version to 2.0.28-02 to support mVRF

Signed-off-by: Garrick He <garrick_he@dell.com>
2020-11-12 10:00:22 -08:00
Joe LeVeque
a704ded668
[sonic-utilities] Add Python 3 sonic-yang-mgmt package as a dependency (#5903)
Add Python 3 sonic-yang-mgmt package as a dependency in sonic-utilities makefile.

Recently updated the sonic-utilities Jenkins build environment [here](https://github.com/Azure/sonic-build-tools/pull/185) to begin running tests on the Python 3 version of the sonic-utilities package. However, the build is failing because it attempts to copy the Python 3 sonic-yang-mgmt package from the artifacts of the latest VS build, but the package does not exist because there are no targets which specify it as a dependency. This PR will ensure the Python 3 package is built during the image build process.
2020-11-11 17:58:35 -08:00
Praveen Chaudhary
6156cb2805
[sonic-yang-mgmt] Build PY3 & PY2 packages (#5559)
Moving sonic-yang-mgmt to PY3 to support move of sonic-utilities to PY3.

Signed-off-by: Praveen Chaudhary<pchaudhary@linkedin.com>
2020-11-07 13:03:41 -08:00
pavel-shirshov
13f8e9ce5e
[bgpcfgd]: Convert bgpcfgd and bgpmon to python3 (#5746)
* Convert bgpcfgd to python3

Convert bgpmon to python3
Fix some issues in bgpmon

* Add python3-swsscommon as depends

* Install dependencies

* reorder deps

Co-authored-by: Pavel Shirshov <pavel.contrib@gmail.com>
2020-11-05 10:01:43 -08:00
Joe LeVeque
e3164d5fb4
[lldpmgrd] Convert to Python 3 (#5785)
- Convert lldpmgrd to Python 3
- Install Python 3 swsscommon package in docker-lldp
2020-11-03 12:50:11 -08:00
Blueve
698b5544c9
[openssh] Introduce custom openssh-server package for supporting reverse console SSH (#5717)
* Build and install openssh from source
* Copy openssh deb package to dest folder
* Update make rule
* Update sonic debian extension
* Append empty line before EOF
* Update openssh patch
* Add openssh-server to base image dependency
* Fix indent type
* Fix comments
* Use commit id instead of tag id and add comment

Signed-off-by: Jing Kan jika@microsoft.com
2020-11-02 10:31:15 +08:00
Samuel Angebault
12911ba619
[Arista] Update arista driver submodules (#5736)
- Change `/run/arista` mount to pmon by `/var/run/platform_cache`
 - Python3 by default for Arista platform initialisation
 - Fix outstanding py2/3 compatibility issues (eeprom mostly)
 - Use pytest for unit testing
 - Miscellaneous modular fixes
2020-10-30 04:17:30 -07:00
Joe LeVeque
9e34003136
[sonic-config-engine] Clean up dependencies, pin versions; install Python 3 package in Buster container (#5656)
To clean up the image build procedure, and let setuptools/pip[3] implicitly install Python dependencies. Also use ipaddress package instead of ipaddr.
2020-10-26 13:48:50 -07:00
Shi Su
67408c85aa
[synchronous-mode] Add template file for synchronous mode (#5644)
The orchagent and syncd need to have the same default synchronous mode configuration. This PR adds a template file to translate the default value in CONFIG_DB (empty field) to an explicit mode so that the orchagent and syncd could have the same default mode.
2020-10-23 13:08:35 -07:00
Samuel Angebault
5bfe37ca42
[Arista] Update driver submodules (#5686)
- Enable thermalctld support for our platforms
 - Fix Chassis.get_num_sfp which had an off by one
 - Implement read_eeprom and write_eeprom in SfpBase
 - Refactor of Psus and PsuSlots. Psus they are now detected and metadata reported
 - Improvements to modular support

Co-authored-by: Zhi Yuan Carl Zhao <zyzhao@arista.com>
2020-10-23 12:28:36 -07:00