64 |
64 |
self.write_count = 0
|
65 |
65 |
self._lock = _config_lock
|
66 |
66 |
self._config_data = None
|
67 |
|
self._config_time = None
|
68 |
|
self._config_size = None
|
69 |
|
self._config_inode = None
|
70 |
67 |
self._offline = offline
|
71 |
68 |
if cfg_file is None:
|
72 |
69 |
self._cfg_file = constants.CLUSTER_CONF_FILE
|
... | ... | |
79 |
76 |
# better to raise an error before starting to modify the config
|
80 |
77 |
# file than after it was modified
|
81 |
78 |
self._my_hostname = utils.HostInfo().name
|
|
79 |
self._OpenConfig()
|
82 |
80 |
|
83 |
81 |
# this method needs to be static, so that we can call it on the class
|
84 |
82 |
@staticmethod
|
... | ... | |
95 |
93 |
This should check the current instances for duplicates.
|
96 |
94 |
|
97 |
95 |
"""
|
98 |
|
self._OpenConfig()
|
99 |
96 |
prefix = self._config_data.cluster.mac_prefix
|
100 |
97 |
all_macs = self._AllMACs()
|
101 |
98 |
retries = 64
|
... | ... | |
119 |
116 |
check for potential collisions elsewhere.
|
120 |
117 |
|
121 |
118 |
"""
|
122 |
|
self._OpenConfig()
|
123 |
119 |
all_macs = self._AllMACs()
|
124 |
120 |
return mac in all_macs
|
125 |
121 |
|
... | ... | |
130 |
126 |
This checks the current disks for duplicates.
|
131 |
127 |
|
132 |
128 |
"""
|
133 |
|
self._OpenConfig()
|
134 |
129 |
all_secrets = self._AllDRBDSecrets()
|
135 |
130 |
retries = 64
|
136 |
131 |
while retries > 0:
|
... | ... | |
146 |
141 |
"""Compute the list of all LVs.
|
147 |
142 |
|
148 |
143 |
"""
|
149 |
|
self._OpenConfig()
|
150 |
144 |
lvnames = set()
|
151 |
145 |
for instance in self._config_data.instances.values():
|
152 |
146 |
node_data = instance.MapLVsByNode()
|
... | ... | |
192 |
186 |
"""Return all MACs present in the config.
|
193 |
187 |
|
194 |
188 |
"""
|
195 |
|
self._OpenConfig()
|
196 |
|
|
197 |
189 |
result = []
|
198 |
190 |
for instance in self._config_data.instances.values():
|
199 |
191 |
for nic in instance.nics:
|
... | ... | |
224 |
216 |
def VerifyConfig(self):
|
225 |
217 |
"""Stub verify function.
|
226 |
218 |
"""
|
227 |
|
self._OpenConfig()
|
228 |
|
|
229 |
219 |
result = []
|
230 |
220 |
seen_macs = []
|
231 |
221 |
ports = {}
|
... | ... | |
343 |
333 |
if not isinstance(port, int):
|
344 |
334 |
raise errors.ProgrammerError("Invalid type passed for port")
|
345 |
335 |
|
346 |
|
self._OpenConfig()
|
347 |
336 |
self._config_data.cluster.tcpudp_port_pool.add(port)
|
348 |
337 |
self._WriteConfig()
|
349 |
338 |
|
... | ... | |
352 |
341 |
"""Returns a copy of the current port list.
|
353 |
342 |
|
354 |
343 |
"""
|
355 |
|
self._OpenConfig()
|
356 |
344 |
return self._config_data.cluster.tcpudp_port_pool.copy()
|
357 |
345 |
|
358 |
346 |
@locking.ssynchronized(_config_lock)
|
... | ... | |
364 |
352 |
highest_used_port).
|
365 |
353 |
|
366 |
354 |
"""
|
367 |
|
self._OpenConfig()
|
368 |
|
|
369 |
355 |
# If there are TCP/IP ports configured, we use them first.
|
370 |
356 |
if self._config_data.cluster.tcpudp_port_pool:
|
371 |
357 |
port = self._config_data.cluster.tcpudp_port_pool.pop()
|
... | ... | |
422 |
408 |
order as the passed nodes.
|
423 |
409 |
|
424 |
410 |
"""
|
425 |
|
self._OpenConfig()
|
426 |
|
|
427 |
411 |
d_map = self._ComputeDRBDMap(instance)
|
428 |
412 |
result = []
|
429 |
413 |
for nname in nodes:
|
... | ... | |
484 |
468 |
@return: Cluster name
|
485 |
469 |
|
486 |
470 |
"""
|
487 |
|
self._OpenConfig()
|
488 |
471 |
return self._config_data.cluster.cluster_name
|
489 |
472 |
|
490 |
473 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
494 |
477 |
@return: Master hostname
|
495 |
478 |
|
496 |
479 |
"""
|
497 |
|
self._OpenConfig()
|
498 |
480 |
return self._config_data.cluster.master_node
|
499 |
481 |
|
500 |
482 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
504 |
486 |
@return: Master IP
|
505 |
487 |
|
506 |
488 |
"""
|
507 |
|
self._OpenConfig()
|
508 |
489 |
return self._config_data.cluster.master_ip
|
509 |
490 |
|
510 |
491 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
512 |
493 |
"""Get the master network device for this cluster.
|
513 |
494 |
|
514 |
495 |
"""
|
515 |
|
self._OpenConfig()
|
516 |
496 |
return self._config_data.cluster.master_netdev
|
517 |
497 |
|
518 |
498 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
520 |
500 |
"""Get the file storage dir for this cluster.
|
521 |
501 |
|
522 |
502 |
"""
|
523 |
|
self._OpenConfig()
|
524 |
503 |
return self._config_data.cluster.file_storage_dir
|
525 |
504 |
|
526 |
505 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
528 |
507 |
"""Get the hypervisor type for this cluster.
|
529 |
508 |
|
530 |
509 |
"""
|
531 |
|
self._OpenConfig()
|
532 |
510 |
return self._config_data.cluster.hypervisor
|
533 |
511 |
|
534 |
512 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
539 |
517 |
|
540 |
518 |
Returns: rsa hostkey
|
541 |
519 |
"""
|
542 |
|
self._OpenConfig()
|
543 |
520 |
return self._config_data.cluster.rsahostkeypub
|
544 |
521 |
|
545 |
522 |
@locking.ssynchronized(_config_lock)
|
... | ... | |
558 |
535 |
all_lvs = instance.MapLVsByNode()
|
559 |
536 |
logging.info("Instance '%s' DISK_LAYOUT: %s", instance.name, all_lvs)
|
560 |
537 |
|
561 |
|
self._OpenConfig()
|
562 |
538 |
instance.serial_no = 1
|
563 |
539 |
self._config_data.instances[instance.name] = instance
|
564 |
540 |
self._config_data.cluster.serial_no += 1
|
... | ... | |
572 |
548 |
raise errors.ProgrammerError("Invalid status '%s' passed to"
|
573 |
549 |
" ConfigWriter._SetInstanceStatus()" %
|
574 |
550 |
status)
|
575 |
|
self._OpenConfig()
|
576 |
551 |
|
577 |
552 |
if instance_name not in self._config_data.instances:
|
578 |
553 |
raise errors.ConfigurationError("Unknown instance '%s'" %
|
... | ... | |
595 |
570 |
"""Remove the instance from the configuration.
|
596 |
571 |
|
597 |
572 |
"""
|
598 |
|
self._OpenConfig()
|
599 |
|
|
600 |
573 |
if instance_name not in self._config_data.instances:
|
601 |
574 |
raise errors.ConfigurationError("Unknown instance '%s'" % instance_name)
|
602 |
575 |
del self._config_data.instances[instance_name]
|
... | ... | |
612 |
585 |
rename.
|
613 |
586 |
|
614 |
587 |
"""
|
615 |
|
self._OpenConfig()
|
616 |
588 |
if old_name not in self._config_data.instances:
|
617 |
589 |
raise errors.ConfigurationError("Unknown instance '%s'" % old_name)
|
618 |
590 |
inst = self._config_data.instances[old_name]
|
... | ... | |
645 |
617 |
This function is for internal use, when the config lock is already held.
|
646 |
618 |
|
647 |
619 |
"""
|
648 |
|
self._OpenConfig()
|
649 |
620 |
return self._config_data.instances.keys()
|
650 |
621 |
|
651 |
622 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
664 |
635 |
"""Attempt to expand an incomplete instance name.
|
665 |
636 |
|
666 |
637 |
"""
|
667 |
|
self._OpenConfig()
|
668 |
|
|
669 |
638 |
return utils.MatchNameComponent(short_name,
|
670 |
639 |
self._config_data.instances.keys())
|
671 |
640 |
|
... | ... | |
675 |
644 |
This function is for internal use, when the config lock is already held.
|
676 |
645 |
|
677 |
646 |
"""
|
678 |
|
self._OpenConfig()
|
679 |
|
|
680 |
647 |
if instance_name not in self._config_data.instances:
|
681 |
648 |
return None
|
682 |
649 |
|
... | ... | |
721 |
688 |
"""
|
722 |
689 |
logging.info("Adding node %s to configuration" % node.name)
|
723 |
690 |
|
724 |
|
self._OpenConfig()
|
725 |
691 |
node.serial_no = 1
|
726 |
692 |
self._config_data.nodes[node.name] = node
|
727 |
693 |
self._config_data.cluster.serial_no += 1
|
... | ... | |
734 |
700 |
"""
|
735 |
701 |
logging.info("Removing node %s from configuration" % node_name)
|
736 |
702 |
|
737 |
|
self._OpenConfig()
|
738 |
703 |
if node_name not in self._config_data.nodes:
|
739 |
704 |
raise errors.ConfigurationError("Unknown node '%s'" % node_name)
|
740 |
705 |
|
... | ... | |
747 |
712 |
"""Attempt to expand an incomplete instance name.
|
748 |
713 |
|
749 |
714 |
"""
|
750 |
|
self._OpenConfig()
|
751 |
|
|
752 |
715 |
return utils.MatchNameComponent(short_name,
|
753 |
716 |
self._config_data.nodes.keys())
|
754 |
717 |
|
... | ... | |
762 |
725 |
Returns: the node object
|
763 |
726 |
|
764 |
727 |
"""
|
765 |
|
self._OpenConfig()
|
766 |
|
|
767 |
728 |
if node_name not in self._config_data.nodes:
|
768 |
729 |
return None
|
769 |
730 |
|
... | ... | |
787 |
748 |
This function is for internal use, when the config lock is already held.
|
788 |
749 |
|
789 |
750 |
"""
|
790 |
|
self._OpenConfig()
|
791 |
751 |
return self._config_data.nodes.keys()
|
792 |
752 |
|
793 |
753 |
|
... | ... | |
825 |
785 |
file, since de-serialisation could be slow.
|
826 |
786 |
|
827 |
787 |
"""
|
828 |
|
try:
|
829 |
|
st = os.stat(self._cfg_file)
|
830 |
|
except OSError, err:
|
831 |
|
raise errors.ConfigurationError("Can't stat config file: %s" % err)
|
832 |
|
if (self._config_data is not None and
|
833 |
|
self._config_time is not None and
|
834 |
|
self._config_time == st.st_mtime and
|
835 |
|
self._config_size == st.st_size and
|
836 |
|
self._config_inode == st.st_ino):
|
837 |
|
# data is current, so skip loading of config file
|
838 |
|
return
|
839 |
|
|
840 |
788 |
f = open(self._cfg_file, 'r')
|
841 |
789 |
try:
|
842 |
790 |
try:
|
... | ... | |
854 |
802 |
raise errors.ConfigurationError("Incomplete configuration"
|
855 |
803 |
" (missing cluster.rsahostkeypub)")
|
856 |
804 |
self._config_data = data
|
857 |
|
self._config_time = st.st_mtime
|
858 |
|
self._config_size = st.st_size
|
859 |
|
self._config_inode = st.st_ino
|
860 |
805 |
|
861 |
806 |
def _DistributeConfig(self):
|
862 |
807 |
"""Distribute the configuration to the other nodes.
|
... | ... | |
903 |
848 |
# we don't need to do os.close(fd) as f.close() did it
|
904 |
849 |
os.rename(name, destination)
|
905 |
850 |
self.write_count += 1
|
906 |
|
# re-set our cache as not to re-read the config file
|
907 |
|
try:
|
908 |
|
st = os.stat(destination)
|
909 |
|
except OSError, err:
|
910 |
|
raise errors.ConfigurationError("Can't stat config file: %s" % err)
|
911 |
|
self._config_time = st.st_mtime
|
912 |
|
self._config_size = st.st_size
|
913 |
|
self._config_inode = st.st_ino
|
|
851 |
|
914 |
852 |
# and redistribute the config file
|
915 |
853 |
self._DistributeConfig()
|
916 |
854 |
|
... | ... | |
945 |
883 |
"""Return the volume group name.
|
946 |
884 |
|
947 |
885 |
"""
|
948 |
|
self._OpenConfig()
|
949 |
886 |
return self._config_data.cluster.volume_group_name
|
950 |
887 |
|
951 |
888 |
@locking.ssynchronized(_config_lock)
|
... | ... | |
953 |
890 |
"""Set the volume group name.
|
954 |
891 |
|
955 |
892 |
"""
|
956 |
|
self._OpenConfig()
|
957 |
893 |
self._config_data.cluster.volume_group_name = vg_name
|
958 |
894 |
self._config_data.cluster.serial_no += 1
|
959 |
895 |
self._WriteConfig()
|
... | ... | |
963 |
899 |
"""Return the default bridge.
|
964 |
900 |
|
965 |
901 |
"""
|
966 |
|
self._OpenConfig()
|
967 |
902 |
return self._config_data.cluster.default_bridge
|
968 |
903 |
|
969 |
904 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
971 |
906 |
"""Return the mac prefix.
|
972 |
907 |
|
973 |
908 |
"""
|
974 |
|
self._OpenConfig()
|
975 |
909 |
return self._config_data.cluster.mac_prefix
|
976 |
910 |
|
977 |
911 |
@locking.ssynchronized(_config_lock, shared=1)
|
... | ... | |
982 |
916 |
the cluster object
|
983 |
917 |
|
984 |
918 |
"""
|
985 |
|
self._OpenConfig()
|
986 |
|
|
987 |
919 |
return self._config_data.cluster
|
988 |
920 |
|
989 |
921 |
@locking.ssynchronized(_config_lock)
|