Repository: dmwm/wmcore
Issue: [py2py3] Exception creating WMAgent component daemons

**Impact of the bug**
WMAgent Python3

**Describe the bug**
Deploying WMAgent Py3 `1.5.0.pre3`, plus a few PRs that have been already merged, shows that we actually cannot start the components `$manage start-agent` because the daemon information fails to be persisted in disk [1].

Once that issue gets fixed, we stumble upon yet another problem, as can be seen in [2].

**How to reproduce it**
Deploy wmagentpy3 `1.5.0.pre3` and run the start-agent command.

**Expected behavior**
We should be able to successfully start Py3 WMAgent components, meaning the Daemon.xml file needs to be properly written out to disk and read back to cross-check the component status.

**Additional context and error message**
[1]
```
Log will be in /data/srv/wmagent/v1.5.0.pre3/install/wmagentpy3/WorkQueueManager 
Waiting 1 seconds, to ensure daemon file is created
Traceback (most recent call last):
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/bin/wmcoreD", line 349, in <module>
    startup(config)
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/bin/wmcoreD", line 223, in startup
    componentObject.startDaemon(keepParent = True)
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/lib/python3.8/site-packages/WMCore/Agent/Harness.py", line 396, in startDaemon
    pid = createDaemon(compSect.componentDir, keepParent)
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/lib/python3.8/site-packages/WMCore/Agent/Daemon/Create.py", line 184, in createDaemon
    return daemonize(workdir=workdir, startmsg=startmsg, keepParent=keepParent)
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/lib/python3.8/site-packages/WMCore/Agent/Daemon/Create.py", line 80, in daemonize
    se = open(stderr, 'a+', 0)
ValueError: can't have unbuffered text I/O
Path for daemon file does not exist!
```

[2]
```
started with pid 2311173
Traceback (most recent call last):
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/bin/wmcoreD", line 349, in <module>
    startup(config)
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/bin/wmcoreD", line 232, in startup
    if not daemon.isAlive():         
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/lib/python3.8/site-packages/WMCore/Agent/Daemon/Details.py", line 81, in isAlive
    dummyse, dummyso, rc = run('ps -p %s' % self['ProcessID'])
  File "/data/srv/wmagent/v1.5.0.pre3/sw.amaltaro/slc7_amd64_gcc630/cms/wmagentpy3/1.5.0.pre3/lib/python3.8/site-packages/WMCore/Agent/Daemon/Details.py", line 31, in run
    proc.stdin.write(command)
TypeError: a bytes-like object is required, not 'str'
```

Changed files:
src/python/WMCore/Agent/Daemon/Create.py, src/python/WMCore/Agent/Daemon/Details.py

diff --git a/src/python/WMCore/Agent/Daemon/Create.py b/src/python/WMCore/Agent/Daemon/Create.py
index 035a1765d..9bf91b893 100644
--- a/src/python/WMCore/Agent/Daemon/Create.py
+++ b/src/python/WMCore/Agent/Daemon/Create.py
@@ -27,7 +27,7 @@ import os
 import sys
 import time
 from logging.handlers import RotatingFileHandler
-from xml.dom.minidom import Document, Element
+from xml.dom.minidom import Document
 
 # File mode creation mask of the daemon.
 UMASK = 0o022
@@ -91,37 +91,36 @@ def daemonize(stdout='/dev/null', stderr=None, stdin='/dev/null',
         # the parent, so we give the child complete control over permissions.
         os.umask(UMASK)
 
-        daemon = Element("Daemon")
-        processId = Element("ProcessID")
+        xmlDoc = Document()
+        daemon = xmlDoc.createElement("Daemon")
+        processId = xmlDoc.createElement("ProcessID")
         processId.setAttribute("Value", str(os.getpid()))
         daemon.appendChild(processId)
 
-        parentProcessId = Element("ParentProcessID")
+        parentProcessId = xmlDoc.createElement("ParentProcessID")
         parentProcessId.setAttribute("Value", str(os.getppid()))
         daemon.appendChild(parentProcessId)
 
-        processGroupId = Element("ProcessGroupID")
+        processGroupId = xmlDoc.createElement("ProcessGroupID")
         processGroupId.setAttribute("Value", str(os.getpgrp()))
         daemon.appendChild(processGroupId)
 
-        userId = Element("UserID")
+        userId = xmlDoc.createElement("UserID")
         userId.setAttribute("Value", str(os.getuid()))
         daemon.appendChild(userId)
 
-        effectiveUserId = Element("EffectiveUserID")
+        effectiveUserId = xmlDoc.createElement("EffectiveUserID")
         effectiveUserId.setAttribute("Value", str(os.geteuid()))
         daemon.appendChild(effectiveUserId)
 
-        groupId = Element("GroupID")
+        groupId = xmlDoc.createElement("GroupID")
         groupId.setAttribute("Value", str(os.getgid()))
         daemon.appendChild(groupId)
 
-        effectiveGroupId = Element("EffectiveGroupID")
+        effectiveGroupId = xmlDoc.createElement("EffectiveGroupID")
         effectiveGroupId.setAttribute("Value", str(os.getegid()))
         daemon.appendChild(effectiveGroupId)
 
-        dom = Document()
-        dom.appendChild(daemon)
         with open("Daemon.xml", "w") as props:
             props.write(daemon.toprettyxml())
 
diff --git a/src/python/WMCore/Agent/Daemon/Details.py b/src/python/WMCore/Agent/Daemon/Details.py
index 7da804a0c..8153e70a3 100644
--- a/src/python/WMCore/Agent/Daemon/Details.py
+++ b/src/python/WMCore/Agent/Daemon/Details.py
@@ -19,6 +19,9 @@ import time
 # FIXME: needs to be replaced with persistent backend.
 from xml.dom.minidom import parse
 
+from Utils.PythonVersion import PY3
+from Utils.Utilities import encodeUnicodeToBytesConditional
+
 
 def run(command):
     proc = subprocess.Popen(
@@ -28,7 +31,7 @@ def run(command):
         stdin=subprocess.PIPE,
         )
 
-    proc.stdin.write(command)
+    proc.stdin.write(encodeUnicodeToBytesConditional(command, condition=PY3))
     stdout, stderr = proc.communicate()
     rc = proc.returncode