Merge lp:~niedbalski/juju-deployer/fix-lp1454720 into lp:juju-deployer

Proposed by Jorge Niedbalski
Status: Merged
Merged at revision: 145
Proposed branch: lp:~niedbalski/juju-deployer/fix-lp1454720
Merge into: lp:juju-deployer
Diff against target: 187 lines (+110/-12)
4 files modified
deployer/action/importer.py (+40/-11)
deployer/deployment.py (+7/-1)
deployer/tests/test_data/v4/container-existing-machine.yaml (+42/-0)
deployer/tests/test_importer.py (+21/-0)
To merge this branch: bzr merge lp:~niedbalski/juju-deployer/fix-lp1454720
Reviewer Review Type Date Requested Status
Tim Van Steenburgh (community) Approve
Review via email: mp+259002@code.launchpad.net

Description of the change

Not forcefully create a machine if already exists on the environment.

To post a comment you must log in.
147. By Jorge Niedbalski

Added docstrings

Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

LGTM, thanks Jorge! One inline comment for cleanup.

review: Approve
148. By Jorge Niedbalski

Addressed @tvan review

Revision history for this message
Jorge Niedbalski (niedbalski) wrote :

@tvansteenburgh

Thanks for reviewing. I just Re-submitted using your recommendations

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'deployer/action/importer.py'
2--- deployer/action/importer.py 2015-03-24 17:38:56 +0000
3+++ deployer/action/importer.py 2015-05-13 19:46:10 +0000
4@@ -56,6 +56,11 @@
5 else:
6 self.env.add_units(svc.name, abs(delta))
7
8+ def machine_exists(self, id):
9+ """Checks if the given id exists on the current environment."""
10+ return int(id) in map(int,
11+ self.env.status().get('machines', {}).keys())
12+
13 def create_machines(self):
14 """Create machines as specified in the machine spec in the bundle.
15
16@@ -70,26 +75,42 @@
17 foo: bar
18 1:
19 constraints: "mem=4G"
20-
21+
22 This method first attempts to create any machines in the 'machines'
23 section of the bundle specification with the given constraints and
24 annotations. Then, if there are any machines requested for containers
25 in the style of <container type>:new, it creates those machines and
26- adds them to the machines map."""
27+ adds them to the machines map.
28+
29+ If the machine already exists on the environment, then the new machine
30+ creation is skipped.
31+ """
32 machines = self.deployment.get_machines()
33+
34 if machines:
35 self.log.info("Creating machines...")
36 for machine_name, spec in machines.items():
37- self.machines[machine_name] = self.env.add_machine(
38- series=spec.get('series',
39+ if self.machine_exists(machine_name):
40+ self.log.info(
41+ """Machine %s already exists on environment, """
42+ """skipping creation""" % machine_name)
43+ self.machines[machine_name] = self.deployment.get_machine(
44+ machine_name)
45+ else:
46+ self.log.info("Machine %s will be created" % machine_name)
47+ self.machines[machine_name] = self.env.add_machine(
48+ series=spec.get('series',
49 self.deployment.data['series']),
50 constraints=spec.get('constraints'))
51- annotations = spec.get('annotations')
52- if annotations:
53- self.env.set_annotation(
54- self.machines[machine_name],
55- annotations,
56- entity_type='machine')
57+
58+ if isinstance(spec, dict):
59+ annotations = spec.get('annotations')
60+ if annotations:
61+ self.env.set_annotation(
62+ self.machines[machine_name],
63+ annotations,
64+ entity_type='machine')
65+
66 # In the case of <container type>:new, we need to create a machine
67 # before creating the container on which the service will be
68 # deployed. This is stored in the machines map which will be used
69@@ -97,7 +118,15 @@
70 for service in self.deployment.get_services():
71 placement = self.deployment.get_unit_placement(service, None)
72 for container_host in placement.get_new_machines_for_containers():
73- self.machines[container_host] = self.env.add_machine()
74+ if self.machine_exists(machine_name):
75+ self.log.info("Machine %s already exists,"
76+ "skipping creation" % machine_name)
77+ self.machines[container_host] = self.deployment.get_machine(
78+ container_host)
79+ else:
80+ self.log.info("A new container will be created"
81+ "on machine: %s" % container_host)
82+ self.machines[container_host] = self.env.add_machine()
83 self.deployment.set_machines(machines)
84
85 def get_charms(self):
86
87=== modified file 'deployer/deployment.py'
88--- deployer/deployment.py 2015-03-18 18:19:43 +0000
89+++ deployer/deployment.py 2015-05-13 19:46:10 +0000
90@@ -59,6 +59,12 @@
91 """
92 self.machines = machines
93
94+ def get_machine(self, id):
95+ """Return a dict containing machine options
96+ None is returned if the machine doesn't exists in
97+ the bundle YAML."""
98+ return self.get_machines().get(id, None)
99+
100 def get_machines(self):
101 """Return a dict mapping machine names to machine options.
102
103@@ -77,7 +83,7 @@
104 @staticmethod
105 def _machines_placement_sort(svc_a, svc_b):
106 """Sort machines with machine placement in mind.
107-
108+
109 If svc_a is colocated alongside svc_b, svc_b needs to be deployed
110 first, so that it exists by the time svc_a is deployed, and vice
111 versa; this sorts first based on this fact, then secondly based on
112
113=== added file 'deployer/tests/test_data/v4/container-existing-machine.yaml'
114--- deployer/tests/test_data/v4/container-existing-machine.yaml 1970-01-01 00:00:00 +0000
115+++ deployer/tests/test_data/v4/container-existing-machine.yaml 2015-05-13 19:46:10 +0000
116@@ -0,0 +1,42 @@
117+services:
118+ mediawiki:
119+ charm: cs:precise/mediawiki-10
120+ num_units: 1
121+ options:
122+ debug: false
123+ name: Please set name of wiki
124+ skin: vector
125+ annotations:
126+ gui-x: "609"
127+ gui-y: "-15"
128+ to:
129+ - "1"
130+ mysql:
131+ charm: cs:precise/mysql-28
132+ num_units: 1
133+ options:
134+ binlog-format: MIXED
135+ block-size: 5
136+ dataset-size: 80%
137+ flavor: distro
138+ ha-bindiface: eth0
139+ ha-mcastport: 5411
140+ max-connections: -1
141+ preferred-storage-engine: InnoDB
142+ query-cache-size: -1
143+ query-cache-type: "OFF"
144+ rbd-name: mysql1
145+ tuning-level: safest
146+ vip_cidr: 24
147+ vip_iface: eth0
148+ annotations:
149+ gui-x: "610"
150+ gui-y: "255"
151+ to:
152+ - "lxc:1"
153+series: precise
154+relations:
155+- - mediawiki:db
156+ - mysql:db
157+machines:
158+ 1: 1
159
160=== modified file 'deployer/tests/test_importer.py'
161--- deployer/tests/test_importer.py 2015-03-24 17:38:56 +0000
162+++ deployer/tests/test_importer.py 2015-05-13 19:46:10 +0000
163@@ -94,3 +94,24 @@
164 self.assertEqual(
165 env.add_machine.call_args_list[1][1],
166 {'series': 'trusty', 'constraints': 'mem=512M'})
167+
168+ @skip_if_offline
169+ @mock.patch('deployer.action.importer.time')
170+ def test_importer_existing_machine(self, mock_time):
171+ self.options.configs = [
172+ os.path.join(self.test_data_dir, 'v4',
173+ 'container-existing-machine.yaml')]
174+ stack = ConfigStack(self.options.configs)
175+ deploy = stack.get(self.options.configs[0])
176+ env = mock.MagicMock()
177+
178+ config = {'status.return_value.get.return_value': {
179+ 1: {}
180+ }}
181+
182+ env.configure_mock(**config)
183+
184+ importer = Importer(env, deploy, self.options)
185+ importer.run()
186+
187+ env.add_machine.assert_not_called()

Subscribers

People subscribed via source and target branches