3 # Copyright 2016 RIFT.IO Inc
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
19 @author Varun Prasad(varun.prasad@riftio.com)
32 gi
.require_version('RwcalYang', '1.0')
33 gi
.require_version('RwCal', '1.0')
34 gi
.require_version('RwLog', '1.0')
36 from . import server
as cal_server
37 import rift
.cal
.utils
as cal_util
38 import rift
.rwcal
.cloudsim
.shell
as shell
42 class CloudsimServerOperations(cal_util
.CloudSimCalMixin
):
43 """Convenience class to provide start, stop and cleanup operations
46 log (logging): Log instance
47 PID_FILE (str): Location to generate the PID file.
49 PID_FILE
= "/var/log/rift/cloudsim_server.pid"
51 def __init__(self
, log
):
59 with
open(self
.PID_FILE
) as fh
:
60 pid
= fh
.readlines()[0]
61 pid
= int(pid
.strip())
63 self
.log
.error("Looks like the pid file does not contain a valid ID")
65 self
.log
.debug("No PID file found.")
69 def is_pid_exists(self
, pid
):
77 def start_server(self
, foreground
=False):
78 """Start the tornado app """
80 # Before starting verify if all requirements are satisfied
81 cal_server
.CalServer
.verify_requirements(self
.log
)
83 # If the /var/log directory is not present, then create it first.
84 if not os
.path
.exists(os
.path
.dirname(self
.PID_FILE
)):
85 self
.log
.warning("Creating /var/log/rift directory for log storage")
86 os
.makedirs(os
.path
.dirname(self
.PID_FILE
))
88 # Check if an exiting PID file is present, if so check if it has an
89 # associated proc, otherwise it's a zombie file so clean it.
90 # Otherwise the daemon fails silently.
91 if self
.pid
is not None and not self
.is_pid_exists(self
.pid
):
92 self
.log
.warning("Removing stale PID file")
93 os
.remove(self
.PID_FILE
)
97 def start(daemon_mode
=False):
99 log
= cal_util
.Logger(daemon_mode
=daemon_mode
, log_name
='')
100 log
.logger
.info("Starting the cloud server.")
101 server
= cal_server
.CalServer()
105 # Write the PID file for consistency
106 with
open(self
.PID_FILE
, mode
='w') as fh
:
107 fh
.write(str(os
.getpid()) + "\n")
110 context
= daemon
.DaemonContext(
111 pidfile
=daemon
.pidfile
.PIDLockFile(self
.PID_FILE
))
113 start(daemon_mode
=True)
115 def stop_server(self
):
116 """Stop the daemon"""
118 def kill_pid(pid
, sig
):
119 self
.log
.info("Sending {} to PID: {}".format(str(sig
), pid
))
123 def search_and_kill():
124 """In case the PID file is not found, and the server is still
125 running, as a last resort we search thro' the process table
126 and stop the server."""
127 cmd
= ["pgrep", "-u", "daemon,root", "python3"]
130 pids
= subprocess
.check_output(cmd
)
131 except subprocess
.CalledProcessError
:
132 self
.log
.error("No Cloudsim server process found. "
133 "Please ensure Cloudsim server is running")
136 pids
= map(int, pids
.split())
139 if pid
!= os
.getpid():
142 def wait_till_exit(pid
, timeout
=30, retry_interval
=1):
143 start_time
= time
.time()
146 if not self
.is_pid_exists(pid
):
147 msg
= "Killed {}".format(pid
)
151 time_elapsed
= time
.time() - start_time
152 time_remaining
= timeout
- time_elapsed
154 self
.log
.info("Process still exists, trying again in {} sec(s)"
155 .format(retry_interval
))
157 if time_remaining
<= 0:
158 msg
= 'Process {} has not yet terminated within {} secs. Trying SIGKILL'
159 self
.log
.error(msg
.format(pid
, timeout
))
162 time
.sleep(min(time_remaining
, retry_interval
))
164 def kill_sequence(pid
):
165 kill_pid(pid
, signal
.SIGHUP
)
166 wait_till_exit(pid
, timeout
=10, retry_interval
=2)
167 kill_pid(pid
, signal
.SIGKILL
)
168 status
= wait_till_exit(pid
)
171 # Remove the lock file.
172 shell
.command("rm -f {}".format(self
.PID_FILE
))
176 self
.log
.warning("Server running with PID: {} found, "
177 "trying to stop it".format(pid
))
180 self
.log
.warning("No PID file found. Searching the process "
184 def clean_server(self
, images
=False):
185 """Clean all resource using rest APIs. """
188 _
, vdus
= self
.cal
.get_vdu_list(self
.account
)
189 for vdu
in vdus
.vdu_info_list
:
190 self
.cal
.delete_vdu(self
.account
, vdu
.vdu_id
)
193 _
, vlinks
= self
.cal
.get_virtual_link_list(self
.account
)
194 for vlink
in vlinks
.virtual_link_info_list
:
195 self
.cal
.delete_virtual_link(self
.account
, vlink
.virtual_link_id
)
198 _
, images
= self
.cal
.get_image_list(self
.account
)
199 for image
in images
.image_info_list
:
200 self
.cal
.delete_image(self
.account
, image
.id)