bonding: exclude drupal when updating
[tests.git] / system / TestBonding.py
1 """
2 Utilities to create a setup made of 2 different builds
3 read : 2 different node flavours 
4 so that each myplc knows about the nodeflavour/slicefamily supported
5 by the other one
6 ---
7 This would be the basics for running tests on multi-node myplc, 
8 in particular for node upgrades
9 """
10
11 #################### WARNING
12
13 # this feature relies on a few assumptions that need to be taken care of
14 # more or less manually; this is based on the onelab.eu setup
15
16 # (*) the build host is expected to have /root/git-build.sh reasonably up-to-date
17 # with our build module, so we can locate partial-repo.sh
18 # this utility needs to be run on the build host so we can point at a PARTIAL-RPMS
19 # sub-repo that exposes the
20 # bootcd/bootstraps/ and the like rpms from one flavour to another
21
22 # a utility to create a bonding_plc_spec from
23 # a plc_spec and just a buildname
24
25 def onelab_bonding_spec (buildname):
26
27     # essentially generic ..
28     buildname      = buildname
29     
30     with open ("../{}/arg-fcdistro".format(buildname)) as input:
31         fcdistro   = input.read().strip()
32     with open ("../{}/arg-pldistro".format(buildname)) as input:
33         pldistro   = input.read().strip()
34     with open ("../{}/arg-ips-bplc".format(buildname)) as input:
35         plc_box    = input.read().strip().split()[0]
36     # e.g. http://build.onelab.eu/onelab//2015.03.15--f14/RPMS/x86_64
37     with open ("../{}/arg-arch-rpms-url".format(buildname)) as input:
38         arch_rpms_url = input.read().strip()
39     arch           = arch_rpms_url.split('/')[-1]
40     build_www_host = arch_rpms_url.split('/')[2]
41     base_url       = arch_rpms_url.replace("RPMS/{}".format(arch), "PARTIAL-RPMS")
42         
43     # onelab specifics
44     build_www_git = '/root/git-build/'
45     build_www_dir  = '/build/{}/{}'.format(pldistro, buildname)
46     
47     return locals()
48
49 ####################
50 import os, os.path
51
52 import utils
53 from TestSsh import TestSsh
54
55 ####################
56 class TestBonding(object):
57
58     """
59     Holds details about a 'bonding' build
60     so we can configure the local myplc (test_plc)
61     for multi-flavour nodes and slices
62     options is a TestMain options
63     """
64     
65     def __init__(self, test_plc, bonding_spec, options):
66         """
67         test_plc is one local TestPlc instance
68         bonding_spec is a dictionary that gives details on
69         the build we want to be bonding with
70         """
71         self.test_plc = test_plc
72         self.bonding_spec = bonding_spec
73         self.options = options
74         # the local build & plc is described in options
75         # the bonding build is described in bonding_spec
76
77     def nodefamily(self):
78         return "{pldistro}-{fcdistro}-{arch}".format(**self.bonding_spec)
79         
80     def init_partial(self):
81         """
82         runs partial-repo.sh for the bonding build
83         this action takes place on the build host
84         """
85         test_ssh = TestSsh (self.bonding_spec['build_www_host'])
86         command = "{build_www_git}/partial-repo.sh -i {build_www_dir}".\
87                   format(**self.bonding_spec)
88                          
89         return test_ssh.run (command, dry_run = self.options.dry_run) == 0
90         
91
92     def add_yum(self):
93         """
94         creates a separate yum.repo file in the myplc box
95         where our own build runs, and that points at the partial
96         repo for the bonding build
97         """
98
99         # create a .repo file locally
100         yumrepo_contents = """
101 [{buildname}]
102 name=Partial repo from bonding build {buildname}
103 baseurl={base_url}
104 enabled=1
105 gpgcheck=0
106 """.format(**self.bonding_spec)
107
108         yumrepo_local = '{buildname}-partial.repo'.\
109                         format(**self.bonding_spec)
110         with open(yumrepo_local, 'w') as yumrepo_file:
111             yumrepo_file.write(yumrepo_contents)
112         utils.header("(Over)wrote {}".format(yumrepo_local))
113
114         # push onto our myplc instance
115         test_ssh = TestSsh (self.test_plc.vserverip)
116
117         yumrepo_remote = '/etc/yum.repos.d/{bonding_buildname}-partial.repo'.\
118                          format(bonding_buildname = self.bonding_spec['buildname'])
119
120         if test_ssh.copy_abs (yumrepo_local, yumrepo_remote,
121                               dry_run=self.options.dry_run) != 0:
122             return False
123
124         # xxx TODO looks like drupal also needs to be excluded
125         # from the 2 entries in building.repo
126         # otherwise subsequent yum update calls will fail
127
128         return True
129         
130     def install_rpms(self):
131         """
132         once the 2 operations above have been performed, we can 
133         actually install the various rpms that provide support for the 
134         nodeflavour/slicefamily offered byt the bonding build to our own build
135         """
136
137         test_ssh = TestSsh (self.test_plc.vserverip)
138         
139         command1 = "yum -y update --exclude drupal"
140         if test_ssh.run (command1, dry_run = self.options.dry_run) != 0:
141             return False
142
143         nodefamily = self.nodefamily()
144         extra_list = [ 'bootcd', 'nodeimage', 'noderepo' ]
145
146         extra_rpms = [ "{}-{}".format(rpm, nodefamily) for rpm in extra_list]
147
148         command2 = "yum -y install " + " ".join(extra_rpms) 
149         if test_ssh.run (command2, dry_run = self.options.dry_run) != 0:
150             return False
151
152         command3 = "/etc/plc.d/packages force"
153         if test_ssh.run (command3, dry_run = self.options.dry_run) != 0:
154             return False
155
156         return True
157
158 ### probably obsolete already    
159 if __name__ == '__main__':
160
161     from TestPlc import TestPlc    
162
163     from config_default import sample_test_plc_spec
164     test_plc_spec = sample_test_plc_spec()
165     test_plc = TestPlc (test_plc_spec)
166     test_plc.show()
167
168     print(test_plc.host_box)
169
170     from argparse import ArgumentParser
171     parser = ArgumentParser()
172     parser.add_argument ("-n", "--dry-run", dest='dry_run', default=False,
173                          action='store_true', help="dry run")
174     parser.add_argument ("build_name")
175     args = parser.parse_args()
176
177     test_bonding = TestBonding (test_plc,
178                                 onelab_bonding_spec(args.build_name),
179                                 dry_run = args.dry_run)
180
181     test_bonding.bond ()
182