Package roslib :: Module os_detect
[frames] | no frames]

Source Code for Module roslib.os_detect

  1  #!/usr/bin/env python 
  2  # Copyright (c) 2009, Willow Garage, Inc. 
  3  # All rights reserved. 
  4  #  
  5  # Redistribution and use in source and binary forms, with or without 
  6  # modification, are permitted provided that the following conditions are met: 
  7  #  
  8  #     * Redistributions of source code must retain the above copyright 
  9  #       notice, this list of conditions and the following disclaimer. 
 10  #     * Redistributions in binary form must reproduce the above copyright 
 11  #       notice, this list of conditions and the following disclaimer in the 
 12  #       documentation and/or other materials provided with the distribution. 
 13  #     * Neither the name of the Willow Garage, Inc. nor the names of its 
 14  #       contributors may be used to endorse or promote products derived from 
 15  #       this software without specific prior written permission. 
 16  #  
 17  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 18  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 19  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 20  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 21  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 22  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 23  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 24  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 25  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 26  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 27  # POSSIBILITY OF SUCH DAMAGE. 
 28   
 29  # Author Tully Foote/tfoote@willowgarage.com 
 30   
 31  """ 
 32  Library for detecting the current OS, including detecting specific 
 33  Linux distributions.  
 34   
 35  The APIs of this library are still very coupled with the rosdep  
 36  command-line tool. 
 37  """ 
 38   
 39  import roslib.exceptions 
 40  import os 
 41  import sys 
 42  import subprocess 
 43  import types 
 44  import tempfile 
 45  import distutils.version # To parse version numbers 
 46   
 47  if sys.hexversion > 0x03000000: #Python3 
 48      python3 = True 
 49  else: 
 50      python3 = False 
 51   
 52  ####### Linux Helper Functions ##### 
53 -def _read_stdout(cmd):
54 pop = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 55 (std_out, std_err) = pop.communicate() 56 if python3: 57 return std_out.decode() 58 else: 59 return std_out
60
61 -def lsb_get_os():
62 """ 63 Linux: wrapper around lsb_release to get the current OS 64 """ 65 try: 66 return _read_stdout(['lsb_release', '-si']).strip() 67 except: 68 return None
69
70 -def lsb_get_codename():
71 """ 72 Linux: wrapper around lsb_release to get the current OS codename 73 """ 74 try: 75 return _read_stdout(['lsb_release', '-sc']).strip() 76 except: 77 return None
78
79 -def lsb_get_version():
80 """ 81 Linux: wrapper around lsb_release to get the current OS version 82 """ 83 try: 84 return _read_stdout(['lsb_release', '-sr']).strip() 85 except: 86 return None
87
88 -def uname_get_machine():
89 """ 90 Linux: wrapper around uname to determine if OS is 64-bit 91 """ 92 try: 93 return _read_stdout(['uname', '-m']).strip() 94 except: 95 return None
96 97 98 99 #### Override class for debugging and unsupported OSs ###########
100 -class OSOverride:
101 - def __init__(self):
102 self._os_name = "uninitialized from ROS_OS_OVERRIDE=name:version" 103 self._os_version = "uninitialized from ROS_OS_OVERRIDE=name:version"
104
105 - def check_presence(self):
106 try: 107 (self._os_name, self._os_version) = os.environ["ROS_OS_OVERRIDE"].split(':') 108 sys.stderr.write("Using environment variable ROS_OS_OVERRIDE name = %s version = %s\n"%(self._os_name, self._os_version)) 109 return True 110 except: 111 return False
112
113 - def get_version(self):
114 return self._os_version
115
116 - def get_name(self):
117 return self._os_name
118 119
120 -class OSDetectException(roslib.exceptions.ROSLibException): pass
121
122 -class OSBase:
123 """ 124 This defines the API used for OS detection within the os_detect 125 module for roslib. All OS specific instantiantions must inherit 126 and override these methods. 127 """
128 - def check_presence(self):
129 """ 130 Return if the specific OS which this class is designed to 131 detect is present. Only one version of this class should return for 132 any version. 133 """ 134 raise OSDetectException("check_presence unimplemented")
135
136 - def get_name(self):
137 """ 138 Return the standardized name for this OS. (ala Ubuntu Hardy Heron = "ubuntu") 139 """ 140 raise OSDetectException("get_name unimplemented")
141
142 - def get_version(self):
143 """ 144 Return the standardized version for this OS. (ala Ubuntu Hardy Heron = "8.04") 145 """ 146 raise OSDetectException("get_version unimplemented")
147 148 149 ###### Debian SPECIALIZATION #########################
150 -class Debian(OSBase):
151 """ 152 Detect Debian OS. 153 """
154 - def check_presence(self):
155 if "Debian" == lsb_get_os(): 156 return True 157 return False
158
159 - def get_version(self):
160 return lsb_get_codename()
161 - def get_name(self):
162 return "debian"
163 164 ###### END Debian SPECIALIZATION ######################## 165 166 ###### Mandriva SPECIALIZATION #########################
167 -class Mandriva(OSBase):
168 """ 169 Detect Mandriva OS. The returned version will be the year release (e.g. 170 2010.0) concatenated with the machine architecture (e.g. x86_64), resulting 171 in something like 2010.0x86_64. 172 """
173 - def check_presence(self):
174 if "MandrivaLinux" == lsb_get_os(): 175 return True 176 return False
177
178 - def get_version(self):
180 - def get_name(self):
181 return "mandriva"
182 183 ###### END Mandriva SPECIALIZATION ######################## 184 185 186 187 ###### UBUNTU SPECIALIZATION #########################
188 -class Ubuntu(Debian):
189 """ This is an implementation of a standard interface for 190 interacting with rosdep. This defines all Ubuntu sepecific 191 methods, including detecting the OS/Version number. As well as 192 how to check for and install packages."""
193 - def check_presence(self):
194 if "Ubuntu" == lsb_get_os(): 195 return True 196 return False
197
198 - def get_version(self):
199 return lsb_get_codename()
200 - def get_name(self):
201 return "ubuntu"
202 203 ###### END UBUNTU SPECIALIZATION ######################## 204 205 ###### Mint SPECIALIZATION #########################
206 -class Mint(OSBase):
207 """ 208 Detect Mint variants of Debian. 209 """
210 - def check_presence(self):
211 if "LinuxMint" == lsb_get_os(): 212 return True 213 return False
214
215 - def get_version(self):
216 return lsb_get_version()
217
218 - def get_name(self):
219 return "mint"
220 ###### END Mint SPECIALIZATION ######################## 221 222 ###### OpenSuse SPECIALIZATION #########################
223 -class OpenSuse(OSBase):
224 """ 225 Detect OpenSuse OS. 226 """
227 - def check_presence(self):
228 try: 229 filename = "/etc/SuSE-brand" 230 if os.path.exists(filename): 231 with open(filename, 'r') as fh: 232 os_list = fh.read().split() 233 if len(os_list) > 0 and os_list[0] == "openSUSE": 234 return True 235 except: 236 pass 237 return False
238
239 - def get_version(self):
240 try: 241 filename = "/etc/SuSE-brand" 242 if os.path.exists(filename): 243 with open(filename, 'r') as fh: 244 os_list = fh.read().strip().split('\n') 245 if len(os_list) == 2: 246 os_list = os_list[1].split(' = ') 247 if os_list[0] == "VERSION": 248 return os_list[1] 249 except: 250 return False 251 252 return False
253
254 - def get_name(self):
255 return "opensuse"
256 257 ###### END OpenSuse SPECIALIZATION ######################## 258 259 260 ###### Fedora SPECIALIZATION #########################
261 -class Fedora(OSBase):
262 """ 263 Detect Fedora OS. 264 """
265 - def check_presence(self):
266 try: 267 filename = "/etc/redhat-release" 268 if os.path.exists(filename): 269 with open(filename, 'r') as fh: 270 os_list = fh.read().split() 271 if os_list and os_list[0] == "Fedora" and os_list[1] == "release": 272 return True 273 except: 274 pass 275 return False
276
277 - def get_version(self):
278 try: 279 filename = "/etc/issue" 280 if os.path.exists(filename): 281 with open(filename, 'r') as fh: 282 os_list = fh.read().split() 283 if os_list[0] == "Fedora" and os_list[1] == "release": 284 return os_list[2] 285 except: 286 sys.stderr.write("Fedora failed to get version\n") 287 return False 288 289 return False
290
291 - def get_name(self):
292 return "fedora"
293 294 ###### END Fedora SPECIALIZATION ######################## 295 296 ###### Rhel SPECIALIZATION #########################
297 -class Rhel(Fedora):
298 """ 299 Detect Redhat OS. 300 """
301 - def check_presence(self):
302 try: 303 filename = "/etc/redhat-release" 304 if os.path.exists(filename): 305 with open(filename, 'r') as fh: 306 os_list = fh.read().split() 307 if os_list and os_list[2] == "Enterprise": 308 return True 309 except: 310 pass 311 return False
312
313 - def get_version(self):
314 try: 315 filename = "/etc/issue" 316 if os.path.exists(filename): 317 with open(filename, 'r') as fh: 318 os_list = fh.read().split() 319 if os_list and os_list[2] == "Enterprise": 320 return os_list[6] 321 except: 322 sys.stderr.write("Rhel failed to get version\n") 323 return False 324 325 return False
326
327 - def get_name(self):
328 return "rhel"
329 330 ###### END Rhel SPECIALIZATION ######################## 331 332 ###### OSX SPECIALIZATION #########################
333 -def port_detect(p):
334 """ 335 Detect presence of Macports by running "port installed" command. 336 """ 337 std_out = _read_stdout(['port', 'installed', p]) 338 return (std_out.count("(active)") > 0)
339
340 -class Osx(OSBase):
341 """ 342 Detect OS X 343 """
344 - def check_presence(self):
345 filename = "/usr/bin/sw_vers" 346 if os.path.exists(filename): 347 return True 348 return False
349
350 - def get_version(self):
351 # REP 111 this should be the code name (e.g., lion, snow, tiger) #3570 352 std_out = _read_stdout(['/usr/bin/sw_vers','-productVersion']) 353 ver = distutils.version.StrictVersion(std_out).version 354 if len(ver) < 2: 355 raise OSDetectException("invalid version string: %s"%(std_out)) 356 major, minor = ver[0:2] 357 # Source: http://en.wikipedia.org/wiki/Mac_OS_X#Versions 358 if major == 10 and minor == 4: 359 return 'tiger' 360 elif major == 10 and minor == 5: 361 return 'leopard' 362 elif major == 10 and minor == 6: 363 return 'snow' 364 elif major == 10 and minor == 7: 365 return 'lion' 366 else: 367 raise OSDetectException("unrecognized version: %s"%(std_out))
368
369 - def get_name(self):
370 return "osx"
371
372 -class OsxBrew(OSBase):
373 """ 374 Detect OS X 375 """ 376
377 - def check_presence(self):
378 # not enabled for ROS Electric. Only enabled under override. 379 return False
380
381 - def get_version(self):
382 # REP 111 this should be the code name (e.g., lion, snow, tiger) #3570 383 std_out = _read_stdout(['/usr/bin/sw_vers','-productVersion']) 384 ver = distutils.version.StrictVersion(std_out).version 385 if len(ver) < 2: 386 raise OSDetectException("invalid version string: %s"%(std_out)) 387 major, minor = ver[0:2] 388 # Source: http://en.wikipedia.org/wiki/Mac_OS_X#Versions 389 if major == 10 and minor == 4: 390 return 'tiger' 391 elif major == 10 and minor == 5: 392 return 'leopard' 393 elif major == 10 and minor == 6: 394 return 'snow' 395 elif major == 10 and minor == 7: 396 return 'lion' 397 else: 398 raise OSDetectException("unrecognized version: %s"%(std_out))
399
400 - def get_name(self):
401 return "osxbrew"
402 403 ###### END OSX SPECIALIZATION ######################## 404 405 ###### Arch SPECIALIZATION #########################
406 -class Arch(OSBase):
407 """ 408 Detect Arch Linux. 409 """ 410
411 - def check_presence(self):
412 filename = "/etc/arch-release" 413 if os.path.exists(filename): 414 return True 415 return False
416
417 - def get_version(self):
418 return ""
419
420 - def get_name(self):
421 return "arch"
422 423 ###### END Arch SPECIALIZATION ######################## 424 425 426 ###### Cygwin SPECIALIZATION #########################
427 -class Cygwin(OSBase):
428 """ 429 Detect Cygwin presence on Windows OS. 430 """
431 - def check_presence(self):
432 filename = "/usr/bin/cygwin1.dll" 433 if os.path.exists(filename): 434 return True 435 return False
436
437 - def get_version(self):
438 return _read_stdout(['uname','-r']).strip()
439
440 - def get_name(self):
441 return "cygwin"
442 443 ###### END Cygwin SPECIALIZATION ######################## 444 445 ###### Gentoo Sepcialization ###############################
446 -class Gentoo(OSBase):
447 """ 448 Detect Gentoo OS. 449 """
450 - def check_presence(self):
451 try: 452 filename = "/etc/gentoo-release" 453 if os.path.exists(filename): 454 with open(filename, 'r') as fh: 455 os_list = fh.read().split() 456 if os_list and os_list[0] == "Gentoo" and os_list[1] == "Base": 457 return True 458 except: 459 pass 460 return False
461
462 - def get_version(self):
463 try: 464 filename = "/etc/gentoo-release" 465 if os.path.exists(filename): 466 with open(filename, 'r') as fh: 467 os_list = fh.read().split() 468 if os_list[0] == "Gentoo" and os_list[1] == "Base": 469 return os_list[4] 470 except: 471 sys.stderr.write("Gentoo failed to get version\n") 472 return False 473 474 return False
475
476 - def get_name(self):
477 return "gentoo"
478 479 ###### END Gentoo Sepcialization ############################### 480 481 ###### FreeBSD SPECIALIZATION #########################
482 -class FreeBSD(OSBase):
483 """ 484 Detect FreeBSD OS. 485 """
486 - def check_presence(self):
487 try: 488 filename = "/usr/bin/uname" 489 if os.path.exists(filename): 490 std_out = _read_stdout([filename]) 491 if std_out.strip() == "FreeBSD": 492 return True 493 else: 494 return False 495 except: 496 pass#print >> sys.stderr, "FreeBSD failed to detect OS" 497 return False
498
499 - def get_version(self):
500 try: 501 filename = "/usr/bin/uname" 502 if os.path.exists(filename): 503 return _read_stdout([filename, "-r"]).strip() 504 else: 505 return False 506 except: 507 sys.stderr.write("FreeBSD failed to get version\n") 508 return False 509 510 return False
511
512 - def get_name(self):
513 return "freebsd"
514 515 ###### FreeBSD SPECIALIZATION ######################### 516 517 518 519 520 521
522 -class OSDetect:
523 """ This class will iterate over registered classes to lookup the 524 active OS and version"""
525 - def __init__(self, os_list = [Debian(), Mandriva(), Ubuntu(), Mint(), Osx(), OsxBrew(), Arch(), OpenSuse(), Fedora(), Rhel(), Gentoo(), Cygwin(), FreeBSD()]):
526 self._os_list = os_list 527 for o in self._os_list: 528 if not isinstance(o, OSBase): 529 raise OSDetectException("Class [%s] not derived from OSBase"%o.__class__.__name__) 530 531 self._os_class = None 532 self._os_name = None 533 self._os_version = None 534 535 self.detect_os()
536
537 - def add_os(self, class_ref):
538 self._os_list.append(class_ref)
539 540 # \TODO look at throwing here
541 - def detect_os(self):
542 override = OSOverride() 543 if override.check_presence(): 544 for os_class in self._os_list: 545 if os_class.get_name() == override.get_name(): 546 self._os_name = override.get_name() 547 self._os_version = override.get_version() 548 self._os_class = os_class 549 return True 550 551 for os_class in self._os_list: 552 if os_class.check_presence(): 553 self._os_name = os_class.get_name() 554 self._os_version = os_class.get_version() 555 self._os_class = os_class 556 return True 557 558 # No solution found 559 attempted_oss = [o.get_name() for o in self._os_list] 560 raise OSDetectException("Could not detect OS, tried %s"%attempted_oss) 561 return False
562
563 - def get_os(self):
564 if not self._os_class: 565 self.detect_os() 566 return self._os_class
567
568 - def get_name(self):
569 if not self._os_name: 570 self.detect_os() 571 return self._os_name
572
573 - def get_version(self):
574 if not self._os_version: 575 not self.detect_os() 576 return self._os_version
577